diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index ff583e2..5df1863 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -8,6 +8,8 @@ set(SLIC3R_GUI_SOURCES pchheader.hpp GUI/Printer/PrinterFileSystem.cpp GUI/Printer/PrinterFileSystem.h + GUI/Widgets/AnimaController.hpp + GUI/Widgets/AnimaController.cpp GUI/Widgets/AxisCtrlButton.cpp GUI/Widgets/AxisCtrlButton.hpp GUI/Widgets/Button.cpp @@ -450,6 +452,8 @@ set(SLIC3R_GUI_SOURCES GUI/ModelMall.cpp GUI/SelectMachine.hpp GUI/SelectMachine.cpp + GUI/PrePrintChecker.hpp + GUI/PrePrintChecker.cpp GUI/SelectMachinePop.hpp GUI/SelectMachinePop.cpp GUI/SendToPrinter.hpp @@ -537,6 +541,8 @@ set(SLIC3R_GUI_SOURCES Utils/NetworkAgent.hpp Utils/MKS.hpp Utils/MKS.cpp + Utils/CpuMemory.cpp + Utils/CpuMemory.hpp Utils/Duet.cpp Utils/Duet.hpp Utils/FlashAir.cpp diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index c15ca90..b8f5031 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -355,7 +355,7 @@ void GLIndexedVertexArray::render( const float GLVolume::SinkingContours::HalfWidth = 0.25f; -void GLVolume::SinkingContours::render() +void GLVolume::SinkingContours::render(const GUI::Camera &camera, Model &model) { const auto& shader = GUI::wxGetApp().get_shader("flat"); if (!shader) { @@ -364,9 +364,7 @@ void GLVolume::SinkingContours::render() GUI::wxGetApp().bind_shader(shader); - update(); - - const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera(); + update(model); shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_shift)); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); m_model.render_geometry(); @@ -374,11 +372,9 @@ void GLVolume::SinkingContours::render() GUI::wxGetApp().unbind_shader(); } -void GLVolume::SinkingContours::update() +void GLVolume::SinkingContours::update(Model &model) { int object_idx = m_parent.object_idx(); - Model& model = GUI::wxGetApp().plater()->model(); - if (0 <= object_idx && object_idx < (int)model.objects.size() && m_parent.is_sinking() && !m_parent.is_below_printbed()) { const BoundingBoxf3& box = m_parent.transformed_convex_hull_bounding_box(); if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) { @@ -464,10 +460,23 @@ Vec2f calc_pt_in_screen(const Vec3d &pt, const Matrix4d &view_proj_mat, int win LOD_LEVEL calc_volume_box_in_screen_bigger_than_threshold(const BoundingBoxf3 &v_box_in_world, const Matrix4d &view_proj_mat, int window_width, int window_height) { - auto s_min = calc_pt_in_screen(v_box_in_world.min, view_proj_mat, window_width, window_height); - auto s_max = calc_pt_in_screen(v_box_in_world.max, view_proj_mat, window_width, window_height); - auto size_x = abs(s_max.x() - s_min.x()); - auto size_y = abs(s_max.y() - s_min.y()); + auto & _min = v_box_in_world.min; + auto & _max = v_box_in_world.max; + std::array src_vertices; + src_vertices[0] = _min; + src_vertices[1] = Vec3d(_max.x(), _min.y(), _min.z()); + src_vertices[2] = Vec3d(_max.x(), _max.y(), _min.z()); + src_vertices[3] = Vec3d(_min.x(), _max.y(), _min.z()); + src_vertices[4] = Vec3d(_min.x(), _min.y(), _max.z()); + src_vertices[5] = Vec3d(_max.x(), _min.y(), _max.z()); + src_vertices[6] = _max; + src_vertices[7] = Vec3d(_min.x(), _max.y(), _max.z()); + BoundingBoxf box2d; + for (int i = 0; i < src_vertices.size(); i++) { + box2d.merge(calc_pt_in_screen(src_vertices[i], view_proj_mat, window_width, window_height).cast()); + } + auto size_x = box2d.size().x(); + auto size_y = box2d.size().y(); if (size_x >= LOD_SCREEN_MAX.x() || size_y >= LOD_SCREEN_MAX.y()) { return LOD_LEVEL::HIGH; } @@ -786,17 +795,20 @@ BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d & bounding_box().transformed(trafo); } -BoundingBoxf3 GLVolume::transformed_non_sinking_bounding_box(const Transform3d& trafo) const +BoundingBoxf3 GLVolume::transformed_non_sinking_bounding_box(const Transform3d& trafo,Model& model) const { - return GUI::wxGetApp().plater()->model().objects[object_idx()]->volumes[volume_idx()]->mesh().transformed_bounding_box(trafo, 0.0); + if (object_idx() < model.objects.size()) + return model.objects[object_idx()]->volumes[volume_idx()]->mesh().transformed_bounding_box(trafo, 0.0); + else + return {}; } -const BoundingBoxf3& GLVolume::transformed_non_sinking_bounding_box() const +const BoundingBoxf3 &GLVolume::transformed_non_sinking_bounding_box(Model &model) const { if (!m_transformed_non_sinking_bounding_box.has_value()) { std::optional* trans_box = const_cast*>(&m_transformed_non_sinking_bounding_box); const Transform3d& trafo = world_matrix(); - *trans_box = transformed_non_sinking_bounding_box(trafo); + *trans_box = transformed_non_sinking_bounding_box(trafo, model); } return *m_transformed_non_sinking_bounding_box; } @@ -838,7 +850,7 @@ void GLVolume::set_range(double min_z, double max_z) //QDS: add outline related logic //static unsigned char stencil_data[1284][2944]; -void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const std::array& body_color) const +void GLVolume::render(const GUI::Camera &camera, const std::vector> &colors, Model &model, bool with_outline, const std::array &body_color) const { if (!is_active) return; @@ -846,15 +858,14 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - auto camera = GUI::wxGetApp().plater()->get_camera(); - auto zoom = camera.get_zoom(); - Transform3d vier_mat = camera.get_view_matrix(); - Matrix4d vier_proj_mat = camera.get_projection_matrix().matrix() * vier_mat.matrix(); + auto zoom = camera.get_zoom(); + auto view_matrix = camera.get_view_matrix(); + Matrix4d vier_proj_mat = camera.get_projection_matrix().matrix() * view_matrix.matrix(); const std::array &viewport = camera.get_viewport(); // QDS: add logic for mmu segmentation rendering auto render_body = [&]() { bool color_volume = false; - ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects; + ModelObjectPtrs &model_objects = model.objects; do { if ((!printable) || object_idx() >= model_objects.size()) break; @@ -867,7 +878,6 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s if (mv->mmu_segmentation_facets.empty()) break; - std::vector> colors = GUI::wxGetApp().plater()->get_extruders_colors(); if (colors.size() == 1) { break; } @@ -895,12 +905,11 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s const auto shader = GUI::wxGetApp().get_current_shader(); if (color_volume && !picking) { - std::vector> colors = GUI::wxGetApp().plater()->get_extruders_colors(); - //when force_transparent, we need to keep the alpha + auto cp_colors = colors; if (force_native_color && (render_color[3] < 1.0)) { for (int index = 0; index < colors.size(); index ++) - colors[index][3] = render_color[3]; + cp_colors[index][3] = render_color[3]; } for (int idx = 0; idx < mmuseg_ivas.size(); idx++) { GLIndexedVertexArray* iva = &mmuseg_ivas[idx]; @@ -912,23 +921,20 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s ModelObject* mo = model_objects[object_idx()]; ModelVolume* mv = mo->volumes[volume_idx()]; int extruder_id = mv->extruder_id(); - //shader->set_uniform("uniform_color", colors[extruder_id - 1]); //to make black not too hard too see if (extruder_id <= 0) { extruder_id = 1; } - std::array new_color = adjust_color_for_rendering(colors[extruder_id - 1]); + std::array new_color = adjust_color_for_rendering(cp_colors[extruder_id - 1]); shader->set_uniform("uniform_color", new_color); } else { if (idx <= colors.size()) { - //shader->set_uniform("uniform_color", colors[idx - 1]); //to make black not too hard too see - std::array new_color = adjust_color_for_rendering(colors[idx - 1]); + std::array new_color = adjust_color_for_rendering(cp_colors[idx - 1]); shader->set_uniform("uniform_color", new_color); } else { - //shader->set_uniform("uniform_color", colors[0]); //to make black not too hard too see - std::array new_color = adjust_color_for_rendering(colors[0]); + std::array new_color = adjust_color_for_rendering(cp_colors[0]); shader->set_uniform("uniform_color", new_color); } } @@ -958,7 +964,9 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY){ m_lod_update_index = 0; LAST_CAMERA_ZOOM_VALUE = zoom; - m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); + if (!picking) { + m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); + } } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small) { render_which(indexed_vertex_array_small, shader); @@ -1085,7 +1093,9 @@ void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const s if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY) { m_lod_update_index = 0; LAST_CAMERA_ZOOM_VALUE = zoom; - m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); + if (!picking) { + m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); + } } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small && indexed_vertex_array_small->vertices_and_normals_interleaved_VBO_id > 0) { this->indexed_vertex_array_small->render(shader, this->tverts_range_lod, this->qverts_range_lod); @@ -1222,9 +1232,8 @@ bool GLVolume::is_below_printbed() const return transformed_convex_hull_bounding_box().max.z() < 0.0; } -void GLVolume::render_sinking_contours() -{ - m_sinking_contours.render(); +void GLVolume::render_sinking_contours(const GUI::Camera &camera, Model &model) { + m_sinking_contours.render(camera, model); } GLWipeTowerVolume::GLWipeTowerVolume(const std::vector>& colors) @@ -1233,7 +1242,11 @@ GLWipeTowerVolume::GLWipeTowerVolume(const std::vector>& co m_colors = colors; } -void GLWipeTowerVolume::render(const Transform3d& view_matrix, bool with_outline,const std::array &body_color) const +void GLWipeTowerVolume::render(const GUI::Camera &camera, + const std::vector> &extruder_colors, + Model &model, + bool with_outline, + const std::array &body_color) const { if (!is_active) return; @@ -1611,6 +1624,36 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo return list; } +GLVolumeWithIdAndZList volumes_to_render_for_sinking(const GLVolumePtrs & volumes, + GLVolumeCollection::ERenderType type, + const Transform3d & view_matrix) +{ + GLVolumeWithIdAndZList list; + list.reserve(volumes.size()); + + for (unsigned int i = 0; i < (unsigned int) volumes.size(); ++i) { + GLVolume *volume = volumes[i]; + bool is_transparent = (volume->render_color[3] < 1.0f); + auto tempGlwipeTowerVolume = dynamic_cast(volume); + if (tempGlwipeTowerVolume) { + continue; + } + if (!volume->selected) + continue; + list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0))); + } + + if (type == GLVolumeCollection::ERenderType::Transparent && list.size() > 1) { + for (GLVolumeWithIdAndZ &volume : list) { volume.second.second = volume.first->bounding_box().transformed(view_matrix * volume.first->world_matrix()).max(2); } + + std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ &v1, const GLVolumeWithIdAndZ &v2) -> bool { return v1.second.second < v2.second.second; }); + } else if (type == GLVolumeCollection::ERenderType::Opaque && list.size() > 1) { + std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ &v1, const GLVolumeWithIdAndZ &v2) -> bool { return v1.first->selected && !v2.first->selected; }); + } + + return list; +} + int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_support) const { const DynamicPrintConfig& glb_cfg = GUI::wxGetApp().preset_bundle->prints.get_edited_preset().config; @@ -1623,14 +1666,17 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pipeline_stage, GLVolumeCollection::ERenderType type, bool disable_cullface, - const Transform3d & view_matrix, - const Transform3d& projection_matrix, + const GUI::Camera & camera, + const std::vector>& colors, + Model& model, std::function filter_func, bool with_outline, const std::array & body_color, bool partly_inside_enable, - std::vector * printable_heights) const + std::vector * printable_heights) { + auto view_matrix = camera.get_view_matrix(); + auto projection_matrix = camera.get_projection_matrix(); GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func); if (to_render.empty()) return; @@ -1652,7 +1698,6 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip glsafe(::glEnable(GL_CULL_FACE)); } - auto camera = GUI::wxGetApp().plater()->get_camera(); for (GLVolumeWithIdAndZ& volume : to_render) { auto world_box = volume.first->transformed_bounding_box(); if (!camera.getFrustum().intersects(world_box)) { @@ -1678,7 +1723,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip if (volume.first->is_sinking() && !volume.first->is_below_printbed() && volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { GUI::wxGetApp().unbind_shader(); - volume.first->render_sinking_contours(); + volume.first->render_sinking_contours(camera, model); GUI::wxGetApp().bind_shader(shader); } } @@ -1749,12 +1794,12 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip //QDS: add outline related logic auto red_color = std::array({ 1.0f, 0.0f, 0.0f, 1.0f });//slice_error - volume.first->render(view_matrix, with_outline&& volume.first->selected, volume.first->slice_error ? red_color : body_color); + volume.first->render(camera, colors,model,with_outline && volume.first->selected, volume.first->slice_error ? red_color : body_color); } else { if (volume.first->selected) { shader->set_uniform("u_model_matrix", volume.first->world_matrix()); - volume.first->render(view_matrix, false, body_color); + volume.first->render(camera, colors, model, false, body_color); } } @@ -1775,7 +1820,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { GUI::wxGetApp().unbind_shader(); glsafe(::glDepthFunc(GL_ALWAYS)); - volume.first->render_sinking_contours(); + volume.first->render_sinking_contours(camera, model); glsafe(::glDepthFunc(GL_LESS)); GUI::wxGetApp().bind_shader(shader); } @@ -1790,7 +1835,90 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip glsafe(::glDisable(GL_BLEND)); } -bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults* object_results) const +void GLVolumeCollection::only_render_sinking(GUI::ERenderPipelineStage render_pipeline_stage, + ERenderType type, + bool disable_cullface, + const GUI::Camera & camera, + const std::vector> &colors, + Model & model, + std::function filter_func, + bool with_outline, + const std::array & body_color, + bool partly_inside_enable, + std::vector * printable_heights) +{ + auto view_matrix = camera.get_view_matrix(); + auto projection_matrix = camera.get_projection_matrix(); + GLVolumeWithIdAndZList to_render = volumes_to_render_for_sinking(volumes, type, view_matrix); + if (to_render.empty()) + return; + + const auto shader = GUI::wxGetApp().get_current_shader(); + if (shader == nullptr) + return; + + if (type == ERenderType::Transparent) { + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + } + + glsafe(::glDisable(GL_CULL_FACE)); + if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + if (m_show_sinking_contours) { + for (GLVolumeWithIdAndZ &volume : to_render) { + if (volume.first->is_sinking() && !volume.first->is_below_printbed()) { + GUI::wxGetApp().unbind_shader(); + glsafe(::glDepthFunc(GL_ALWAYS)); + volume.first->render_sinking_contours(camera, model); + glsafe(::glDepthFunc(GL_LESS)); + GUI::wxGetApp().bind_shader(shader); + } + } + } + } + + if (disable_cullface) + glsafe(::glEnable(GL_CULL_FACE)); + + if (type == ERenderType::Transparent) + glsafe(::glDisable(GL_BLEND)); +} + +bool GLVolumeCollection::check_wipe_tower_outside_state(const Slic3r::BuildVolume &build_volume, int plate_id) const +{ + for (GLVolume *volume : this->volumes) { + if (volume->is_wipe_tower) { + int wipe_tower_plate_id = volume->composite_id.object_id - 1000; + if (wipe_tower_plate_id != plate_id) + continue; + const std::vector& printable_area = build_volume.printable_area(); + Polygon printable_poly = Polygon::new_scale(printable_area); + + // multi-extruder + Polygons extruder_polys; + const std::vector> & extruder_areas = build_volume.extruder_areas(); + if (!extruder_areas.empty()) { + for (size_t i = 0; i < extruder_areas.size(); ++i) { + extruder_polys.emplace_back(Polygon::new_scale(extruder_areas[i])); + } + extruder_polys = union_(extruder_polys); + if (extruder_polys.empty()) + return false; + + printable_poly = extruder_polys[0]; + } + + const BoundingBoxf3 &bbox = volume->transformed_convex_hull_bounding_box(); + Polygon wipe_tower_polygon = bbox.polygon(true); + + Polygons diff_res = diff(wipe_tower_polygon, printable_poly); + return diff_res.empty(); + } + } + return true; +} + +bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults *object_results, Model &model) const { if (GUI::wxGetApp().plater() == NULL) { @@ -1799,15 +1927,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo return false; } - const Model& model = GUI::wxGetApp().plater()->model(); auto volume_below = [](GLVolume& volume) -> bool { return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_below_printbed(); }; // Volume is partially below the print bed, thus a pre-calculated convex hull cannot be used. auto volume_sinking = [](GLVolume& volume) -> bool { return volume.object_idx() != -1 && volume.volume_idx() != -1 && volume.is_sinking(); }; // Cached bounding box of a volume above the print bed. - auto volume_bbox = [volume_sinking](GLVolume& volume) -> BoundingBoxf3 - { return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box() : volume.transformed_convex_hull_bounding_box(); }; + auto volume_bbox = [volume_sinking ,&model](GLVolume& volume) -> BoundingBoxf3 { + return volume_sinking(volume) ? volume.transformed_non_sinking_bounding_box(model) : volume.transformed_convex_hull_bounding_box(); + }; // Cached 3D convex hull of a volume above the print bed. auto volume_convex_mesh = [volume_sinking, &model](GLVolume& volume) -> const TriangleMesh& { return volume_sinking(volume) ? model.objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : *volume.convex_hull(); }; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 6d9c033..5a12c72 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -52,7 +52,9 @@ class ModelObject; class ModelVolume; class GLShaderProgram; enum ModelInstanceEPrintVolumeState : unsigned char; - +namespace GUI { +struct Camera; +} using ModelObjectPtrs = std::vector; struct ObjectFilamentInfo { @@ -352,10 +354,10 @@ protected: public: SinkingContours(GLVolume& volume) : m_parent(volume) {} - void render(); + void render(const GUI::Camera &camera, Model &model); private: - void update(); + void update(Model &model); }; SinkingContours m_sinking_contours; @@ -574,9 +576,9 @@ public: // caching variant const BoundingBoxf3& transformed_convex_hull_bounding_box() const; // non-caching variant - BoundingBoxf3 transformed_non_sinking_bounding_box(const Transform3d& trafo) const; + BoundingBoxf3 transformed_non_sinking_bounding_box(const Transform3d &trafo, Model &model) const; // caching variant - const BoundingBoxf3& transformed_non_sinking_bounding_box() const; + const BoundingBoxf3 &transformed_non_sinking_bounding_box(Model &model) const; // convex hull const TriangleMesh* convex_hull() const { return m_convex_hull.get(); } @@ -585,7 +587,9 @@ public: void set_range(double low, double high); //QDS: add outline related logic and add virtual specifier - virtual void render(const Transform3d& view_matrix, + virtual void render(const GUI::Camera & camera, + const std::vector>& colors, + Model & model, bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f} ) const; @@ -602,7 +606,7 @@ public: bool is_sinking() const; bool is_below_printbed() const; - void render_sinking_contours(); + void render_sinking_contours(const GUI::Camera &camera,Model& model); // Return an estimate of the memory consumed by this class. size_t cpu_memory_used() const { @@ -618,7 +622,11 @@ public: class GLWipeTowerVolume : public GLVolume { public: GLWipeTowerVolume(const std::vector>& colors); - void render(const Transform3d& view_matrix, bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const override; + void render(const GUI::Camera & camera, + const std::vector> & colors, + Model & model, + bool with_outline = false, + const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const override; std::vector iva_per_colors; bool IsTransparent(); @@ -731,14 +739,25 @@ public: void render(GUI::ERenderPipelineStage render_pipeline_stage, ERenderType type, bool disable_cullface, - const Transform3d & view_matrix, - const Transform3d& projection_matrix, + const GUI::Camera & camera, + const std::vector>& colors, + Model & model, std::function filter_func = std::function(), bool with_outline = true, const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, bool partly_inside_enable = true, - std::vector * printable_heights = nullptr) const; - + std::vector * printable_heights = nullptr); + void only_render_sinking(GUI::ERenderPipelineStage render_pipeline_stage, + ERenderType type, + bool disable_cullface, + const GUI::Camera & camera, + const std::vector> &colors, + Model & model, + std::function filter_func = std::function(), + bool with_outline = true, + const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, + bool partly_inside_enable = true, + std::vector * printable_heights = nullptr); // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects // and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs. @@ -777,8 +796,9 @@ public: // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null - bool check_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state, ObjectFilamentResults* object_results) const; + bool check_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state, ObjectFilamentResults* object_results,Model& model) const; void reset_outside_state(); + bool check_wipe_tower_outside_state(const Slic3r::BuildVolume &build_volume, int plate_id) const; void update_colors_by_extruder(const DynamicPrintConfig *config, bool is_update_alpha = true); diff --git a/src/slic3r/GUI/AMSMaterialsSetting.cpp b/src/slic3r/GUI/AMSMaterialsSetting.cpp index 9659ef2..9d61282 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.cpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.cpp @@ -24,7 +24,7 @@ static std::string float_to_string_with_precision(float value, int precision = 3 } AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id) - : DPIDialog(parent, id, _L("BOX Materials Setting"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) + : DPIDialog(parent, id, _L("Box Materials Setting"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) , m_color_picker_popup(ColorPickerPopup(this)) { create(); @@ -46,7 +46,7 @@ void AMSMaterialsSetting::create() m_sizer_button->Add(0, 0, 1, wxEXPAND, 0); m_button_confirm = new Button(this, _L("Confirm")); - m_btn_bg_blue = StateColor(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), + m_btn_bg_blue = StateColor(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_confirm->SetBackgroundColor(m_btn_bg_blue); m_button_confirm->SetBorderColor(wxColour(68, 121, 251)); @@ -414,21 +414,23 @@ void AMSMaterialsSetting::update() { if (obj) { update_widgets(); - if (obj->is_in_printing() || obj->can_resume()) { - enable_confirm_button(false); - } else { - enable_confirm_button(true); - } + update_filament_editing(obj->is_in_printing() || obj->can_resume()); } } -void AMSMaterialsSetting::enable_confirm_button(bool en) +void AMSMaterialsSetting::update_filament_editing(bool is_printing) { - if (!en) { + if (is_printing) { + m_comboBox_filament->Enable(obj->is_support_filament_setting_inprinting); + m_comboBox_cali_result->Enable(obj->is_support_filament_setting_inprinting); m_button_confirm->Show(obj->is_support_filament_setting_inprinting); + m_button_reset->Show(obj->is_support_filament_setting_inprinting); } else { - m_button_confirm->Show(en); + m_comboBox_filament->Enable(true); + m_comboBox_cali_result->Enable(true); + m_button_reset->Show(true); + m_button_confirm->Show(true); } if (!m_is_third) { @@ -447,7 +449,7 @@ void AMSMaterialsSetting::enable_confirm_button(bool en) } m_tip_readonly->Wrap(FromDIP(380)); - m_tip_readonly->Show(!en); + m_tip_readonly->Show(is_printing); } } @@ -553,7 +555,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) if (wxGetApp().app_config->get("skip_ams_blacklist_check") != "true") { bool in_blacklist = false; std::string action; - std::string info; + wxString info; std::string filamnt_type; std::string filamnt_name; it->get_filament_type(filamnt_type); @@ -562,18 +564,18 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event) if (vendor && (vendor->values.size() > 0)) { std::string vendor_name = vendor->values[0]; - DeviceManager::check_filaments_in_blacklist(obj->printer_type, vendor_name, filamnt_type, ams_id, slot_id, it->name, in_blacklist, action, info); + DeviceManager::check_filaments_in_blacklist(obj->printer_type, vendor_name, filamnt_type, it->filament_id, ams_id, slot_id, it->name, in_blacklist, action, info); } if (in_blacklist) { if (action == "prohibition") { - MessageDialog msg_wingow(nullptr, wxString::FromUTF8(info), _L("Error"), wxICON_WARNING | wxOK); + MessageDialog msg_wingow(nullptr, info, _L("Error"), wxICON_WARNING | wxOK); msg_wingow.ShowModal(); //m_comboBox_filament->SetSelection(m_filament_selection); return; } else if (action == "warning") { - MessageDialog msg_wingow(nullptr, wxString::FromUTF8(info), _L("Warning"), wxICON_INFORMATION | wxOK); + MessageDialog msg_wingow(nullptr, info, _L("Warning"), wxICON_INFORMATION | wxOK); msg_wingow.ShowModal(); } } @@ -820,7 +822,7 @@ bool AMSMaterialsSetting::Show(bool show) m_input_k_val->Show(); Layout(); Fit(); - wxGetApp().UpdateDarkUI(this); + wxGetApp().UpdateDlgDarkUI(this); } return DPIDialog::Show(show); } @@ -1453,7 +1455,7 @@ void ColorPicker::doRender(wxDC& dc) } if (m_show_full) { - dc.SetPen(wxPen(wxColour(0x6B6B6B))); + dc.SetPen(wxPen(wxColour("#6B6B6B"))); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawCircle(size.x / 2, size.y / 2, radius); @@ -1516,30 +1518,30 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent) :PopupWindow(parent, wxBORDER_NONE) { m_def_colors.clear(); - m_def_colors.push_back(wxColour(0xFFFFFF)); - m_def_colors.push_back(wxColour(0xfff144)); - m_def_colors.push_back(wxColour(0xDCF478)); - m_def_colors.push_back(wxColour(0x0ACC38)); - m_def_colors.push_back(wxColour(0x057748)); - m_def_colors.push_back(wxColour(0x0d6284)); - m_def_colors.push_back(wxColour(0x0EE2A0)); - m_def_colors.push_back(wxColour(0x76D9F4)); - m_def_colors.push_back(wxColour(0x46a8f9)); - m_def_colors.push_back(wxColour(0x2850E0)); - m_def_colors.push_back(wxColour(0x443089)); - m_def_colors.push_back(wxColour(0xA03CF7)); - m_def_colors.push_back(wxColour(0xF330F9)); - m_def_colors.push_back(wxColour(0xD4B1DD)); - m_def_colors.push_back(wxColour(0xf95d73)); - m_def_colors.push_back(wxColour(0xf72323)); - m_def_colors.push_back(wxColour(0x7c4b00)); - m_def_colors.push_back(wxColour(0xf98c36)); - m_def_colors.push_back(wxColour(0xfcecd6)); - m_def_colors.push_back(wxColour(0xD3C5A3)); - m_def_colors.push_back(wxColour(0xAF7933)); - m_def_colors.push_back(wxColour(0x898989)); - m_def_colors.push_back(wxColour(0xBCBCBC)); - m_def_colors.push_back(wxColour(0x161616)); + m_def_colors.push_back(wxColour("#FFFFFF")); + m_def_colors.push_back(wxColour("#fff144")); + m_def_colors.push_back(wxColour("#DCF478")); + m_def_colors.push_back(wxColour("#0ACC38")); + m_def_colors.push_back(wxColour("#057748")); + m_def_colors.push_back(wxColour("#0d6284")); + m_def_colors.push_back(wxColour("#0EE2A0")); + m_def_colors.push_back(wxColour("#76D9F4")); + m_def_colors.push_back(wxColour("#46a8f9")); + m_def_colors.push_back(wxColour("#2850E0")); + m_def_colors.push_back(wxColour("#443089")); + m_def_colors.push_back(wxColour("#A03CF7")); + m_def_colors.push_back(wxColour("#F330F9")); + m_def_colors.push_back(wxColour("#D4B1DD")); + m_def_colors.push_back(wxColour("#f95d73")); + m_def_colors.push_back(wxColour("#f72323")); + m_def_colors.push_back(wxColour("#7c4b00")); + m_def_colors.push_back(wxColour("#f98c36")); + m_def_colors.push_back(wxColour("#fcecd6")); + m_def_colors.push_back(wxColour("#D3C5A3")); + m_def_colors.push_back(wxColour("#AF7933")); + m_def_colors.push_back(wxColour("#898989")); + m_def_colors.push_back(wxColour("#BCBCBC")); + m_def_colors.push_back(wxColour("#161616")); SetBackgroundColour(wxColour(*wxWHITE)); @@ -1554,7 +1556,7 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent) m_title_ams->SetBackgroundColour(wxColour(238, 238, 238)); m_sizer_ams->Add(m_title_ams, 0, wxALL, 5); auto ams_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); - ams_line->SetBackgroundColour(wxColour(0xCECECE)); + ams_line->SetBackgroundColour(wxColour("#CECECE")); ams_line->SetMinSize(wxSize(-1, 1)); ams_line->SetMaxSize(wxSize(-1, 1)); m_sizer_ams->Add(ams_line, 1, wxALIGN_CENTER, 0); @@ -1601,7 +1603,7 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent) auto other_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); other_line->SetMinSize(wxSize(-1, 1)); other_line->SetMaxSize(wxSize(-1, 1)); - other_line->SetBackgroundColour(wxColour(0xCECECE)); + other_line->SetBackgroundColour(wxColour("#CECECE")); m_sizer_other->Add(other_line, 1, wxALIGN_CENTER, 0); //custom color @@ -1610,7 +1612,7 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent) m_title_custom->SetFont(::Label::Body_14); m_title_custom->SetBackgroundColour(wxColour(238, 238, 238)); auto custom_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); - custom_line->SetBackgroundColour(wxColour(0xCECECE)); + custom_line->SetBackgroundColour(wxColour("#CECECE")); custom_line->SetMinSize(wxSize(-1, 1)); custom_line->SetMaxSize(wxSize(-1, 1)); m_sizer_custom->Add(m_title_custom, 0, wxALL, 5); diff --git a/src/slic3r/GUI/AMSMaterialsSetting.hpp b/src/slic3r/GUI/AMSMaterialsSetting.hpp index 960516e..939604d 100644 --- a/src/slic3r/GUI/AMSMaterialsSetting.hpp +++ b/src/slic3r/GUI/AMSMaterialsSetting.hpp @@ -102,7 +102,6 @@ public: void input_min_finish(); void input_max_finish(); void update(); - void enable_confirm_button(bool en); bool Show(bool show) override; void Popup(wxString filament = wxEmptyString, wxString sn = wxEmptyString, wxString temp_min = wxEmptyString, wxString temp_max = wxEmptyString, @@ -146,6 +145,8 @@ protected: bool is_virtual_tray(); void update_widgets(); + void update_filament_editing(bool is_printing); + protected: StateColor m_btn_bg_blue; StateColor m_btn_bg_gray; diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index b1d0a9b..744fb68 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -840,7 +840,14 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt) auto left = item->GetSize(); if (pos.x > p_rect.x && pos.y > p_rect.y && pos.x < (p_rect.x + item->GetSize().x) && pos.y < (p_rect.y + item->GetSize().y)) { - if (item->m_tray_data.type == TrayType::NORMAL && !is_match_material(item->m_tray_data.filament_type)) return; + if (item->m_tray_data.type == TrayType::NORMAL) { + if (!m_ext_mapping_filatype_check && (item->m_ams_id == VIRTUAL_TRAY_MAIN_ID || item->m_ams_id == VIRTUAL_TRAY_DEPUTY_ID)) { + // Do nothing + } else { + if(!is_match_material(item->m_tray_data.filament_type)) { return; } + } + } + if (item->m_tray_data.type == TrayType::EMPTY) return; if ((m_show_type == ShowType::LEFT && item->GetParent()->GetName() == "left") || (m_show_type == ShowType::RIGHT && item->GetParent()->GetName() == "right") || @@ -1187,7 +1194,7 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& if(slot_state[i]) td.slot_id = slot_id[i]; else - td.slot_id = -1; + td.slot_id = VIRTUAL_TRAY_MAIN_ID; td.type = NORMAL; @@ -1231,16 +1238,16 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& } } - //y61 + //y61 //y67 //ext { TrayData td; td.id = 0; - td.ams_id = -1; + td.ams_id = VIRTUAL_TRAY_MAIN_ID; - td.slot_id = -1; + td.slot_id = VIRTUAL_TRAY_MAIN_ID; td.type = NORMAL; @@ -1250,6 +1257,7 @@ void AmsMapingPopup::update(MachineObject* obj, const std::vector& td.name = filament_type.back(); td.filament_type = filament_type.back(); td.ctype = TrayType::NORMAL; + m_right_extra_slot->send_win = send_win; add_ext_ams_mapping(td, m_right_extra_slot); } @@ -1389,7 +1397,7 @@ void AmsMapingPopup::add_ext_ams_mapping(TrayData tray_data, MappingItem* item) } item->Bind(wxEVT_LEFT_DOWN, [this, tray_data, item](wxMouseEvent& e) { - if (!is_match_material(tray_data.filament_type)) return; + if (m_ext_mapping_filatype_check && !is_match_material(tray_data.filament_type)) return; item->send_event(m_current_filament_id); Dismiss(); }); @@ -2224,7 +2232,7 @@ void AmsReplaceMaterialDialog::create() std::pair(wxColour(38, 46, 48), StateColor::Enabled)); - StateColor btn_bg_blue(std::pair(wxColour(54, 97, 201), StateColor::Pressed), std::pair(wxColour(68, 121, 251), StateColor::Normal)); + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 22), StateColor::Pressed), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_sizer->Add( 0, 0, 1, wxEXPAND, 0 ); m_main_sizer->Add(0,0,0, wxTOP, FromDIP(12)); diff --git a/src/slic3r/GUI/AmsMappingPopup.hpp b/src/slic3r/GUI/AmsMappingPopup.hpp index acbc638..3f22f9b 100644 --- a/src/slic3r/GUI/AmsMappingPopup.hpp +++ b/src/slic3r/GUI/AmsMappingPopup.hpp @@ -207,6 +207,7 @@ class AmsMapingPopup : public PopupWindow { bool m_use_in_sync_dialog = false; bool m_ams_remain_detect_flag = false; + bool m_ext_mapping_filatype_check = true; wxStaticText* m_title_text{ nullptr }; public: @@ -288,6 +289,8 @@ public: public: void msw_rescale(); + void EnableExtMappingFilaTypeCheck(bool to_check = true) { m_ext_mapping_filatype_check = to_check;} ; + private: ResetCallback m_reset_callback{nullptr}; std::string m_material_index; diff --git a/src/slic3r/GUI/BaseTransparentDPIFrame.cpp b/src/slic3r/GUI/BaseTransparentDPIFrame.cpp index c1d8a3a..ba91d96 100644 --- a/src/slic3r/GUI/BaseTransparentDPIFrame.cpp +++ b/src/slic3r/GUI/BaseTransparentDPIFrame.cpp @@ -66,8 +66,8 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame( bSizer_button->Add(m_checkbox, 0, wxALIGN_LEFT);*/ bSizer_button->AddStretchSpacer(1); //y59 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(23, 25, 22), StateColor::Pressed), std::pair(wxColour(43, 45, 42), StateColor::Hovered), std::pair(wxColour(23, 25, 22), StateColor::Normal)); diff --git a/src/slic3r/GUI/BindDialog.cpp b/src/slic3r/GUI/BindDialog.cpp index 7708d0e..407d59d 100644 --- a/src/slic3r/GUI/BindDialog.cpp +++ b/src/slic3r/GUI/BindDialog.cpp @@ -137,8 +137,8 @@ PingCodeBindDialog::PingCodeBindDialog(Plater* plater /*= nullptr*/) m_button_bind = new Button(request_bind_panel, _L("Confirm")); StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_bind->SetBackgroundColor(btn_bg_blue); m_button_bind->SetBorderColor(*wxWHITE); @@ -480,7 +480,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_link_Terms_title->SetFont(Label::Head_13); m_link_Terms_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_Terms_title->Wrap(FromDIP(450)); - m_link_Terms_title->SetForegroundColour(wxColour(0x4479FB)); // y96 + m_link_Terms_title->SetForegroundColour(wxColour("#4479FB")); // y96 m_link_Terms_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { wxString txt = _L("Thank you for purchasing a QIDI Tech device.Before using your QIDI Tech device, please read the termsand conditions.By clicking to agree to use your QIDI Tech device, you agree to abide by the Privacy Policy and Terms of Use(collectively, the \"Terms\"). If you do not comply with or agree to the QIDI Tech Privacy Policy, please do not use QIDI Tech equipment and services."); ConfirmBeforeSendDialog confirm_dlg(this, wxID_ANY, _L("Terms and Conditions"), ConfirmBeforeSendDialog::ButtonStyle::ONLY_CONFIRM); @@ -499,7 +499,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_link_privacy_title->SetFont(Label::Head_13); m_link_privacy_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_privacy_title->Wrap(FromDIP(450)); - m_link_privacy_title->SetForegroundColour(wxColour(0x4479FB)); + m_link_privacy_title->SetForegroundColour(wxColour("#4479FB")); m_link_privacy_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { std::string url; std::string country_code = Slic3r::GUI::wxGetApp().app_config->get_country_code(); @@ -540,7 +540,7 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_link_notice_title->SetFont(Label::Head_13); m_link_notice_title->SetMaxSize(wxSize(FromDIP(450), -1)); m_link_notice_title->Wrap(FromDIP(450)); - m_link_notice_title->SetForegroundColour(wxColour(0x4479FB)); + m_link_notice_title->SetForegroundColour(wxColour("#4479FB")); m_link_notice_title->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_HAND); }); m_link_notice_title->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCURSOR_ARROW); }); m_link_notice_title->Bind(wxEVT_LEFT_DOWN, [this](auto& e) { @@ -677,8 +677,8 @@ PingCodeBindDialog::~PingCodeBindDialog() { m_button_bind = new Button(button_panel, _L("Confirm")); StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_bind->SetBackgroundColor(btn_bg_blue); m_button_bind->SetBorderColor(*wxWHITE); @@ -1032,7 +1032,7 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/) m_sizer_button->Add(0, 0, 1, wxEXPAND, 5); m_button_unbind = new Button(this, _L("Confirm")); - StateColor btn_bg_blue(std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_unbind->SetBackgroundColor(btn_bg_blue); m_button_unbind->SetBorderColor(wxColour(68, 121, 251)); diff --git a/src/slic3r/GUI/CaliHistoryDialog.cpp b/src/slic3r/GUI/CaliHistoryDialog.cpp index d5b4d71..4340ace 100644 --- a/src/slic3r/GUI/CaliHistoryDialog.cpp +++ b/src/slic3r/GUI/CaliHistoryDialog.cpp @@ -94,7 +94,7 @@ HistoryWindow::HistoryWindow(wxWindow* parent, const std::vector& Button * mew_btn = new Button(scroll_window, _L("New")); // y96 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); mew_btn->SetBackgroundColour(*wxWHITE); mew_btn->SetBackgroundColor(btn_bg_blue); @@ -321,6 +321,7 @@ void HistoryWindow::sync_history_data() { auto title_name = new Label(m_history_data_panel, _L("Name")); title_name->SetFont(Label::Head_14); gbSizer->Add(title_name, {0, get_colume_idx(CaliColumnType::Cali_Name, curr_obj) }, {1, 1}, wxBOTTOM, FromDIP(15)); + BOOST_LOG_TRIVIAL(info) << "=====================" << title_name->GetLabelText().ToStdString(); auto title_preset_name = new Label(m_history_data_panel, _L("Filament")); title_preset_name->SetFont(Label::Head_14); @@ -365,9 +366,6 @@ void HistoryWindow::sync_history_data() { wxString preset_name = get_preset_name_by_filament_id(result.filament_id); auto preset_name_value = new Label(m_history_data_panel, preset_name); - wxString nozzle_name = get_nozzle_volume_type_name(result.nozzle_volume_type); - auto nozzle_name_label = new Label(m_history_data_panel, nozzle_name); - auto k_str = wxString::Format("%.3f", result.k_value); auto n_str = wxString::Format("%.3f", result.n_coef); auto k_value = new Label(m_history_data_panel, k_str); @@ -394,8 +392,8 @@ void HistoryWindow::sync_history_data() { }); auto edit_button = new Button(m_history_data_panel, _L("Edit")); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); edit_button->SetBackgroundColour(*wxWHITE); edit_button->SetBackgroundColor(btn_bg_blue); @@ -424,8 +422,11 @@ void HistoryWindow::sync_history_data() { gbSizer->Add(name_value, {i, get_colume_idx(CaliColumnType::Cali_Name, curr_obj)}, {1, 1}, wxBOTTOM, FromDIP(15)); gbSizer->Add(preset_name_value, {i, get_colume_idx(CaliColumnType::Cali_Filament, curr_obj)}, {1, 1}, wxBOTTOM, FromDIP(15)); - if (curr_obj && curr_obj->is_multi_extruders()) + if (curr_obj && curr_obj->is_multi_extruders()) { + wxString nozzle_name = get_nozzle_volume_type_name(result.nozzle_volume_type); + auto nozzle_name_label = new Label(m_history_data_panel, nozzle_name); gbSizer->Add(nozzle_name_label, {i, get_colume_idx(CaliColumnType::Cali_Nozzle, curr_obj)}, {1, 1}, wxBOTTOM, FromDIP(15)); + } gbSizer->Add(k_value, {i, get_colume_idx(CaliColumnType::Cali_K_Value, curr_obj)}, {1, 1}, wxBOTTOM, FromDIP(15)); //gbSizer->Add(n_value, { i, 3 }, { 1, 1 }, wxBOTTOM, FromDIP(15)); gbSizer->Add(delete_button, {i, get_colume_idx(CaliColumnType::Cali_Delete, curr_obj)}, {1, 1}, wxBOTTOM, FromDIP(15)); @@ -563,8 +564,8 @@ EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); Button* save_btn = new Button(top_panel, _L("Save")); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); save_btn->SetBackgroundColour(*wxWHITE); save_btn->SetBackgroundColor(btn_bg_blue); @@ -824,7 +825,7 @@ NewCalibrationHistoryDialog::NewCalibrationHistoryDialog(wxWindow *parent, const auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); Button * ok_btn = new Button(top_panel, _L("Ok")); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); ok_btn->SetBackgroundColour(*wxWHITE); ok_btn->SetBackgroundColor(btn_bg_blue); diff --git a/src/slic3r/GUI/CalibrationPanel.cpp b/src/slic3r/GUI/CalibrationPanel.cpp index b20635f..2a53061 100644 --- a/src/slic3r/GUI/CalibrationPanel.cpp +++ b/src/slic3r/GUI/CalibrationPanel.cpp @@ -80,7 +80,7 @@ void CalibrationPanel::create_preset_box(wxWindow* parent, wxBoxSizer* sizer_sid { if (!m_filament_choice->is_selected_physical_printer()) wxGetApp().preset_bundle->physical_printers.unselect_printer(); - std::string preset_name = m_filament_choice->GetString(selection).ToUTF8().data(); + std::string preset_name = Preset::remove_suffix_modified(m_filament_choice->GetString(selection).ToUTF8().data()); if (preset_name.find("PETG") != std::string::npos && m_tabpanel->GetSelection() == 1) { wxMessageBox("PETG filaments are not suitable for pressure advance calibration", "Warning", wxOK | wxICON_ERROR); } diff --git a/src/slic3r/GUI/CalibrationWizardPage.cpp b/src/slic3r/GUI/CalibrationWizardPage.cpp index 9565b65..7363b27 100644 --- a/src/slic3r/GUI/CalibrationWizardPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPage.cpp @@ -87,8 +87,8 @@ CaliPageButton::CaliPageButton(wxWindow* parent, CaliPageActionType type, wxStri { // y96 StateColor btn_bg_blue(std::pair(wxColour(206, 206, 206), StateColor::Disabled), - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Disabled), diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 29a549f..ec5ca27 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -87,6 +87,12 @@ void Camera::select_view(const std::string& direction) { if (direction == "iso") set_iso_orientation(); + else if (direction == "iso_1") + set_iso_orientation(ViewAngleType::Iso_1); + else if (direction == "iso_2") + set_iso_orientation(ViewAngleType::Iso_2); + else if (direction == "iso_3") + set_iso_orientation(ViewAngleType::Iso_3); else if (direction == "left") look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ()); else if (direction == "right") @@ -99,11 +105,8 @@ void Camera::select_view(const std::string& direction) look_at(m_target - m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ()); else if (direction == "rear") look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ()); - else if (direction == "topfront") + else if (direction == "topfront" || "plate") look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ()); - else if (direction == "plate") { - look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ()); - } } void Camera::select_view(ViewAngleType type) { @@ -112,6 +115,18 @@ void Camera::select_view(ViewAngleType type) select_view("iso"); break; } + case Slic3r::GUI::Camera::ViewAngleType::Iso_1: { + select_view("iso_1"); + break; + } + case Slic3r::GUI::Camera::ViewAngleType::Iso_2: { + select_view("iso_2"); + break; + } + case Slic3r::GUI::Camera::ViewAngleType::Iso_3: { + select_view("iso_3"); + break; + } case Slic3r::GUI::Camera::ViewAngleType::Top_Front: { select_view("topfront"); break; @@ -534,7 +549,6 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo { std::pair ret; auto& [near_z, far_z] = ret; - m_scene_box_radius = box.radius(); // box in eye space const BoundingBoxf3 eye_box = box.transformed(m_view_matrix); near_z = -eye_box.max(2); @@ -552,17 +566,12 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo far_z = mid_z + half_size; } - if (near_z < FrustrumMinNearZ) { + if (near_z < FrustrumMinNearZ) + { const double delta = FrustrumMinNearZ - near_z; set_distance(m_distance + delta); - m_last_scene_box_radius = m_scene_box_radius; near_z += delta; far_z += delta; - } else { - if (abs(m_last_scene_box_radius - m_scene_box_radius) > 1) { - m_last_scene_box_radius = m_scene_box_radius; - set_distance(DefaultDistance); - } } return ret; @@ -693,19 +702,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(); @@ -746,28 +742,30 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up void Camera::set_default_orientation() { // QDS modify default orientation - look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ()); - - /*m_zenit = 45.0f; - const double theta_rad = Geometry::deg2rad(-(double)m_zenit); - const double phi_rad = Geometry::deg2rad(45.0); - const double sin_theta = ::sin(theta_rad); - const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad)); - m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ()); - m_view_rotation.normalize(); - m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());*/ + select_view("topfront"); } -void Camera::set_iso_orientation() +void Camera::set_iso_orientation(ViewAngleType va_type) { - m_zenit = 45.0f; - const double theta_rad = Geometry::deg2rad(-(double)m_zenit); - const double phi_rad = Geometry::deg2rad(45.0); - const double sin_theta = ::sin(theta_rad); - const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad)); - m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ()); + if (!(va_type == ViewAngleType::Iso || va_type == ViewAngleType::Iso_1 || va_type == ViewAngleType::Iso_2 ||va_type == ViewAngleType::Iso_3)) { + return; + } + Vec3d dir = Vec3d(-0.5f, -0.5f, std::sqrt(2) / 2.f); + m_view_rotation = Eigen::AngleAxisd(Geometry::deg2rad(-45.0), Vec3d::UnitX()) * Eigen::AngleAxisd(Geometry::deg2rad(45.0), Vec3d::UnitZ()); + if (va_type == ViewAngleType::Iso_1) { + dir = Vec3d(-0.5f, 0.5f, std::sqrt(2) / 2.f); + m_view_rotation = Eigen::AngleAxisd(Geometry::deg2rad(-45.0), Vec3d::UnitX()) * Eigen::AngleAxisd(Geometry::deg2rad(135.0), Vec3d::UnitZ()); + } else if (va_type == ViewAngleType::Iso_2) { + dir = Vec3d(0.5f, 0.5f, std::sqrt(2) / 2.f); + m_view_rotation = Eigen::AngleAxisd(Geometry::deg2rad(-45.0), Vec3d::UnitX()) * Eigen::AngleAxisd(Geometry::deg2rad(225.0), Vec3d::UnitZ()); + } else if (va_type == ViewAngleType::Iso_3) { + dir = Vec3d(0.5f, -0.5f, std::sqrt(2) / 2.f); + m_view_rotation = Eigen::AngleAxisd(Geometry::deg2rad(-45.0), Vec3d::UnitX()) * Eigen::AngleAxisd(Geometry::deg2rad(315.0), Vec3d::UnitZ()); + } m_view_rotation.normalize(); + const Vec3d camera_pos = m_target + m_distance * dir; m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones()); + update_zenit(); } @@ -788,7 +786,8 @@ Vec3d Camera::validate_target(const Vec3d& target) const void Camera::update_zenit() { - m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0))); } + m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0))); +} void Camera::update_target() { Vec3d temptarget = get_position() + m_distance * get_dir_forward(); diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index c26ea73..f1a7408 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -43,6 +43,9 @@ struct Camera Rear, Count_ViewAngleType, Top_Plate,//for 3mf and Skip parts + Iso_1,//clockwise rotate 90 degrees on the basis of Iso + Iso_2,//clockwise rotate 180 degrees on the basis of Iso + Iso_3,//clockwise rotate 270 degrees on the basis of Iso }; bool requires_zoom_to_bed{ false }; //QDS @@ -67,8 +70,6 @@ private: std::pair m_frustrum_zs; BoundingBoxf3 m_scene_box; - float m_scene_box_radius{0}; - float m_last_scene_box_radius{0}; Frustum m_frustum; Vec3f m_last_eye, m_last_center, m_last_up; float m_last_near, m_last_far, m_last_aspect, m_last_fov,m_last_zoom; @@ -161,9 +162,6 @@ public: look_at(get_position(), m_target, Vec3d::UnitZ()); } - //QDS 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; } @@ -178,7 +176,7 @@ private: void set_distance(double distance); void set_default_orientation(); - void set_iso_orientation(); + void set_iso_orientation(ViewAngleType va_type = ViewAngleType::Iso); Vec3d validate_target(const Vec3d& target) const; void update_zenit(); void update_target(); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 02894b7..245f09b 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -559,6 +559,19 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con apply(config, &new_conf); is_msg_dlg_already_exist = false; } + + // layer_height shouldn't be equal to zero + float skin_depth = config->opt_float("skin_infill_depth"); + if (config->opt_float("infill_lock_depth") > skin_depth) { + const wxString msg_text = _(L("lock depth should smaller than skin depth.\nReset to 50%% of skin depth")); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); + DynamicPrintConfig new_conf = *config; + is_msg_dlg_already_exist = true; + dialog.ShowModal(); + new_conf.set_key_value("infill_lock_depth", new ConfigOptionFloat(skin_depth / 2)); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } } void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector const &keys, std::map const &configs) @@ -603,11 +616,16 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in //cross zag bool is_cross_zag = config->option>("sparse_infill_pattern")->value == InfillPattern::ipCrossZag; - toggle_line("infill_shift_step", is_cross_zag); + bool is_locked_zig = config->option>("sparse_infill_pattern")->value == InfillPattern::ipLockedZag; + + toggle_line("infill_shift_step", is_cross_zag || is_locked_zig); + for (auto el : { "skeleton_infill_density", "skin_infill_density", "infill_lock_depth", "skin_infill_depth","skin_infill_line_width", "skeleton_infill_line_width" }) + toggle_line(el, is_locked_zig); + bool is_zig_zag = config->option>("sparse_infill_pattern")->value == InfillPattern::ipZigZag; toggle_line("infill_rotate_step", is_zig_zag); - toggle_line("symmetric_infill_y_axis", is_zig_zag || is_cross_zag); + toggle_line("symmetric_infill_y_axis", is_zig_zag || is_cross_zag || is_locked_zig); bool has_spiral_vase = config->opt_bool("spiral_mode"); toggle_line("spiral_mode_smooth", has_spiral_vase); @@ -753,6 +771,7 @@ for (auto el : {"tree_support_branch_angle", "tree_support_branch_distance", "tr toggle_line(el, has_overhang_speed, variant_index); toggle_line("flush_into_objects", !is_global_config); + toggle_line("print_flow_ratio", !is_global_config); toggle_line("support_interface_not_for_body",config->opt_int("support_interface_filament")&&!config->opt_int("support_filament")); diff --git a/src/slic3r/GUI/ConnectPrinter.cpp b/src/slic3r/GUI/ConnectPrinter.cpp index a20d0bd..5a2e72e 100644 --- a/src/slic3r/GUI/ConnectPrinter.cpp +++ b/src/slic3r/GUI/ConnectPrinter.cpp @@ -54,8 +54,8 @@ ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, cons StateColor btn_bg( // y96 - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) ); diff --git a/src/slic3r/GUI/CreatePresetsDialog.cpp b/src/slic3r/GUI/CreatePresetsDialog.cpp index 4321f31..aaf59ac 100644 --- a/src/slic3r/GUI/CreatePresetsDialog.cpp +++ b/src/slic3r/GUI/CreatePresetsDialog.cpp @@ -922,7 +922,7 @@ wxBoxSizer *CreateFilamentPresetDialog::create_button_item() wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); bSizer_button->Add(0, 0, 1, wxEXPAND, 0); // y96 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_create = new Button(this, _L("Create")); @@ -1995,7 +1995,7 @@ wxBoxSizer *CreatePrinterPresetDialog::create_page1_btns_item(wxWindow *parent) wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); bSizer_button->Add(0, 0, 1, wxEXPAND, 0); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_OK = new Button(parent, _L("OK")); @@ -2666,7 +2666,7 @@ wxBoxSizer *CreatePrinterPresetDialog::create_page2_btns_item(wxWindow *parent) wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); bSizer_button->Add(0, 0, 1, wxEXPAND, 0); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), @@ -3439,7 +3439,7 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con case FILAMENT: m_button_ok = sync_user_preset_need_enabled ? new Button(this, _L("Sync user presets")) : new Button(this, _L("OK")); break; } - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), @@ -4282,7 +4282,9 @@ ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_process_preset_to_f std::unordered_map>::iterator iter = m_process_presets.find(printer_name); if (m_process_presets.end() != iter) { for (Preset *process_preset : iter->second) { - if (preset_is_not_compatible_qdt_printer(process_preset)) continue; + //y65 + //if (preset_is_not_compatible_qdt_printer(process_preset)) continue; + if (process_presets.find(process_preset->name) != process_presets.end()) continue; process_presets.insert(process_preset->name); std::string preset_path = boost::filesystem::path(process_preset->file).make_preferred().string(); @@ -4311,7 +4313,7 @@ wxBoxSizer *ExportConfigsDialog::create_button_item(wxWindow* parent) wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); bSizer_button->Add(0, 0, 1, wxEXPAND, 0); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_ok = new Button(this, _L("OK")); @@ -4880,7 +4882,7 @@ wxBoxSizer *EditFilamentPresetDialog::create_button_sizer() bSizer_button->Add(0, 0, 1, wxEXPAND, 0); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_ok_btn = new Button(this, _L("OK")); @@ -5080,7 +5082,7 @@ wxBoxSizer *CreatePresetForPrinterDialog::create_button_sizer() bSizer_button->Add(0, 0, 1, wxEXPAND, 0); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_ok_btn = new Button(this, _L("OK")); @@ -5230,7 +5232,7 @@ wxPanel *PresetTree::get_child_item(wxPanel *parent, std::shared_ptr pre StateColor flush_bd_col(std::pair(wxColour(68, 121, 251), StateColor::Pressed), std::pair(wxColour(68, 121, 251), StateColor::Hovered), std::pair(wxColour(172, 172, 172), StateColor::Normal)); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); Button *edit_preset_btn = new Button(panel, _L("Edit Preset")); diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 5386bcb..161788d 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -281,27 +281,45 @@ PrinterArch get_printer_arch_by_str(std::string arch_str) return PrinterArch::ARCH_CORE_XY; } -void check_filaments_for_vt_slot(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info) +bool check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, const std::string& filament_id, int ams_id, bool &in_blacklist, std::string &ac, wxString &info) { - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (!dev) - return; + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { + return true; + } - MachineObject *obj = dev->get_selected_machine(); - if (obj == nullptr) - return; + MachineObject *obj = dev->get_selected_machine(); + if (obj == nullptr || !obj->is_multi_extruders()) { + return true; + } - if (tag_type == "TPU" && ams_id != VIRTUAL_TRAY_MAIN_ID) { - wxString extruder_name = _L("left"); - if (obj->is_main_extruder_on_left()) { - extruder_name = _L("right"); - } - wxString info_str = wxString::Format(_L("TPU is not supported by %s extruder for this printer."), extruder_name); + Preset *printer_preset = GUI::get_printer_preset(obj); + if (!printer_preset) + return true; - ac = "prohibition"; - info = info_str.ToUTF8().data(); - in_blacklist = true; - } + ConfigOptionInts *physical_extruder_map_op = dynamic_cast(printer_preset->config.option("physical_extruder_map")); + if (!physical_extruder_map_op) + return true; + std::vector physical_extruder_maps = physical_extruder_map_op->values; + int extruder_idx = obj->get_extruder_id_by_ams_id(std::to_string(ams_id)); + for (int index = 0; index < physical_extruder_maps.size(); ++index) { + if (physical_extruder_maps[index] == extruder_idx) { + extruder_idx = index; + break; + } + } + + PresetBundle *preset_bundle = GUI::wxGetApp().preset_bundle; + std::optional filament_info = preset_bundle->get_filament_by_filament_id(filament_id, printer_preset->name); + if (filament_info.has_value() && !(filament_info->filament_printable >> extruder_idx & 1)) { + wxString extruder_name = extruder_idx == 0 ? _L("left") : _L("right"); + ac = "prohibition"; + info = (wxString::Format(_L("%s is not supported by %s extruder."), tag_type, extruder_name)).ToUTF8().data(); + in_blacklist = true; + return false; + } + + return true; } void AmsTray::update_color_from_str(std::string color) @@ -593,6 +611,13 @@ bool MachineObject::is_lan_mode_printer() return result; } +std::string MachineObject::convertToIp(long long ip) +{ + std::stringstream ss; + ss << ((ip >> 0) & 0xFF) << "." << ((ip >> 8) & 0xFF) << "." << ((ip >> 16) & 0xFF) << "." << ((ip >> 24) & 0xFF); + return ss.str(); +} + PrinterSeries MachineObject::get_printer_series() const { std::string series = DeviceManager::get_printer_series(printer_type); @@ -634,7 +659,7 @@ std::string MachineObject::get_printer_series_str() const{ return DeviceManager: void MachineObject::reload_printer_settings() { print_json.load_compatible_settings("", ""); - parse_json("{}"); + parse_json("cloud", "{}"); } //y59 @@ -741,17 +766,7 @@ MachineObject::~MachineObject() model_task = nullptr; } - if (get_slice_info_thread) { - if (get_slice_info_thread->joinable()) { - get_slice_info_thread->join(); - get_slice_info_thread = nullptr; - } - } - - if (slice_info) { - delete slice_info; - slice_info = nullptr; - } + free_slice_info(); for (auto it = amsList.begin(); it != amsList.end(); it++) { for (auto tray_it = it->second->trayList.begin(); tray_it != it->second->trayList.end(); tray_it++) { @@ -776,7 +791,9 @@ bool MachineObject::check_valid_ip() void MachineObject::_parse_print_option_ack(int option) { - xcam_auto_recovery_step_loss = ((option >> (int)PRINT_OP_AUTO_RECOVERY) & 0x01) != 0; + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { + xcam_auto_recovery_step_loss = ((option >> (int)PRINT_OP_AUTO_RECOVERY) & 0x01) != 0; + } } bool MachineObject::is_in_extrusion_cali() @@ -901,6 +918,10 @@ AmsTray *MachineObject::get_ams_tray(std::string ams_id, std::string tray_id) return nullptr; } +std::string MachineObject::get_filament_id(std::string ams_id, std::string tray_id) const { + return this->get_tray(ams_id, tray_id).setting_id; +} + void MachineObject::_parse_ams_status(int ams_status) { ams_status_sub = ams_status & 0xFF; @@ -1002,8 +1023,9 @@ int MachineObject::ams_filament_mapping( if (filaments.empty()) return -1; - // tray_index : tray_color - std::map tray_filaments; + ///////////////////////// + // Step 1: collect filaments in machine + std::map tray_filaments; // tray_index : tray_color bool left_nozzle_has_ams = false, right_nozzle_has_ams = false; //y59 @@ -1018,7 +1040,7 @@ int MachineObject::ams_filament_mapping( std::vector box_filament_infos; for (int i = 0; i < filament_colors.size(); i++) { - if (!filament_colors[i].empty()) { + if (!filament_colors[i].empty() && slot_id[i] != -1) { FilamentInfo box_fila_info; box_fila_info.color = filament_colors[i].erase(0, 1) + "FF"; box_fila_info.type = filament_type[i]; @@ -1081,6 +1103,8 @@ int MachineObject::ams_filament_mapping( } } + ///////////////////////// + // Step 2: collect the distances of filaments_in_slicing to filaments_in_machine char buffer[256]; std::vector> distance_map; @@ -1091,7 +1115,7 @@ int MachineObject::ams_filament_mapping( ::sprintf(buffer, " BOX%02d", tray->second.id+1); line += std::string(buffer); } - BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line; + BOOST_LOG_TRIVIAL(info) << "box_mapping_distance:" << line;// Print the collected filaments for (int i = 0; i < filaments.size(); i++) { std::vector rol; @@ -1138,14 +1162,20 @@ int MachineObject::ams_filament_mapping( distance_map.push_back(rol); } - // mapping algorithm + ///////////////////////// + // Step 3: do mapping algorithm + + // setup the mapping result for (int i = 0; i < filaments.size(); i++) { FilamentInfo info; - info.id = filaments[i].id; - info.tray_id = -1; + info.id = filaments[i].id; + info.tray_id = -1; + info.type = filaments[i].type; + info.filament_id = filaments[i].filament_id; result.push_back(info); } + // traverse the mapping std::set picked_src; std::set picked_tar; //y59 @@ -1156,6 +1186,8 @@ int MachineObject::ams_filament_mapping( for (int i = 0; i < distance_map.size(); i++) { if (picked_src.find(i) != picked_src.end()) continue; + + // try to mapping to different tray for (int j = 0; j < distance_map[i].size(); j++) { if (picked_tar.find(j) != picked_tar.end()) { if (distance_map[i][j].is_same_color @@ -1164,6 +1196,7 @@ int MachineObject::ams_filament_mapping( min_val = distance_map[i][j].distance; picked_src_idx = i; picked_tar_idx = j; + tray_filaments[picked_tar_idx].distance = min_val; } continue; } @@ -1174,6 +1207,7 @@ int MachineObject::ams_filament_mapping( min_val = distance_map[i][j].distance; picked_src_idx = i; picked_tar_idx = j; + tray_filaments[picked_tar_idx].distance = min_val; } else if (min_val == distance_map[i][j].distance && filaments[picked_src_idx].filament_id!= box_filament_infos[picked_src_idx].filament_id && filaments[i].filament_id == box_filament_infos[j].filament_id) { picked_src_idx = i; @@ -1181,9 +1215,27 @@ int MachineObject::ams_filament_mapping( } } } + + // take a retry to mapping to used tray + if (picked_src_idx < 0 || picked_tar_idx < 0) { + for (int j = 0; j < distance_map[i].size(); j++) { + if (distance_map[i][j].is_same_color && distance_map[i][j].is_type_match) { + if (min_val > distance_map[i][j].distance) { + min_val = distance_map[i][j].distance; + picked_src_idx = i; + picked_tar_idx = j; + tray_filaments[picked_tar_idx].distance = min_val; + } else if (min_val == distance_map[i][j].distance && filaments[picked_src_idx].filament_id != tray_filaments[picked_tar_idx].filament_id && filaments[i].filament_id == tray_filaments[j].filament_id) { + picked_src_idx = i; + picked_tar_idx = j; + } + } + } + } } + //y59 - if (picked_src_idx >= 0 && picked_tar_idx >= 0 && box_filament_infos[picked_tar_idx].slot_id != "-1") { + if (picked_src_idx >= 0 && picked_tar_idx >= 0) { result[picked_src_idx].tray_id = distance_map[k][picked_tar_idx].tray_id; result[picked_src_idx].color = box_filament_infos[picked_tar_idx].color; result[picked_src_idx].type = box_filament_infos[picked_tar_idx].type; @@ -1196,10 +1248,6 @@ int MachineObject::ams_filament_mapping( result[picked_src_idx].ams_id = box_filament_infos[picked_tar_idx].ams_id; result[picked_src_idx].slot_id = box_filament_infos[picked_tar_idx].slot_id; } - else { - FilamentInfo info; - info.tray_id = -1; - } //::sprintf(buffer, "ams_mapping, picked F(%02d) AMS(%02d), distance=%6.0f", picked_src_idx+1, picked_tar_idx+1, // distance_map[picked_src_idx][picked_tar_idx].distance); //BOOST_LOG_TRIVIAL(info) << std::string(buffer); @@ -1207,8 +1255,6 @@ int MachineObject::ams_filament_mapping( picked_tar.insert(picked_tar_idx); } - std::vector cache_map_result = result; - ////check ams mapping result //if (is_valid_mapping_result(result, true)) { // return 0; @@ -1625,9 +1671,7 @@ void MachineObject::parse_state_changed_event() void MachineObject::parse_status(int flag) { is_220V_voltage = ((flag >> 3) & 0x1) != 0; - if (xcam_auto_recovery_hold_count > 0) - xcam_auto_recovery_hold_count--; - else { + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { xcam_auto_recovery_step_loss = ((flag >> 4) & 0x1) != 0; } @@ -1640,28 +1684,25 @@ void MachineObject::parse_status(int flag) sdcard_state = MachineObject::SdcardState(get_flag_bits(flag, 8, 2)); - if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_MAX) + if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_3SEC) { ams_auto_switch_filament_flag = ((flag >> 10) & 0x1) != 0; } is_support_flow_calibration = ((flag >> 15) & 0x1) != 0; - if (this->is_series_n()) { is_support_flow_calibration = true; }/* STUDIO-11014 cover the mistake of AP at n series*/ + if (this->is_series_o()) { is_support_flow_calibration = false; } // todo: Temp modification due to incorrect machine push message for H2D is_support_pa_calibration = ((flag >> 16) & 0x1) != 0; + if (this->is_series_p()) { is_support_pa_calibration = false; } // todo: Temp modification due to incorrect machine push message for P - if (xcam_prompt_sound_hold_count > 0) - xcam_prompt_sound_hold_count--; - else { + if (time(nullptr) - xcam_prompt_sound_hold_start > HOLD_TIME_3SEC) { xcam_allow_prompt_sound = ((flag >> 17) & 0x1) != 0; } is_support_prompt_sound = ((flag >> 18) & 0x1) != 0; is_support_filament_tangle_detect = ((flag >> 19) & 0x1) != 0; - if (xcam_filament_tangle_detect_count > 0) - xcam_filament_tangle_detect_count--; - else { + if (time(nullptr) - xcam_filament_tangle_detect_hold_start > HOLD_TIME_3SEC) { xcam_filament_tangle_detect = ((flag >> 20) & 0x1) != 0; } @@ -1673,7 +1714,10 @@ void MachineObject::parse_status(int flag) is_support_user_preset = ((flag >> 22) & 0x1) != 0; is_support_nozzle_blob_detection = ((flag >> 25) & 0x1) != 0; - nozzle_blob_detection_enabled = ((flag >> 24) & 0x1) != 0; + + if (time(nullptr) - nozzle_blob_detection_hold_start > HOLD_TIME_3SEC) { + nozzle_blob_detection_enabled = ((flag >> 24) & 0x1) != 0; + } is_support_air_print_detection = ((flag >> 29) & 0x1) != 0; ams_air_print_status = ((flag >> 28) & 0x1) != 0; @@ -1836,11 +1880,11 @@ bool MachineObject::canEnableTimelapse(wxString &error_message) const if (sdcard_state != MachineObject::SdcardState::HAS_SDCARD_NORMAL) { if (sdcard_state == MachineObject::SdcardState::NO_SDCARD) { - error_message = _L("Timelapse is not supported while the SD card does not exist."); + error_message = _L("Timelapse is not supported while the storage does not exist."); } else if (sdcard_state == MachineObject::SdcardState::HAS_SDCARD_ABNORMAL) { - error_message = _L("Timelapse is not supported while the SD card is unavailable."); + error_message = _L("Timelapse is not supported while the storage is unavailable."); } else if (sdcard_state == MachineObject::SdcardState::HAS_SDCARD_READONLY) { - error_message = _L("Timelapse is not supported while the SD card is readonly."); + error_message = _L("Timelapse is not supported while the storage is readonly."); } return false; @@ -2105,6 +2149,8 @@ int MachineObject::command_task_pause() int MachineObject::command_task_resume() { + if(check_resume_condition()) return 0; + json j; j["print"]["command"] = "resume"; j["print"]["param"] = ""; @@ -2115,6 +2161,8 @@ int MachineObject::command_task_resume() int MachineObject::command_hms_idle_ignore(const std::string &error_str, int type) { + if(check_resume_condition()) return 0; + json j; j["print"]["command"] = "idle_ignore"; j["print"]["err"] = error_str; @@ -2125,6 +2173,8 @@ int MachineObject::command_hms_idle_ignore(const std::string &error_str, int typ int MachineObject::command_hms_resume(const std::string& error_str, const std::string& job_id) { + if(check_resume_condition()) return 0; + json j; j["print"]["command"] = "resume"; j["print"]["err"] = error_str; @@ -2137,6 +2187,8 @@ int MachineObject::command_hms_resume(const std::string& error_str, const std::s int MachineObject::command_hms_ignore(const std::string& error_str, const std::string& job_id) { + if(check_resume_condition()) return 0; + json j; j["print"]["command"] = "ignore"; j["print"]["err"] = error_str; @@ -2147,6 +2199,17 @@ int MachineObject::command_hms_ignore(const std::string& error_str, const std::s return this->publish_json(j.dump(), 1); } +int MachineObject::command_hms_stop(const std::string &error_str, const std::string &job_id) { + json j; + j["print"]["command"] = "stop"; + j["print"]["err"] = error_str; + j["print"]["param"] = "reserve"; + j["print"]["job_id"] = job_id; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + + return this->publish_json(j.dump(), 1); +} + int MachineObject::command_stop_buzzer() { json j; @@ -2211,46 +2274,21 @@ int MachineObject::command_set_chamber(int temp) return this->publish_json(j.dump(), 1); } -//int MachineObject::command_ams_switch(int tray_index, int old_temp, int new_temp) -//{ -// assert(!is_enable_np); -// -// BOOST_LOG_TRIVIAL(trace) << "ams_switch to " << tray_index << " with temp: " << old_temp << ", " << new_temp; -// -// if (old_temp < 0) old_temp = FILAMENT_DEF_TEMP; -// if (new_temp < 0) new_temp = FILAMENT_DEF_TEMP; -// int result = 0; -// -// -// //command -// if (is_support_command_ams_switch) { -// command_ams_change_filament(tray_index, old_temp, new_temp); -// } -// //gcode -// else { -// std::string gcode = ""; -// if (tray_index == 255) { -// gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode"); -// } -// else { -// // include VIRTUAL_TRAY_MAIN_ID -// gcode = DeviceManager::load_gcode(printer_type, "ams_load.gcode"); -// boost::replace_all(gcode, "[next_extruder]", std::to_string(tray_index)); -// boost::replace_all(gcode, "[new_filament_temp]", std::to_string(new_temp)); -// } -// -// result = this->publish_gcode(gcode); -// } -// -// return result; -//} +int MachineObject::check_resume_condition() +{ + if (jobState_ > 1) { + GUI::wxGetApp().show_dialog(_L("To ensure your safety, certain processing tasks (such as laser) can only be resumed on printer.")); + return 1; + } + return 0; +} int MachineObject::command_ams_change_filament(bool load, std::string ams_id, std::string slot_id, int old_temp, int new_temp) { json j; try { auto tray_id = 0; - if (ams_id < "16") { + if (atoi(ams_id.c_str()) < 16) { tray_id = atoi(ams_id.c_str()) * 4 + atoi(slot_id.c_str()); } @@ -2364,6 +2402,8 @@ int MachineObject::command_ams_select_tray(std::string tray_id) int MachineObject::command_ams_control(std::string action) { + if (action == "resume" && check_resume_condition()) return 0; + //valid actions if (action == "resume" || action == "reset" || action == "pause" || action == "done" || action == "abort") { json j; @@ -2529,6 +2569,7 @@ int MachineObject::command_nozzle_blob_detect(bool nozzle_blob_detect) j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["print"]["nozzle_blob_detect"] = nozzle_blob_detect; nozzle_blob_detection_enabled = nozzle_blob_detect; + nozzle_blob_detection_hold_start = time(nullptr); return this->publish_json(j.dump()); } @@ -2877,7 +2918,7 @@ int MachineObject::command_ipcam_record(bool on_off) j["camera"]["command"] = "ipcam_record_set"; j["camera"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["camera"]["control"] = on_off ? "enable" : "disable"; - camera_recording_hold_count = HOLD_COUNT_CAMERA; + camera_recording_ctl_start = time(nullptr); this->camera_recording_when_printing = on_off; return this->publish_json(j.dump()); } @@ -2902,7 +2943,7 @@ int MachineObject::command_ipcam_resolution_set(std::string resolution) j["camera"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); j["camera"]["resolution"] = resolution; camera_resolution_hold_count = HOLD_COUNT_CAMERA; - camera_recording_hold_count = HOLD_COUNT_CAMERA; + camera_recording_ctl_start = time(nullptr); this->camera_resolution = resolution; return this->publish_json(j.dump()); } @@ -2936,35 +2977,35 @@ int MachineObject::command_xcam_control_ai_monitoring(bool on_off, std::string l int MachineObject::command_xcam_control_buildplate_marker_detector(bool on_off) { xcam_buildplate_marker_detector = on_off; - xcam_buildplate_marker_hold_count = HOLD_COUNT_MAX; + xcam_buildplate_marker_hold_start = time(nullptr); return command_xcam_control("buildplate_marker_detector", on_off); } int MachineObject::command_xcam_control_first_layer_inspector(bool on_off, bool print_halt) { xcam_first_layer_inspector = on_off; - xcam_first_layer_hold_count = HOLD_COUNT_MAX; + xcam_first_layer_hold_start = time(nullptr); return command_xcam_control("first_layer_inspector", on_off); } int MachineObject::command_xcam_control_auto_recovery_step_loss(bool on_off) { xcam_auto_recovery_step_loss = on_off; - xcam_auto_recovery_hold_count = HOLD_COUNT_MAX; + xcam_auto_recovery_hold_start = time(nullptr); return command_set_printing_option(on_off); } int MachineObject::command_xcam_control_allow_prompt_sound(bool on_off) { xcam_allow_prompt_sound = on_off; - xcam_prompt_sound_hold_count = HOLD_COUNT_MAX; + xcam_prompt_sound_hold_start = time(nullptr); return command_set_prompt_sound(on_off); } int MachineObject::command_xcam_control_filament_tangle_detect(bool on_off) { xcam_filament_tangle_detect = on_off; - xcam_filament_tangle_detect_count = HOLD_COUNT_MAX; + xcam_filament_tangle_detect_hold_start = time(nullptr); return command_set_filament_tangle_detect(on_off); } @@ -3075,6 +3116,7 @@ void MachineObject::reset() { BOOST_LOG_TRIVIAL(trace) << "reset dev_id=" << dev_id; last_update_time = std::chrono::system_clock::now(); + subscribe_counter = SUBSCRIBE_RETRY_COUNT; m_push_count = 0; m_full_msg_count = 0; is_220V_voltage = false; @@ -3092,10 +3134,12 @@ void MachineObject::reset() extruder_axis_status = LOAD; network_wired = false; dev_connection_name = ""; - subscribe_counter = SUBSCRIBE_RETRY_COUNT; job_id_ = ""; + jobState_ = 0; m_plate_index = -1; + nt_reset_data(); + // reset print_json json empty_j; print_json.diff2all_base_reset(empty_j); @@ -3107,10 +3151,15 @@ void MachineObject::reset() vt_slot.erase(vt_slot.begin() + 1); } } - - subtask_ = nullptr; +} +void MachineObject::nt_reset_data() +{ + nt_try_local_tunnel = false; + nt_use_local_tunnel = false; + nt_cloud_full_msg_count = 0; + nt_local_full_msg_count = 0; } void MachineObject::set_print_state(std::string status) @@ -3118,15 +3167,12 @@ void MachineObject::set_print_state(std::string status) print_status = status; } -int MachineObject::connect(bool is_anonymous, bool use_openssl) +int MachineObject::connect(bool use_openssl) { if (dev_ip.empty()) return -1; - std::string username; - std::string password; - if (!is_anonymous) { - username = "qdtp"; - password = get_access_code(); - } + std::string username = "qdtp"; + std::string password = get_access_code(); + if (m_agent) { try { return m_agent->connect_printer(dev_id, dev_ip, username, password, use_openssl); @@ -3272,7 +3318,7 @@ static ENUM enum_index_of(char const *key, char const **enum_names, int enum_cou return defl; } -int MachineObject::parse_json(std::string payload, bool key_field_only) +int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_field_only) { parse_msg_count++; std::chrono::system_clock::time_point clock_start = std::chrono::system_clock::now(); @@ -3315,6 +3361,11 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) BOOST_LOG_TRIVIAL(trace) << "static: get push_all msg, dev_id=" << dev_id; m_push_count++; m_full_msg_count++; + + if (tunnel == "cloud") {nt_cloud_full_msg_count++;} + if (tunnel == "lan") {nt_local_full_msg_count++;} + nt_condition_local_tunnel(); + if (!printer_type.empty()) print_json.load_compatible_settings(printer_type, ""); print_json.diff2all_base_reset(j_pre); @@ -3338,9 +3389,10 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) } } else { - if (!printer_type.empty() && connection_type() == "lan") - { + if (!printer_type.empty()) { + nt_local_full_msg_count++; m_full_msg_count++;/* all message package is full at LAN mode*/ + nt_condition_local_tunnel(); print_json.load_compatible_settings(printer_type, ""); } @@ -3443,11 +3495,11 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) else last_utc_time = last_update_time; - if (Slic3r::get_logging_level() < level_string_to_boost("trace")) { - BOOST_LOG_TRIVIAL(info) << "parse_json: dev_id=" << dev_id << ", origin playload=" << j_pre.dump(0); - } else { - BOOST_LOG_TRIVIAL(trace) << "parse_json: dev_id=" << dev_id << ", merged playload=" << j.dump(0); - } + if (Slic3r::get_logging_level() < level_string_to_boost("trace")) { + BOOST_LOG_TRIVIAL(info) << "parse_json: dev_id=" << dev_id << ", origin playload=" << j_pre.dump(0); + } else { + BOOST_LOG_TRIVIAL(trace) << "parse_json: dev_id=" << dev_id << ", tunnel is=" << tunnel << ", merged playload=" << j.dump(0); + } // Parse version info first, as if version arrive or change, 'print' need parse again with new compatible settings try { @@ -3631,7 +3683,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) if (jj.contains("support_flow_calibration") && jj["support_flow_calibration"].is_boolean()) { - is_support_flow_calibration = jj["support_flow_calibration"].get(); + is_support_pa_calibration = jj["support_flow_calibration"].get(); } if (jj.contains("support_auto_flow_calibration") && jj["support_auto_flow_calibration"].is_boolean()) @@ -3766,7 +3818,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) if (jj["errno"].is_number()) { if (jj["errno"].get() == -2) { wxString text = _L("The current chamber temperature or the target chamber temperature exceeds 45\u2103.In order to avoid extruder clogging,low temperature filament(PLA/PETG/TPU) is not allowed to be loaded."); - GUI::wxGetApp().push_notification(text); + GUI::wxGetApp().push_notification(this, text); } } } @@ -3786,7 +3838,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) #if __WXOSX__ set_ctt_dlg(text); #else - GUI::wxGetApp().push_notification(text); + GUI::wxGetApp().push_notification(this, text); #endif } } @@ -3869,8 +3921,24 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) if (jj["net"].contains("conf")) { network_wired = (jj["net"]["conf"].get() & (0x1)) != 0; } + if (jj["net"].contains("info")) { + for (auto info_item = jj["net"]["info"].begin(); info_item != jj["net"]["info"].end(); info_item++) { + + if (info_item->contains("ip")) { + auto tmp_dev_ip = (*info_item)["ip"].get(); + if (tmp_dev_ip == 0) + continue ; + else { + set_dev_ip(convertToIp(tmp_dev_ip)); + } + } else { + break; + } + } + } } } + #pragma endregion #pragma region online @@ -3954,6 +4022,11 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) this->task_id_ = jj["task_id"].get(); } + if (jj.contains("job_attr")) { + int jobAttr = jj["job_attr"].get(); + jobState_ = get_flag_bits(jobAttr, 4, 4); + } + if (jj.contains("gcode_file")) this->m_gcode_file = jj["gcode_file"].get(); if (jj.contains("gcode_file_prepare_percent")) { @@ -4347,9 +4420,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) if (jj.contains("ipcam")) { json const & ipcam = jj["ipcam"]; if (ipcam.contains("ipcam_record")) { - if (camera_recording_hold_count > 0) - camera_recording_hold_count--; - else { + if (time(nullptr) - camera_recording_ctl_start > HOLD_TIME_3SEC) { if (ipcam["ipcam_record"].get() == "enable") { camera_recording_when_printing = true; } @@ -4420,7 +4491,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) try { if (jj.contains("xcam")) { - if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_MAX) { + if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { if (jj["xcam"].contains("printing_monitor")) { // new protocol xcam_ai_monitoring = jj["xcam"]["printing_monitor"].get(); @@ -4439,17 +4510,13 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) } } - if (xcam_first_layer_hold_count > 0) - xcam_first_layer_hold_count--; - else { + if (time(nullptr) - xcam_first_layer_hold_start > HOLD_TIME_3SEC) { if (jj["xcam"].contains("first_layer_inspector")) { xcam_first_layer_inspector = jj["xcam"]["first_layer_inspector"].get(); } } - if (xcam_buildplate_marker_hold_count > 0) - xcam_buildplate_marker_hold_count--; - else { + if (time(nullptr) - xcam_buildplate_marker_hold_start > HOLD_TIME_3SEC) { if (jj["xcam"].contains("buildplate_marker_detector")) { xcam_buildplate_marker_detector = jj["xcam"]["buildplate_marker_detector"].get(); is_support_build_plate_marker_detect = true; @@ -4562,7 +4629,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) if (jj["ams"].contains("insert_flag") || jj["ams"].contains("power_on_flag") || jj["ams"].contains("calibrate_remain_flag")) { - if (time(nullptr) - ams_user_setting_start > HOLD_TIME_MAX) + if (time(nullptr) - ams_user_setting_start > HOLD_TIME_3SEC) { if (jj["ams"].contains("insert_flag")) { ams_insert_flag = jj["ams"]["insert_flag"].get(); @@ -4996,7 +5063,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) result = jj["result"].get(); if (result == "FAIL") { wxString text = _L("Failed to start printing job"); - GUI::wxGetApp().push_notification(text); + GUI::wxGetApp().push_notification(this, text); } } } else if (jj["command"].get() == "ams_filament_setting" && !key_field_only) { @@ -5075,15 +5142,17 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) } if (jj["module_name"].get() == "first_layer_inspector") { - xcam_first_layer_inspector = enable; - xcam_first_layer_hold_count = HOLD_COUNT_MAX; + if (time(nullptr) - xcam_first_layer_hold_start > HOLD_TIME_3SEC) { + xcam_first_layer_inspector = enable; + } } else if (jj["module_name"].get() == "buildplate_marker_detector") { - xcam_buildplate_marker_detector = enable; - xcam_buildplate_marker_hold_count = HOLD_COUNT_MAX; + if (time(nullptr) - xcam_buildplate_marker_hold_start > HOLD_TIME_3SEC) { + xcam_buildplate_marker_detector = enable; + } } else if (jj["module_name"].get() == "printing_monitor") { - if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_MAX) { + if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { xcam_ai_monitoring = enable; if (jj.contains("halt_print_sensitivity")) { xcam_ai_monitoring_sensitivity = jj["halt_print_sensitivity"].get(); @@ -5091,7 +5160,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) } } else if (jj["module_name"].get() == "spaghetti_detector") { - if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_MAX) { + if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_TIME_3SEC) { // old protocol xcam_ai_monitoring = enable; if (jj.contains("print_halt")) { @@ -5111,8 +5180,11 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) _parse_print_option_ack(option); } } - if (jj.contains("auto_recovery")) { - xcam_auto_recovery_step_loss = jj["auto_recovery"].get(); + + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_TIME_3SEC) { + if (jj.contains("auto_recovery")) { + xcam_auto_recovery_step_loss = jj["auto_recovery"].get(); + } } } catch(...) { @@ -5141,7 +5213,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) else { info = reason; } - GUI::wxGetApp().push_notification(info, _L("Calibration error"), UserNotificationStyle::UNS_WARNING_CONFIRM); + GUI::wxGetApp().push_notification(this, info, _L("Calibration error"), UserNotificationStyle::UNS_WARNING_CONFIRM); BOOST_LOG_TRIVIAL(info) << cali_mode << " result fail, reason = " << reason; } } @@ -5478,9 +5550,7 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) BOOST_LOG_TRIVIAL(info) << "ack of timelapse = " << camera_timelapse; } } else if (j["camera"]["command"].get() == "ipcam_record_set") { - if (camera_recording_hold_count > 0) { - camera_recording_hold_count--; - } else { + if (time(nullptr) - camera_recording_ctl_start > HOLD_TIME_3SEC) { if (j["camera"]["control"].get() == "enable") this->camera_recording_when_printing = true; if (j["camera"]["control"].get() == "disable") this->camera_recording_when_printing = false; BOOST_LOG_TRIVIAL(info) << "ack of ipcam_record_set " << camera_recording_when_printing; @@ -5531,17 +5601,20 @@ int MachineObject::parse_json(std::string payload, bool key_field_only) } catch (...) {} - if (!key_field_only) { - if (m_active_state == Active && !module_vers.empty() && check_version_valid() - && !is_camera_busy_off()) { - m_active_state = UpdateToDate; - parse_version_func(); - if (is_support_tunnel_mqtt && connection_type() != "lan") { - m_agent->start_subscribe("tunnel"); - } - parse_state_changed_event(); - } - } + if (!key_field_only) { + BOOST_LOG_TRIVIAL(trace) << "parse_json m_active_state =" << m_active_state; + //if (m_active_state == Active && !is_camera_busy_off()) { + // if (is_support_tunnel_mqtt && connection_type() != "lan") { + // m_active_state = UpdateToDate; + // m_agent->start_subscribe("tunnel"); + // } + //} else if (m_active_state == UpdateToDate && is_camera_busy_off()) { + // m_active_state = Active; + // m_agent->stop_subscribe("tunnel"); + //} + + parse_state_changed_event(); + } } catch (...) { BOOST_LOG_TRIVIAL(trace) << "parse_json failed! dev_id=" << this->dev_id <<", payload = " << payload; @@ -5708,6 +5781,27 @@ void MachineObject::update_model_task() }); } +void MachineObject::free_slice_info() +{ + if (get_slice_info_thread) + { + if (get_slice_info_thread->joinable()) + { + get_slice_info_thread->interrupt(); + get_slice_info_thread->join(); + } + + delete get_slice_info_thread; + get_slice_info_thread = nullptr; + } + + if (slice_info) + { + delete slice_info; + slice_info = nullptr; + } +} + void MachineObject::update_slice_info(std::string project_id, std::string profile_id, std::string subtask_id, int plate_idx) { if (!m_agent) return; @@ -5733,6 +5827,8 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil int plate_index = -1; if (!m_agent) return; + if (!slice_info) return; + if (get_slice_info_thread->interruption_requested()) { return;} if (plate_idx >= 0) { plate_index = plate_idx; @@ -5910,6 +6006,31 @@ std::string MachineObject::get_string_from_fantype(int type) return ""; } +void MachineObject::nt_condition_local_tunnel() +{ + int full_msg_count_limit = 2; + if (!nt_try_local_tunnel && nt_cloud_full_msg_count == full_msg_count_limit) { + connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); + nt_try_local_tunnel = true; + } + + if (!nt_use_local_tunnel && nt_try_local_tunnel && nt_local_full_msg_count == full_msg_count_limit) { + std::vector dev_list{dev_id}; + Slic3r::GUI::wxGetApp().getAgent()->del_subscribe(dev_list); + nt_use_local_tunnel = true; + } +} + +void MachineObject::nt_restore_cloud_tunnel() +{ + if (is_connected()) { + disconnect(); + std::vector dev_list{dev_id}; + Slic3r::GUI::wxGetApp().getAgent()->add_subscribe(dev_list); + nt_use_local_tunnel = false; + } +} + NozzleFlowType MachineObject::get_nozzle_flow_type(int extruder_id) const { if (is_nozzle_flow_type_supported() && m_extder_data.extders.size() > extruder_id) @@ -6101,7 +6222,7 @@ bool MachineObject::contains_tray(const std::string &ams_id, const std::string & } } else { for (const auto& tray : vt_slot) { - if (tray.id == tray_id) { return true; } + if (tray.id == ams_id) { return true; } } } @@ -6119,7 +6240,7 @@ AmsTray MachineObject::get_tray(const std::string &ams_id, const std::string &tr } else { for (const auto &tray : vt_slot) { - if (tray.id == tray_id) { return tray; } + if (tray.id == ams_id) { return tray; } } } @@ -6153,14 +6274,9 @@ void MachineObject::parse_new_info(json print) BOOST_LOG_TRIVIAL(info) << "new print data cfg = " << cfg; if(!cfg.empty()){ - if (camera_recording_hold_count > 0) camera_recording_hold_count--; if (camera_resolution_hold_count > 0) camera_resolution_hold_count--; if (camera_timelapse_hold_count > 0) camera_timelapse_hold_count--; //if (xcam_buildplate_marker_hold_count > 0) xcam_buildplate_marker_hold_count--;first_layer_inspector - if (xcam_first_layer_hold_count > 0) xcam_first_layer_hold_count--; - if (xcam_auto_recovery_hold_count > 0) xcam_auto_recovery_hold_count--; - if (xcam_prompt_sound_hold_count > 0) xcam_prompt_sound_hold_count--; - if (xcam_filament_tangle_detect_count > 0)xcam_filament_tangle_detect_count--; if (nozzle_setting_hold_count > 0)nozzle_setting_hold_count--; @@ -6172,11 +6288,7 @@ void MachineObject::parse_new_info(json print) upgrade_force_upgrade = get_flag_bits(cfg, 2); - if (camera_recording_hold_count > 0) - { - camera_recording_hold_count--; - } - else + if (time(nullptr) - camera_recording_ctl_start > HOLD_COUNT_MAX) { camera_recording_when_printing = get_flag_bits(cfg, 3); } @@ -6204,7 +6316,9 @@ void MachineObject::parse_new_info(json print) printing_speed_lvl = (PrintingSpeedLevel)get_flag_bits(cfg, 8, 3); //is_support_build_plate_marker_detect = get_flag_bits(cfg, 12); todo yangcong - xcam_first_layer_inspector = get_flag_bits(cfg, 12); + if (time(nullptr) - xcam_first_layer_hold_start > HOLD_TIME_3SEC) { + xcam_first_layer_inspector = get_flag_bits(cfg, 12); + } if (time(nullptr) - xcam_ai_monitoring_hold_start > HOLD_COUNT_MAX) { @@ -6220,31 +6334,38 @@ void MachineObject::parse_new_info(json print) } } - xcam_auto_recovery_step_loss = get_flag_bits(cfg, 16); + if (time(nullptr) - xcam_auto_recovery_hold_start > HOLD_COUNT_MAX) { + xcam_auto_recovery_step_loss = get_flag_bits(cfg, 16); + } - if (time(nullptr) - ams_user_setting_start > HOLD_COUNT_MAX) - { + if (time(nullptr) - ams_user_setting_start > HOLD_COUNT_MAX){ ams_calibrate_remain_flag = get_flag_bits(cfg, 17); } - if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_MAX) - { + if (time(nullptr) - ams_switch_filament_start > HOLD_TIME_3SEC){ ams_auto_switch_filament_flag = get_flag_bits(cfg, 18); } - if (time(nullptr) - xcam__save_remote_print_file_to_storage_start_time > HOLD_TIME_MAX) - { + if (time(nullptr) - xcam__save_remote_print_file_to_storage_start_time > HOLD_TIME_3SEC){ xcam__save_remote_print_file_to_storage = get_flag_bits(cfg, 19); } - if (time(nullptr) - xcam_door_open_check_start_time > HOLD_TIME_MAX) - { + if (time(nullptr) - xcam_door_open_check_start_time > HOLD_TIME_3SEC){ xcam_door_open_check = (DoorOpenCheckState) get_flag_bits(cfg, 20, 2); } - xcam_allow_prompt_sound = get_flag_bits(cfg, 22); - xcam_filament_tangle_detect = get_flag_bits(cfg, 23); - nozzle_blob_detection_enabled = get_flag_bits(cfg, 24); + if (time(nullptr) - xcam_prompt_sound_hold_start > HOLD_TIME_3SEC) { + xcam_allow_prompt_sound = get_flag_bits(cfg, 22); + } + + if (time(nullptr) - xcam_filament_tangle_detect_hold_start > HOLD_TIME_3SEC){ + xcam_filament_tangle_detect = get_flag_bits(cfg, 23); + } + + if (time(nullptr) - nozzle_blob_detection_hold_start > HOLD_TIME_3SEC) { + nozzle_blob_detection_enabled = get_flag_bits(cfg, 24); + } + installed_upgrade_kit = get_flag_bits(cfg, 25); } @@ -6259,7 +6380,9 @@ void MachineObject::parse_new_info(json print) is_220V_voltage = get_flag_bits(fun, 2) == 0?false:true; is_support_flow_calibration = get_flag_bits(fun, 6); + if (this->is_series_o()) { is_support_flow_calibration = false; } // todo: Temp modification due to incorrect machine push message for H2D is_support_pa_calibration = get_flag_bits(fun, 7); + if (this->is_series_p()) { is_support_pa_calibration = false; } // todo: Temp modification due to incorrect machine push message for P is_support_prompt_sound = get_flag_bits(fun, 8); is_support_filament_tangle_detect = get_flag_bits(fun, 9); is_support_motor_noise_cali = get_flag_bits(fun, 10); @@ -6269,6 +6392,7 @@ void MachineObject::parse_new_info(json print) is_support_upgrade_kit = get_flag_bits(fun, 14); is_support_internal_timelapse = get_flag_bits(fun, 28); is_support_command_homing = get_flag_bits(fun, 32); + is_support_brtc = get_flag_bits(fun, 31); } /*aux*/ @@ -6287,6 +6411,7 @@ void MachineObject::parse_new_info(json print) if (!stat.empty()) { camera_recording = get_flag_bits(stat, 7); + m_lamp_close_recheck = (get_flag_bits(stat, 36) == 1); } /*device*/ @@ -6306,8 +6431,8 @@ void MachineObject::parse_new_info(json print) auto list = airduct["modeList"].get>(); for (int i = 0; i < list.size(); ++i) { - // only show 2 mode - if (i >= 2) { break; } + // only show 2 mode for o + if (is_series_o() && i >= 2) { break; } json mode_json = list[i]; AirMode mode; @@ -6325,7 +6450,7 @@ void MachineObject::parse_new_info(json print) } } - m_air_duct_data.modes.push_back(mode); + m_air_duct_data.modes[mode.id] = mode; } } @@ -6393,6 +6518,8 @@ void MachineObject::parse_new_info(json print) nozzle_obj.nozzle_type = NozzleType::ntStainlessSteel; } else if (type.substr(2, 2) == std::string("01")) { nozzle_obj.nozzle_type = NozzleType::ntHardenedSteel; + } else if (type.substr(2, 2) == std::string("05")) { + nozzle_obj.nozzle_type = NozzleType::ntTungstenCarbide; } } else { nozzle_obj.tool_type = NozzleToolType::NONE_TOOLTYPE; @@ -6868,7 +6995,7 @@ bool DeviceManager::EnableMultiMachine = false; bool DeviceManager::key_field_only = false; std::vector nozzle_diameter_list{ 0.2f,0.4f,0.6f,0.8f }; -std::vector nozzle_type_list{ "hardened_steel", "stainless_steel" }; +std::vector nozzle_type_list {"hardened_steel", "stainless_steel", "tungsten_carbide"}; DeviceManager::DeviceManager(NetworkAgent* agent) { @@ -6970,14 +7097,22 @@ void DeviceManager::check_pushing() { keep_alive(); MachineObject* obj = this->get_selected_machine(); + + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + auto internal = std::chrono::duration_cast(start - obj->last_update_time); + if (obj && !obj->is_support_mqtt_alive) { - std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); - auto internal = std::chrono::duration_cast(start - obj->last_update_time); if (internal.count() > TIMEOUT_FOR_STRAT && internal.count() < 1000 * 60 * 60 * 300) { BOOST_LOG_TRIVIAL(info) << "command_pushing: diff = " << internal.count(); obj->command_pushing("start"); } } + + /*check local tunnel state*/ + if (obj && obj->nt_use_local_tunnel && internal.count() > PUSHINFO_TIMEOUT) { + obj->nt_restore_cloud_tunnel(); + BOOST_LOG_TRIVIAL(info) << "Unable to receive more data in LAN tunnel"; + } } void DeviceManager::on_machine_alive(std::string json_str) @@ -7299,9 +7434,9 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec if (!need_disconnect) {m_agent->disconnect_printer();} it->second->reset(); #if !QDT_RELEASE_TO_PUBLIC - it->second->connect(false, Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); + it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); #else - it->second->connect(false, it->second->local_use_ssl_for_mqtt); + it->second->connect(it->second->local_use_ssl_for_mqtt); #endif it->second->set_lan_mode_connection_state(true); } @@ -7311,6 +7446,7 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec if (it->second->connection_type() != "lan" || it->second->connection_type().empty()) { if (m_agent->get_user_selected_machine() == dev_id) { it->second->reset_update_time(); + it->second->nt_reset_data(); } else { BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = " << dev_id; @@ -7321,9 +7457,9 @@ bool DeviceManager::set_selected_machine(std::string dev_id, bool need_disconnec BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = empty"; it->second->reset(); #if !QDT_RELEASE_TO_PUBLIC - it->second->connect(false, Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); + it->second->connect(Slic3r::GUI::wxGetApp().app_config->get("enable_ssl_for_mqtt") == "true" ? true : false); #else - it->second->connect(false, it->second->local_use_ssl_for_mqtt); + it->second->connect(it->second->local_use_ssl_for_mqtt); #endif m_agent->set_user_selected_machine(dev_id); it->second->set_lan_mode_connection_state(true); @@ -7811,146 +7947,104 @@ void DeviceManager::OnSelectedMachineLost() { GUI::wxGetApp().sidebar().load_ams_list(string(), nullptr); } -bool DeviceManager::check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info) +// moved from tao.wang and zhimin.zeng +void check_filaments_for_ams_slot(std::string model_id, + std::string tag_vendor, + std::string tag_type, + int ams_id, + int slot_id, + std::string tag_name, + bool& in_blacklist, + std::string& ac, + wxString& info) { - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (!dev) { - return true; + if (tag_name.empty()) + { + tag_name = DeviceManager::get_filament_name_from_ams(ams_id, slot_id); } - MachineObject *obj = dev->get_selected_machine(); - if (obj == nullptr || !obj->is_multi_extruders()) { - return true; - } + std::unordered_map blacklist_prompt = + { + {"TPU: not supported", _L("TPU is not supported by Box.")}, + {"PVA: flexible", _L("Damp PVA will become flexible and get stuck inside Box,please take care to dry it before use.")}, + {"CF/GF: hard and brittle", _L("CF/GF filaments are hard and brittle, It's easy to break or get stuck in Box, please use with caution.")}, + {"PLA-Glow", _L("The rough surface of PLA Glow can accelerate wear on the Box system, particularly on the internal components of the Box Lite.")} + }; - Preset *printer_preset = GUI::get_printer_preset(obj); - if (!printer_preset) - return true; + in_blacklist = false; - ConfigOptionStrings *unprintable_filament_types_op = dynamic_cast(printer_preset->config.option("unprintable_filament_types")); - if (!unprintable_filament_types_op) - return true; + std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower); + std::transform(tag_type.begin(), tag_type.end(), tag_type.begin(), ::tolower); + std::transform(tag_name.begin(), tag_name.end(), tag_name.begin(), ::tolower); + if (DeviceManager::filaments_blacklist.contains("blacklist")) { + for (auto filament_item : DeviceManager::filaments_blacklist["blacklist"]) { - ConfigOptionInts *physical_extruder_map_op = dynamic_cast(printer_preset->config.option("physical_extruder_map")); - if (!physical_extruder_map_op) - return true; + std::string vendor = filament_item.contains("vendor") ? filament_item["vendor"].get() : ""; + std::string type = filament_item.contains("type") ? filament_item["type"].get() : ""; + std::string type_suffix = filament_item.contains("type_suffix") ? filament_item["type_suffix"].get() : ""; + std::string name = filament_item.contains("name") ? filament_item["name"].get() : ""; + std::vector model_ids = filament_item.contains("model_id") ? filament_item["model_id"].get>() : std::vector(); + std::string action = filament_item.contains("action") ? filament_item["action"].get() : ""; + std::string description = filament_item.contains("description") ? filament_item["description"].get() : ""; - std::vector physical_extruder_maps = physical_extruder_map_op->values; - for (size_t idx = 0; idx < unprintable_filament_types_op->values.size(); ++idx) { - if (physical_extruder_maps[idx] == obj->get_extruder_id_by_ams_id(std::to_string(ams_id))) { - std::vector filament_types = split_string(unprintable_filament_types_op->values.at(idx), ','); - auto iter = std::find(filament_types.begin(), filament_types.end(), tag_type); - if (iter != filament_types.end()) { - wxString extruder_name = idx == 0 ? _L("left") : _L("right"); - ac = "prohibition"; - info = (wxString::Format(_L("%s is not supported by %s extruder."), tag_type, extruder_name)).ToUTF8().data(); - in_blacklist = true; - return false; + // check model id + if (!model_ids.empty() && std::find(model_ids.begin(), model_ids.end(), model_id) == model_ids.end()) { continue;} + + // check vendor + std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower); + if (!vendor.empty()) { + if ((vendor == "qidi tech" && (tag_vendor == vendor)) || + (vendor == "third party" && (tag_vendor != "qidi tech"))){ + // Do nothing + } else { + continue; + } } + + // check type + std::transform(type.begin(), type.end(), type.begin(), ::tolower); + if (!type.empty() && (type != tag_type)) { continue; } + + // check type suffix + std::transform(type_suffix.begin(), type_suffix.end(), type_suffix.begin(), ::tolower); + if (!type_suffix.empty()) { + if (tag_type.length() < type_suffix.length()) { continue; } + if ((tag_type.substr(tag_type.length() - type_suffix.length()) != type_suffix)) { continue; } + } + + // check name + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + if (!name.empty() && (name != tag_name)) { continue;} + + in_blacklist = true; + ac = action; + info = blacklist_prompt[description]; + return; } } - - return true; } -void DeviceManager::check_filaments_in_blacklist(std::string model_id, std::string tag_vendor, std::string tag_type, int ams_id, int slot_id, std::string tag_name, bool& in_blacklist, std::string& ac, std::string& info) +void DeviceManager::check_filaments_in_blacklist(std::string model_id, + std::string tag_vendor, + std::string tag_type, + const std::string &filament_id, + int ams_id, + int slot_id, + std::string tag_name, + bool &in_blacklist, + std::string &ac, + wxString &info) { if (ams_id < 0 || slot_id < 0) { return; } - if (!check_filaments_printable(tag_vendor, tag_type, ams_id, in_blacklist, ac, info)) { + if (!check_filaments_printable(tag_vendor, tag_type, filament_id, ams_id, in_blacklist, ac, info)) { return; } - if (DeviceManager::is_virtual_slot(ams_id)) { - check_filaments_for_vt_slot(tag_vendor, tag_type, ams_id, in_blacklist, ac, info); - return; - } - - if (tag_name.empty()) { - tag_name = get_filament_name_from_ams(ams_id, slot_id); - } - - std::unordered_map blacklist_prompt = - { - {"TPU: not supported", _L("TPU is not supported by BOX.")}, - {"PVA: flexible", _L("Damp PVA will become flexible and get stuck inside BOX,please take care to dry it before use.")}, - {"PLA-Glow", _L("The rough surface of PLA Glow can accelerate wear on the BOX system, particularly on the internal components of the BOX Lite.")} - }; - - in_blacklist = false; - - if (filaments_blacklist.contains("blacklist")) { - for (auto prohibited_filament : filaments_blacklist["blacklist"]) { - - std::string vendor; - std::string type; - std::string action; - std::string description; - std::string name = "undefine"; - std::vector model_ids; - - if (prohibited_filament.contains("vendor") && - prohibited_filament.contains("type") && - prohibited_filament.contains("action") && - prohibited_filament.contains("description")) - { - vendor = prohibited_filament["vendor"].get(); - type = prohibited_filament["type"].get(); - action = prohibited_filament["action"].get(); - description = prohibited_filament["description"].get(); - } - else { - return; - } - - if (prohibited_filament.contains("name")) { - name = prohibited_filament["name"].get(); - } - - if (prohibited_filament.contains("model_id")) { - for (auto res : prohibited_filament["model_id"]) - model_ids.emplace_back(res.get()); - } - - std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower); - std::transform(tag_vendor.begin(), tag_vendor.end(), tag_vendor.begin(), ::tolower); - std::transform(tag_type.begin(), tag_type.end(), tag_type.begin(), ::tolower); - std::transform(type.begin(), type.end(), type.begin(), ::tolower); - - - bool mactch_printer = false; - auto it = std::find(model_ids.begin(), model_ids.end(), model_id); - if (it != model_ids.end()) {mactch_printer = true;} - - // third party - if (vendor == "third party") { - if ("QIDI" != tag_vendor && tag_type == type) { - if (name == "undefine" || (tag_name.find(name) != std::string::npos)) { - - if (model_ids.empty() || mactch_printer) { - in_blacklist = true; - ac = action; - info = blacklist_prompt[description].ToUTF8().data(); - return; - } - } - } - } else { - if (vendor == tag_vendor && tag_type == type) { - if (name == "undefine" || (tag_name.find(name) != std::string::npos)) { - - if (model_ids.empty() || mactch_printer) { - in_blacklist = true; - ac = action; - info = blacklist_prompt[description].ToUTF8().data(); - return; - } - } - } - } - } + if (!DeviceManager::is_virtual_slot(ams_id)) { + check_filaments_for_ams_slot(model_id, tag_vendor, tag_type, ams_id, slot_id, tag_name, in_blacklist, ac, info); } } diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 8889093..720ffaa 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -39,8 +39,8 @@ #define HOLD_COUNT_MAX 3 #define HOLD_COUNT_CAMERA 6 -#define HOLD_TIME_MAX 3 // 3 seconds -#define HOLD_TIME_SWITCHING 6 // 6 seconds +#define HOLD_TIME_3SEC 3 // 3 seconds +#define HOLD_TIME_6SEC 6 // 6 seconds #define GET_VERSION_RETRYS 10 #define RETRY_INTERNAL 2000 @@ -188,7 +188,7 @@ struct Nozzle int id; NozzleToolType tool_type; // H nozzle or Cut NozzleFlowType nozzle_flow; // 0-common 1-high flow - NozzleType nozzle_type; // 0-stainless_steel 1-hardened_steel + NozzleType nozzle_type; // 0-stainless_steel 1-hardened_steel 5-tungsten_carbide float diameter = {0.4f}; // 0-0.2mm 1-0.4mm 2-0.6 mm3-0.8mm int max_temp = 0; int wear = 0; @@ -265,7 +265,7 @@ struct AirParts struct AirDuctData { int curren_mode{ 0 }; - std::vector modes; + std::unordered_map modes; std::vector parts; }; @@ -652,6 +652,7 @@ public: int subscribe_counter{3}; std::string dev_connection_type; /* lan | cloud */ std::string connection_type() { return dev_connection_type; } + std::string dev_connection_name; /* lan | eth */ void set_dev_ip(std::string ip) {dev_ip = ip;} std::string get_ftp_folder(); @@ -663,6 +664,7 @@ public: void erase_user_access_code(); std::string get_user_access_code(); bool is_lan_mode_printer(); + std::string convertToIp(long long ip); //PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN; std::string printer_type; /* model_id */ @@ -767,6 +769,9 @@ public: Ams* get_curr_Ams(); AmsTray* get_curr_tray(); AmsTray *get_ams_tray(std::string ams_id, std::string tray_id); + + std::string get_filament_id(std::string ams_id, std::string tray_id) const; + // parse amsStatusMain and ams_status_sub void _parse_ams_status(int ams_status); bool has_ams() { return ams_exist_bits != 0; } @@ -817,6 +822,7 @@ public: //new fan data AirDuctData m_air_duct_data; + bool is_at_heating_mode() const { return m_air_duct_data.curren_mode == AIR_DUCT_HEATING_INTERNAL_FILT; }; void converse_to_duct(bool is_suppt_part_fun, bool is_suppt_aux_fun, bool is_suppt_cham_fun); // Convert the data to duct type to make the newand old protocols consistent /* signals */ @@ -892,6 +898,7 @@ public: int total_layers = 0; bool is_support_layer_num { false }; bool nozzle_blob_detection_enabled{ false }; + time_t nozzle_blob_detection_hold_start = 0; int last_cali_version = -1; int cali_version = -1; @@ -959,18 +966,22 @@ public: PrintingSpeedLevel _parse_printing_speed_lvl(int lvl); int get_bed_temperature_limit(); bool is_filament_installed(); + + /*stat*/ + bool m_lamp_close_recheck = false; + /* camera */ bool has_ipcam { false }; bool camera_recording { false }; bool camera_recording_when_printing { false }; bool camera_timelapse { false }; - int camera_recording_hold_count = 0; + time_t camera_recording_ctl_start = 0; int camera_timelapse_hold_count = 0; int camera_resolution_hold_count = 0; std::string camera_resolution = ""; std::vector camera_resolution_supported; bool xcam_first_layer_inspector { false }; - int xcam_first_layer_hold_count = 0; + time_t xcam_first_layer_hold_start = 0; std::string local_rtsp_url; std::string tutk_state; enum LiveviewLocal { @@ -1026,13 +1037,13 @@ public: time_t xcam_ai_monitoring_hold_start = 0; std::string xcam_ai_monitoring_sensitivity; bool xcam_buildplate_marker_detector{ false }; - int xcam_buildplate_marker_hold_count = 0; + time_t xcam_buildplate_marker_hold_start = 0; bool xcam_auto_recovery_step_loss{ false }; bool xcam_allow_prompt_sound{ false }; bool xcam_filament_tangle_detect{ false }; - int xcam_auto_recovery_hold_count = 0; - int xcam_prompt_sound_hold_count = 0; - int xcam_filament_tangle_detect_count = 0; + time_t xcam_auto_recovery_hold_start = 0; + time_t xcam_prompt_sound_hold_start = 0; + time_t xcam_filament_tangle_detect_hold_start = 0; int nozzle_selected_count = 0; bool flag_update_nozzle = {true}; @@ -1084,6 +1095,7 @@ public: bool is_support_filament_setting_inprinting{false}; bool is_support_internal_timelapse { false };// fun[28], support timelapse without SD card bool is_support_command_homing { false };// fun[32] + bool is_support_brtc{false}; // fun[31], support tcp and upload protocol bool installed_upgrade_kit{false}; int bed_temperature_limit = -1; @@ -1102,7 +1114,7 @@ public: std::vector hms_list; /* machine mqtt apis */ - int connect(bool is_anonymous = false, bool use_openssl = true); + int connect(bool use_openssl = true); int disconnect(); json_diff print_json; @@ -1118,6 +1130,9 @@ public: boost::thread* get_slice_info_thread { nullptr }; boost::thread* get_model_task_thread { nullptr }; + /* job attr */ + int jobState_ = 0; + /* key: sequence id, value: callback */ std::map m_callback_list; @@ -1193,6 +1208,7 @@ public: int command_hms_idle_ignore(const std::string &error_str, int type); int command_hms_resume(const std::string& error_str, const std::string& job_id); int command_hms_ignore(const std::string& error_str, const std::string& job_id); + int command_hms_stop(const std::string &error_str, const std::string &job_id); /* buzzer*/ int command_stop_buzzer(); @@ -1201,6 +1217,7 @@ public: int command_set_nozzle(int temp); int command_set_nozzle_new(int nozzle_id, int temp); int command_set_chamber(int temp); + int check_resume_condition(); // ams controls //int command_ams_switch(int tray_index, int old_temp = 210, int new_temp = 210); int command_ams_change_filament(bool load, std::string ams_id, std::string slot_id, int old_temp = 210, int new_temp = 210); @@ -1305,14 +1322,17 @@ public: int publish_json(std::string json_str, int qos = 0, int flag = 0); int cloud_publish_json(std::string json_str, int qos = 0, int flag = 0); int local_publish_json(std::string json_str, int qos = 0, int flag = 0); - int parse_json(std::string payload, bool key_filed_only = false); + int parse_json(std::string tunnel, std::string payload, bool key_filed_only = false); int publish_gcode(std::string gcode_str); std::string setting_id_to_type(std::string setting_id, std::string tray_type); QDTSubTask* get_subtask(); QDTModelTask* get_modeltask(); void set_modeltask(QDTModelTask* task); + void update_model_task(); + + void free_slice_info(); void update_slice_info(std::string project_id, std::string profile_id, std::string subtask_id, int plate_idx); bool m_firmware_valid { false }; @@ -1321,6 +1341,15 @@ public: bool is_firmware_info_valid(); std::string get_string_from_fantype(int type); + /*for local mqtt tunnel try*/ + bool nt_try_local_tunnel { false }; + bool nt_use_local_tunnel { false }; + int nt_cloud_full_msg_count { 0 }; + int nt_local_full_msg_count { 0 }; + void nt_condition_local_tunnel(); + void nt_restore_cloud_tunnel(); + void nt_reset_data(); + /*for more extruder*/ bool is_enable_np{ false }; bool is_enable_ams_np{ false }; @@ -1492,8 +1521,7 @@ public: static std::vector get_resolution_supported(std::string type_str); static std::vector get_compatible_machine(std::string type_str); static std::vector get_unsupport_auto_cali_filaments(std::string type_str); - static void check_filaments_in_blacklist(std::string model_id, std::string tag_vendor, std::string tag_type, int ams_id, int slot_id, std::string tag_name, bool &in_blacklist, std::string &ac, std::string &info); - static bool check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info); + static void check_filaments_in_blacklist(std::string model_id, std::string tag_vendor, std::string tag_type, const std::string& filament_id, int ams_id, int slot_id, std::string tag_name, bool &in_blacklist, std::string &ac, wxString &info); static boost::bimaps::bimap get_all_model_id_with_name(); static std::string load_gcode(std::string type_str, std::string gcode_file); static bool is_virtual_slot(int ams_id); diff --git a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp index cd51504..93d188e 100644 --- a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp +++ b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.cpp @@ -15,32 +15,86 @@ #include +#include namespace Slic3r { namespace GUI { uiAmsPercentHumidityDryPopup::uiAmsPercentHumidityDryPopup(wxWindow *parent) - : PopupWindow(parent, wxBORDER_NONE) + : wxDialog(parent, wxID_ANY, "") { + Create(); +} + +void uiAmsPercentHumidityDryPopup::Create() +{ + // create images + idle_img = ScalableBitmap(this, "ams_drying", 16); + drying_img = ScalableBitmap(this, "ams_is_drying", 16); + + // background + SetBackgroundColour(*wxWHITE); + + // create title sizer + wxSizer* title_sizer = new wxBoxSizer(wxHORIZONTAL); + + Label* title = new Label(this, _L("Current AMS humidity")); + title->SetForegroundColour(*wxBLACK); + title->SetBackgroundColour(*wxWHITE); + title->SetFont(Label::Head_18); + + title_sizer->AddStretchSpacer(); + title_sizer->Add(title, 0, wxALIGN_CENTER_HORIZONTAL); + title_sizer->AddStretchSpacer(); + + // create humidity image + m_humidity_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap); + + // create dry state sizer + wxGridSizer* dry_state_sizer = new wxGridSizer(2, FromDIP(5), FromDIP(5)); + m_dry_state_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap); + m_dry_state_img->SetMinSize(wxSize(FromDIP(16), FromDIP(16))); + m_dry_state_img->SetMaxSize(wxSize(FromDIP(16), FromDIP(16))); + m_dry_state = new Label(this); + m_dry_state->SetForegroundColour(*wxBLACK); + m_dry_state->SetBackgroundColour(*wxWHITE); + m_dry_state->SetFont(Label::Body_14); + dry_state_sizer->Add(m_dry_state_img, 1, wxALIGN_RIGHT); + dry_state_sizer->Add(m_dry_state, 1, wxALIGN_LEFT); + + // create table grid sizer + wxGridSizer* grid_sizer = new wxGridSizer(2, 3, FromDIP(10), FromDIP(10)); + m_humidity_header = new Label(this, _L("Humidity")); + m_temperature_header = new Label(this, _L("Temperature")); + left_dry_time_header = new Label(this, _L("Left Time")); + m_humidity_label = new Label(this); + m_temperature_label = new Label(this); + left_dry_time_label = new Label(this); + + grid_sizer->Add(m_humidity_header, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + grid_sizer->Add(m_temperature_header, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + grid_sizer->Add(left_dry_time_header, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + grid_sizer->Add(m_humidity_label, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + grid_sizer->Add(m_temperature_label, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + grid_sizer->Add(left_dry_time_label, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL); + + // complete main sizer + m_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer->AddSpacer(FromDIP(10)); + m_sizer->Add(title_sizer, 1, wxEXPAND | wxHORIZONTAL); + m_sizer->Add(m_humidity_img, 1, wxALIGN_CENTER_HORIZONTAL, 0); + m_sizer->AddSpacer(FromDIP(10)); + m_sizer->Add(dry_state_sizer, 1 ,wxEXPAND | wxHORIZONTAL); + m_sizer->Add(grid_sizer, 1, wxEXPAND | wxHORIZONTAL, FromDIP(15)); + m_sizer->AddSpacer(FromDIP(10)); + SetSizer(m_sizer); + SetSize(wxSize(FromDIP(400), FromDIP(270))); SetMinSize(wxSize(FromDIP(400), FromDIP(270))); SetMaxSize(wxSize(FromDIP(400), FromDIP(270))); - idle_img = ScalableBitmap(this, "ams_drying", 16); - drying_img = ScalableBitmap(this, "ams_is_drying", 16); - close_img = ScalableBitmap(this, "hum_popup_close", 24); - - Bind(wxEVT_PAINT, &uiAmsPercentHumidityDryPopup::paintEvent, this); - Bind(wxEVT_LEFT_UP, [this](auto &e) { - auto rect = ClientToScreen(wxPoint(0, 0)); - - auto close_left = rect.x + GetSize().x - close_img.GetBmpWidth() - FromDIP(38); - auto close_right = close_left + close_img.GetBmpWidth(); - auto close_top = rect.y + FromDIP(24); - auto close_bottom = close_top + close_img.GetBmpHeight(); - - auto mouse_pos = ClientToScreen(e.GetPosition()); - if (mouse_pos.x > close_left && mouse_pos.y > close_top && mouse_pos.x < close_right && mouse_pos.y < close_bottom) { Dismiss(); } - }); + Fit(); + Layout(); + Refresh(); } void uiAmsPercentHumidityDryPopup::Update(int humidiy_level, int humidity_percent, int left_dry_time, float current_temperature) @@ -53,62 +107,12 @@ void uiAmsPercentHumidityDryPopup::Update(int humidiy_level, int humidity_percen m_left_dry_time = left_dry_time; m_current_temperature = current_temperature; - Refresh(); + UpdateContents(); } } -void uiAmsPercentHumidityDryPopup::paintEvent(wxPaintEvent &evt) +void uiAmsPercentHumidityDryPopup::UpdateContents() { - wxPaintDC dc(this); - render(dc); -} - -void uiAmsPercentHumidityDryPopup::render(wxDC &dc) -{ -#ifdef __WXMSW__ - wxSize size = GetSize(); - wxMemoryDC memdc; - wxBitmap bmp(size.x, size.y); - memdc.SelectObject(bmp); - memdc.Blit({0, 0}, size, &dc, {0, 0}); - - { - wxGCDC dc2(memdc); - doRender(dc2); - } - - memdc.SelectObject(wxNullBitmap); - dc.DrawBitmap(bmp, 0, 0); -#else - doRender(dc); -#endif -} - -void uiAmsPercentHumidityDryPopup::doRender(wxDC &dc) -{ - // background - { - dc.SetBrush(StateColor::darkModeColorFor(*wxWHITE)); - dc.DrawRoundedRectangle(0, 0, GetSize().GetWidth(), GetSize().GetHeight(), 0); - } - dc.SetBrush(*wxTRANSPARENT_BRUSH); - - wxPoint p; - - // Header - { - dc.SetFont(::Label::Head_24); - dc.SetTextForeground(StateColor::darkModeColorFor(*wxBLACK)); - WxFontUtils::get_suitable_font_size(FromDIP(24), dc); - - auto extent = dc.GetTextExtent(_L("Current BOX humidity")); - dc.DrawText(_L("Current BOX humidity"), (GetSize().GetWidth() - extent.GetWidth()) / 2, FromDIP(24)); - } - - // close icon - p.y += FromDIP(24); - dc.DrawBitmap(close_img.bmp(), GetSize().x - close_img.GetBmpWidth() - FromDIP(38), p.y); - // humitidy image if (0 < m_humidity_level && m_humidity_level < 6) { @@ -122,115 +126,49 @@ void uiAmsPercentHumidityDryPopup::doRender(wxDC &dc) humitidy_image = ScalableBitmap(this, "hum_level" + std::to_string(m_humidity_level) + "_no_num_light", 64); } - p.y += 2 * FromDIP(24); - dc.DrawBitmap(humitidy_image.bmp(), (GetSize().GetWidth() - humitidy_image.GetBmpWidth()) / 2, p.y); - p.y += humitidy_image.GetBmpHeight(); + m_humidity_img->SetBitmap(humitidy_image.bmp()); } // dry state - int spacing = FromDIP(5); - { - p.y += spacing; - if (m_left_dry_time > 0) - { - dc.DrawBitmap(drying_img.bmp(), GetSize().GetWidth() / 2 - drying_img.GetBmpWidth() - spacing, p.y); - } - else - { - dc.DrawBitmap(idle_img.bmp(), GetSize().GetWidth() / 2 - idle_img.GetBmpWidth() - spacing, p.y); - } - - dc.SetFont(::Label::Body_14); - WxFontUtils::get_suitable_font_size(idle_img.GetBmpHeight(), dc); - - const wxString &dry_state = (m_left_dry_time > 0) ? _L("Drying") : _L("Idle"); - auto dry_state_extent = dc.GetTextExtent(dry_state); - - p.y += (idle_img.GetBmpHeight() - dry_state_extent.GetHeight());//align bottom - dc.DrawText(dry_state, GetSize().GetWidth() / 2 + spacing, p.y); - p.y += dry_state_extent.GetHeight(); - } - - // Grid area - { - p.y += 2 * spacing; - DrawGridArea(dc, p); - } -} - - -static vector grid_header{ L("Humidity"), L("Temperature"), L("Left Time")}; -void uiAmsPercentHumidityDryPopup::DrawGridArea(wxDC &dc, wxPoint start_p) -{ - const wxColour& gray_clr = StateColor::darkModeColorFor(wxColour(194, 194, 194)); - const wxColour& black_clr = StateColor::darkModeColorFor(*wxBLACK); - - // Horizontal line - dc.SetPen(gray_clr); - int h_margin = FromDIP(20); - dc.DrawLine(h_margin, start_p.y, GetSize().GetWidth() - h_margin, start_p.y); - start_p.x = h_margin; - start_p.y += h_margin; - - // Draw grid area - int toltal_col; if (m_left_dry_time > 0) { - toltal_col = 3; + m_dry_state_img->SetBitmap(drying_img.bmp()); + m_dry_state->SetLabel(_L("Drying")); + m_dry_state->Fit(); } else { - toltal_col = 2; + m_dry_state_img->SetBitmap(idle_img.bmp()); + m_dry_state->SetLabel(_L("Idle")); + m_dry_state->Fit(); } - int row_height = FromDIP(30); - int text_height = FromDIP(20); - int distance = (GetSize().GetWidth() - 2 * h_margin)/ toltal_col; - for (int col = 0; col < toltal_col; ++col) + // table grid + const wxString& humidity_str = wxString::Format("%d%%", m_humidity_percent); + m_humidity_label->SetLabel(humidity_str); + const wxString& temp_str = wxString::Format(_L("%d \u2103"), (int)std::round(m_current_temperature)); + m_temperature_label->SetLabel(temp_str); + + if (m_left_dry_time > 0) { - const wxString& header = _L(grid_header[col]); - dc.SetFont(::Label::Body_14); - WxFontUtils::get_suitable_font_size(text_height, dc); - const auto &header_extent = dc.GetTextExtent(header); - - int left = start_p.x + (distance - header_extent.GetWidth()) / 2; - dc.SetPen(gray_clr); - dc.DrawText(header, left, start_p.y); - - // row content - dc.SetPen(black_clr); - if (header == _L("Humidity")) - { - const wxString &humidity_str = wxString::Format("%d%%", m_humidity_percent); - dc.DrawText(humidity_str, left, start_p.y + row_height); - } - else if (header == _L("Temperature")) - { - const wxString &temp_str = wxString::Format(_L("%.1f \u2103"), m_current_temperature); - dc.DrawText(temp_str, left, start_p.y + row_height); - } - else if (header == _L("Left Time")) - { - const wxString &time_str = wxString::Format(_L("%d : %d"), m_left_dry_time / 60, m_left_dry_time % 60); - dc.DrawText(time_str, left, start_p.y + row_height); - } - - start_p.x += distance; - if (col < toltal_col - 1) /*draw splitter*/ - { - dc.SetPen(gray_clr); - dc.DrawLine(start_p.x, start_p.y, start_p.x, start_p.y + 2 * row_height); - } + const wxString& time_str = wxString::Format(_L("%d : %d"), m_left_dry_time / 60, m_left_dry_time % 60); + left_dry_time_label->SetLabel(time_str); } + else + { + left_dry_time_label->SetLabel(_L("Idle")); + } + + Fit(); + Layout(); + Refresh(); } void uiAmsPercentHumidityDryPopup::msw_rescale() { idle_img.msw_rescale(); drying_img.msw_rescale(); - close_img.msw_rescale(); - - Refresh(); + UpdateContents(); } } // namespace GUI diff --git a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h index 99237c0..7fd5a98 100644 --- a/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h +++ b/src/slic3r/GUI/DeviceTab/uiAmsHumidityPopup.h @@ -29,7 +29,7 @@ struct uiAmsHumidityInfo /// Note: The popup of Ams Humidity with percentage and dry time /// Author: xin.zhang /// -class uiAmsPercentHumidityDryPopup : public PopupWindow +class uiAmsPercentHumidityDryPopup : public wxDialog { public: uiAmsPercentHumidityDryPopup(wxWindow *parent); @@ -40,19 +40,13 @@ public: std::string get_owner_ams_id() const { return m_ams_id; } - virtual void OnDismiss() wxOVERRIDE {}; - virtual bool ProcessLeftDown(wxMouseEvent &event) wxOVERRIDE { return true;}; - void msw_rescale(); private: void Update(int humidiy_level, int humidity_percent, int left_dry_time, float current_temperature); + void UpdateContents(); - void paintEvent(wxPaintEvent &evt); - void render(wxDC &dc); - void doRender(wxDC &dc); - - void DrawGridArea(wxDC &dc, wxPoint start_p); + void Create(); private: /*owner ams id*/ @@ -64,13 +58,25 @@ private: float m_current_temperature = 0; // Bitmap - ScalableBitmap close_img; ScalableBitmap drying_img; ScalableBitmap idle_img; // Widgets wxStaticBitmap* m_humidity_img; - wxGrid* m_grid_area; + + wxStaticBitmap* m_dry_state_img; + Label* m_dry_state; + + Label* m_humidity_header; + Label* m_humidity_label; + + Label* m_temperature_header; + Label* m_temperature_label; + + Label* left_dry_time_header; + Label* left_dry_time_label; + + wxSizer* m_sizer; }; }} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/ExtrusionCalibration.cpp b/src/slic3r/GUI/ExtrusionCalibration.cpp index 0856002..3c2c62f 100644 --- a/src/slic3r/GUI/ExtrusionCalibration.cpp +++ b/src/slic3r/GUI/ExtrusionCalibration.cpp @@ -172,7 +172,7 @@ void ExtrusionCalibration::create() m_button_cali = new Button(m_step_1_panel, _L("Start calibration")); // y96 - m_btn_bg_blue = StateColor(std::pair(wxColour(238, 238, 238), StateColor::Disabled), std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + m_btn_bg_blue = StateColor(std::pair(wxColour(238, 238, 238), StateColor::Disabled), std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_cali->SetBackgroundColor(m_btn_bg_blue); m_button_cali->SetFont(Label::Body_13); @@ -183,7 +183,7 @@ void ExtrusionCalibration::create() m_button_cali->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_cali, this); m_cali_cancel = new Button(m_step_1_panel, _L("Cancel")); - m_btn_bg_blue = StateColor(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + m_btn_bg_blue = StateColor(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_cali_cancel->SetBackgroundColor(m_btn_bg_blue); m_cali_cancel->SetBorderColor(wxColour(68, 121, 251)); @@ -258,7 +258,7 @@ void ExtrusionCalibration::create() // save button m_button_save_result = new Button(m_step_2_panel, _L("Save")); - m_btn_bg_blue = StateColor(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + m_btn_bg_blue = StateColor(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_save_result->SetBackgroundColor(m_btn_bg_blue); m_button_save_result->SetFont(Label::Body_13); diff --git a/src/slic3r/GUI/FilamentMapDialog.cpp b/src/slic3r/GUI/FilamentMapDialog.cpp index 71daa6d..9396296 100644 --- a/src/slic3r/GUI/FilamentMapDialog.cpp +++ b/src/slic3r/GUI/FilamentMapDialog.cpp @@ -110,8 +110,8 @@ bool try_pop_up_before_slice(bool is_slice_all, Plater* plater_ref, PartPlate* p } -static const StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), +static const StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); static const StateColor btn_bd_blue(std::pair(wxColour(68, 121, 251), StateColor::Normal)); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1723d46..13aa19a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -927,11 +927,11 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle) // set to color print by default if use multi extruders if (m_nozzle_nums > 1) { - m_view_type_sel = (int)EViewType::Summary; + m_view_type_sel = std::distance(view_type_items.begin(),std::find(view_type_items.begin(), view_type_items.end(), EViewType::Summary)); set_view_type(EViewType::Summary); } else { - m_view_type_sel = (int)EViewType::FeatureType; - set_view_type(EViewType::FeatureType); + m_view_type_sel = std::distance(view_type_items.begin(),std::find(view_type_items.begin(), view_type_items.end(), EViewType::ColorPrint)); + set_view_type(EViewType::ColorPrint); } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": finished"); } @@ -1376,7 +1376,7 @@ static void debug_calibration_output_thumbnail(const ThumbnailData& thumbnail_da image.SaveFile("D:/calibrate.png", wxBITMAP_TYPE_PNG); } #endif - +const int MAX_DRAWS_PER_BATCH = 1024; void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, OpenGLManager& opengl_manager) { int plate_idx = thumbnail_params.plate_id; @@ -1396,24 +1396,6 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai camera.zoom_to_box(plate_box, 1.0f); camera.apply_projection(plate_box); - auto render_as_triangles = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](TBuffer &buffer, std::vector::iterator it_path, std::vector::iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(!path.sizes.empty()); - assert(!path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_triangles_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; - auto render_as_instanced_model = [ #if ENABLE_GCODE_VIEWER_STATISTICS this @@ -1565,7 +1547,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai switch (buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Triangle: { - render_as_triangles(buffer, it_path, buffer.render_paths.end(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.end(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Triangles); break; } default: { break; } @@ -3220,7 +3202,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p // QDS: fix the issue that object_idx is not assigned as index of Model.objects array int object_count = 0; const ModelObjectPtrs& model_objs = wxGetApp().model().objects; - bool enable_lod = GUI::wxGetApp().app_config->get("enable_lod") == "true"; + bool enable_lod = false; for (const PrintObject* obj : print.objects()) { const ModelObject* model_obj = obj->model_object(); @@ -3892,6 +3874,46 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS } +template +void GCodeViewer::render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type) +{ + //std::vector::iterator it_path, std::vector::iterator it_end + if ((EDrawPrimitiveType) draw_type == EDrawPrimitiveType::Points) { + glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); + glsafe(::glEnable(GL_POINT_SPRITE)); + } + bool cancel_glmultidraw = wxGetApp().get_opengl_manager()->get_cancle_glmultidraw(); + for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { + const RenderPath &path = *it; + assert(!path.sizes.empty()); + assert(!path.offsets.empty()); + glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); + if (cancel_glmultidraw) { + for (size_t i = 0; i < path.sizes.size(); ++i) { + GLsizei count = path.sizes[i]; + glsafe(::glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (const void *) path.offsets[i])); + } + } else { + int total_draws = path.sizes.size(); + int number = path.sizes.size() / MAX_DRAWS_PER_BATCH + 1; + for (size_t batch = 0; batch < number; batch++) { + int start = batch * MAX_DRAWS_PER_BATCH; + int count = std::min(MAX_DRAWS_PER_BATCH, total_draws - start); + if (count == 0) { continue; } + glsafe(::glMultiDrawElements(OpenGLManager::get_draw_primitive_type((EDrawPrimitiveType)draw_type), (const GLsizei *) path.sizes.data() + start, GL_UNSIGNED_SHORT, + (const void *const *) (path.offsets.data() + start), + (GLsizei) count)); + } + } +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_multi_triangles_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + if ((EDrawPrimitiveType) draw_type == EDrawPrimitiveType::Points) { + glsafe(::glDisable(GL_POINT_SPRITE)); + glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); + } +} void GCodeViewer::render_toolpaths() { @@ -3920,68 +3942,9 @@ void GCodeViewer::render_toolpaths() shader.set_uniform("near_plane_height", near_plane_height); }; - auto render_as_points = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - glsafe(::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)); - glsafe(::glEnable(GL_POINT_SPRITE)); - - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_points_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - - glsafe(::glDisable(GL_POINT_SPRITE)); - glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); - }; - auto shader_init_as_lines = [light_intensity](GLShaderProgram &shader) { shader.set_uniform("light_intensity", light_intensity); }; - auto render_as_lines = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_lines_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; - - auto render_as_triangles = [ -#if ENABLE_GCODE_VIEWER_STATISTICS - this -#endif // ENABLE_GCODE_VIEWER_STATISTICS - ](std::vector::reverse_iterator it_path, std::vector::reverse_iterator it_end, GLShaderProgram& shader, int uniform_color) { - for (auto it = it_path; it != it_end && it_path->ibuffer_id == it->ibuffer_id; ++it) { - const RenderPath& path = *it; - // Some OpenGL drivers crash on empty glMultiDrawElements, see GH #7415. - assert(! path.sizes.empty()); - assert(! path.offsets.empty()); - glsafe(::glUniform4fv(uniform_color, 1, static_cast(path.color.data()))); - glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_multi_triangles_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - }; auto render_as_instanced_model = [ #if ENABLE_GCODE_VIEWER_STATISTICS @@ -4152,16 +4115,16 @@ void GCodeViewer::render_toolpaths() switch (buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Point: { - render_as_points(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Points); break; } case TBuffer::ERenderPrimitiveType::Line: { p_ogl_manager->set_line_width(static_cast(line_width(zoom))); - render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Lines); break; } case TBuffer::ERenderPrimitiveType::Triangle: { - render_as_triangles(it_path, buffer.render_paths.rend(), *shader, uniform_color); + render_sub_paths(it_path, buffer.render_paths.rend(), *shader, uniform_color, (unsigned int) EDrawPrimitiveType::Triangles); break; } default: { break; } @@ -4262,10 +4225,9 @@ void GCodeViewer::render_shells() wxGetApp().bind_shader(shader); //QDS: reopen cul faces - const auto& camera = wxGetApp().plater()->get_camera(); - const auto& view_matrix = camera.get_view_matrix(); - const auto& projection_matrix = camera.get_projection_matrix(); - m_shells.volumes.render(GUI::ERenderPipelineStage::Normal, GLVolumeCollection::ERenderType::Transparent, false, view_matrix, projection_matrix); + auto& camera = wxGetApp().plater()->get_camera(); + std::vector> colors = wxGetApp().plater()->get_extruders_colors(); + m_shells.volumes.render(GUI::ERenderPipelineStage::Normal, GLVolumeCollection::ERenderType::Transparent, false, camera, colors, wxGetApp().plater()->model()); wxGetApp().unbind_shader(); glsafe(::glDepthMask(GL_TRUE)); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 82aceee..bc8ce19 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -925,6 +925,8 @@ private: //QDS: always load shell at preview //void load_shells(const Print& print, bool initialized); void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; + template + void render_sub_paths(Iterator it_path, Iterator it_end, GLShaderProgram &shader, int uniform_color, unsigned int draw_type); void render_toolpaths(); void render_shells(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8eb4130..e6256dd 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -38,11 +38,13 @@ #include "format.hpp" #include "DailyTips.hpp" #include "FilamentMapDialog.hpp" - +#include "../Utils/CpuMemory.hpp" #if ENABLE_RETINA_GL #include "slic3r/Utils/RetinaHelper.hpp" #endif - +#ifdef __APPLE__ +#include "libslic3r/MacUtils.hpp" +#endif #include #include @@ -140,6 +142,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; @@ -276,7 +283,7 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv ImGuiWrapper& imgui = *wxGetApp().imgui(); const Size& cnv_size = canvas.get_canvas_size(); - float zoom = (float)wxGetApp().plater()->get_camera().get_zoom(); + float zoom = (float) canvas.get_active_camera().get_zoom(); float left_pos = canvas.m_main_toolbar.get_item("layersediting")->render_left_pos; float x = 0.5 * cnv_size.get_width() + left_pos * zoom; @@ -436,7 +443,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) const Size& cnv_size = canvas.get_canvas_size(); float half_w = 0.5f * (float)cnv_size.get_width(); float half_h = 0.5f * (float)cnv_size.get_height(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float inv_zoom = (float) canvas.get_active_camera().get_inv_zoom(); return { (half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom }; } @@ -579,7 +586,7 @@ void GLCanvas3D::LayersEditing::render_curve(const Rect & bar_rect) const float scale_y = bar_rect.get_height() / m_object_max_z; const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera &camera = m_canvas.get_active_camera(); Transform3d view_matrix = camera.get_view_matrix_for_billboard(); Transform3d model_matrix{ Transform3d::Identity() }; @@ -666,7 +673,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const shader->set_uniform("z_cursor", float(m_object_max_z) * float(this->get_cursor_z_relative(canvas))); shader->set_uniform("z_cursor_band_width", float(this->band_width)); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera &camera = m_canvas.get_active_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& projection_matrix = camera.get_projection_matrix(); shader->set_uniform("projection_matrix", projection_matrix); @@ -682,6 +689,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const glsafe(::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data())); glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4)); + std::vector> colors = m_canvas.get_active_colors(); for (GLVolume* glvolume : volumes.volumes) { // Render the object using the layer editing shader and texture. if (!glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier) @@ -694,7 +702,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); - glvolume->render(view_matrix); + glvolume->render(camera, colors, m_canvas.get_ref_model()); } // Revert back to the previous shader. glBindTexture(GL_TEXTURE_2D, 0); @@ -869,7 +877,7 @@ void GLCanvas3D::Labels::render(const std::vector& sorted_ if (!m_enabled || !is_shown() || m_canvas.get_gizmos_manager().is_running()) return; - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera &camera = m_canvas.get_active_camera(); const Model* model = m_canvas.get_model(); if (model == nullptr) return; @@ -1137,7 +1145,7 @@ void GLCanvas3D::SequentialPrintClearance::render() wxGetApp().bind_shader(shader); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera &camera = m_canvas.get_active_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); @@ -1330,8 +1338,10 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed) , m_show_picking_texture(false) #endif // ENABLE_RENDER_PICKING_PASS , m_render_sla_auxiliaries(true) + , m_layers_editing(*this) , m_labels(*this) , m_slope(m_volumes) + , m_sequential_print_clearance(*this) { if (m_canvas != nullptr) { m_timer.SetOwner(m_canvas); @@ -1358,7 +1368,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed) GLCanvas3D::~GLCanvas3D() { - reset_volumes(); + reset_volumes(false); m_sel_plate_toolbar.del_all_item(); m_sel_plate_toolbar.del_stats_item(); @@ -1524,7 +1534,7 @@ unsigned int GLCanvas3D::get_volumes_count() const return (unsigned int)m_volumes.volumes.size(); } -void GLCanvas3D::reset_volumes() +void GLCanvas3D::reset_volumes(bool set_notice) { if (!m_initialized) return; @@ -1537,8 +1547,7 @@ void GLCanvas3D::reset_volumes() m_selection.clear(); m_volumes.clear(); m_dirty = true; - - _set_warning_notification(EWarning::ObjectOutside, false); + if (set_notice) { _set_warning_notification(EWarning::ObjectOutside, false); } } //QDS: get current plater's bounding box @@ -1579,6 +1588,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(); @@ -1679,13 +1722,22 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(ObjectFil //assert(m_initialized); ModelInstanceEPrintVolumeState state; - m_volumes.check_outside_state(m_bed.build_volume(), &state, object_results); + m_volumes.check_outside_state(m_bed.build_volume(), &state, object_results,*m_model); construct_error_string(*object_results, get_object_clashed_text()); construct_extruder_unprintable_error(*object_results, get_left_extruder_unprintable_text(), get_right_extruder_unprintable_text()); return state; } +bool GLCanvas3D::is_volumes_selected_and_sinking() const { + for (GLVolume *volume : m_volumes.volumes) { + if (volume->selected && volume->is_sinking() && !volume->is_below_printbed()) { + return true; + } + } + return false; +} + void GLCanvas3D::toggle_selected_volume_visibility(bool selected_visible) { m_render_sla_auxiliaries = !selected_visible; @@ -1820,7 +1872,7 @@ void GLCanvas3D::set_model(Model* model) void GLCanvas3D::bed_shape_changed() { refresh_camera_scene_box(); - wxGetApp().plater()->get_camera().requires_zoom_to_bed = true; + get_active_camera().requires_zoom_to_bed = true; m_dirty = true; } @@ -1830,11 +1882,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) { @@ -1851,7 +1898,7 @@ void GLCanvas3D::set_color_by(const std::string &value) { void GLCanvas3D::refresh_camera_scene_box() { - wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box()); + get_active_camera().set_scene_box(scene_bounding_box()); } BoundingBoxf3 GLCanvas3D::assembly_view_cur_bounding_box() const { @@ -2086,7 +2133,7 @@ void GLCanvas3D::zoom_to_plate(int plate_idx) void GLCanvas3D::select_view(const std::string& direction) { - wxGetApp().plater()->get_camera().select_view(direction); + get_active_camera().select_view(direction); if (m_canvas != nullptr) m_canvas->Refresh(); } @@ -2104,18 +2151,47 @@ void GLCanvas3D::update_volumes_colors_by_extruder() m_volumes.update_colors_by_extruder(m_config); } -float GLCanvas3D::get_collapse_toolbar_width() +int GLCanvas3D::get_main_toolbar_offset() const { - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + const float cnv_width = get_canvas_size().get_width(); + const float collapse_toolbar_width = get_collapse_toolbar_width() * 2; + const float gizmo_width = m_gizmos.get_scaled_total_width(); + const float assemble_width = m_assemble_view_toolbar.get_width(); + const float separator_width = m_separator_toolbar.get_width(); + const float toolbar_total_width = m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width + collapse_toolbar_width; - return collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0; + if (cnv_width < toolbar_total_width) { + return is_collapse_toolbar_on_left() ? collapse_toolbar_width : 0; + } else { + const float offset = (cnv_width - toolbar_total_width) / 2.f; + return is_collapse_toolbar_on_left() ? offset + collapse_toolbar_width : offset; + } } -float GLCanvas3D::get_collapse_toolbar_height() -{ - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); +float GLCanvas3D::get_main_toolbar_left(int cnv_width,float inv_zoom) const { + return (-0.5f * cnv_width + get_main_toolbar_offset()) * inv_zoom; +} - return collapse_toolbar.is_enabled() ? collapse_toolbar.get_height() : 0; +bool GLCanvas3D::is_collapse_toolbar_on_left() const +{ + auto state = wxGetApp().plater()->get_sidebar_docking_state(); + return state == Sidebar::Left; +} + +float GLCanvas3D::get_collapse_toolbar_width() const +{ + GLToolbar &collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + const auto state = wxGetApp().plater()->get_sidebar_docking_state(); + + return state != Sidebar::None ? collapse_toolbar.get_width() : 0; +} + +float GLCanvas3D::get_collapse_toolbar_height() const +{ + GLToolbar &collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); + const auto state = wxGetApp().plater()->get_sidebar_docking_state(); + + return state != Sidebar::None ? collapse_toolbar.get_height() : 0; } bool GLCanvas3D::make_current_for_postinit() { @@ -2191,7 +2267,7 @@ void GLCanvas3D::render(bool only_init) // to preview, this was called before canvas had its final size. It reported zero width // and the viewport was set incorrectly, leading to tripping glAsserts further down // the road (in apply_projection). That's why the minimum size is forced to 10. - Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); if (camera.requires_zoom_to_bed) { @@ -2426,14 +2502,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(); } @@ -2926,7 +3002,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } } m_volumes.volumes = std::move(glvolumes_new); - bool enable_lod = GUI::wxGetApp().app_config->get("enable_lod") == "true"; + bool enable_lod = GUI::wxGetApp().app_config->get_bool("enable_lod") ; for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) { const ModelObject &model_object = *m_model->objects[obj_idx]; for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) { @@ -2947,6 +3023,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh // later in this function. it->volume_idx = m_volumes.volumes.size(); + if (enable_lod && CpuMemory::cur_free_memory_less_than_specify_size_gb(LOD_FREE_MEMORY_SIZE)) { + enable_lod = false; + } +#ifdef __APPLE__ + if (Slic3r::is_mac_version_15()) { + enable_lod = false; + } +#endif m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized, m_canvas_type == ECanvasType::CanvasAssembleView, false, enable_lod); m_volumes.volumes.back()->geometry_id = key.geometry_id; update_object_list = true; @@ -3092,7 +3176,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const Print* print = m_process->fff_print(); const Print* current_print = part_plate->fff_print(); - if (current_print->config().timelapse_type.value != TimelapseType::tlSmooth && part_plate->get_extruders(true).size() < 2) continue; + if (!timelapse_enabled && part_plate->get_extruders(true).size() < 2) continue; if (part_plate->get_objects_on_this_plate().empty()) continue; float brim_width = print->wipe_tower_data(filaments_count).brim_width; @@ -3119,31 +3203,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) { // update for wipe tower position { - bool need_update = false; - if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) { - x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin; - need_update = true; - } else if (x < margin + plate_bbox_x_min_local_coord) { - x = margin + plate_bbox_x_min_local_coord; - need_update = true; - } - if (need_update) { - ConfigOptionFloat wt_x_opt(x); - dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0); - need_update = false; - } - - if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) { - y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin; - need_update = true; - } else if (y < margin) { - y = margin; - need_update = true; - } - if (need_update) { - ConfigOptionFloat wt_y_opt(y); - dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0); - } int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1), (float) wipe_tower_size(0), (float) wipe_tower_size(1), (float) wipe_tower_size(2), a, @@ -3152,7 +3211,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new; } } else { - const float margin = 2.f; auto tower_bottom = current_print->wipe_tower_data().wipe_tower_mesh_data->bottom; tower_bottom.translate(scaled(Vec2d{x, y})); tower_bottom.translate(scaled(Vec2d{plate_origin[0], plate_origin[1]})); @@ -3160,15 +3218,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_build_volume(true); BoundingBox plate_bbox2d = BoundingBox(scaled(Vec2f(plate_bbox.min[0], plate_bbox.min[1])), scaled(Vec2f(plate_bbox.max[0], plate_bbox.max[1]))); Vec2f offset = WipeTower::move_box_inside_box(tower_bottom_bbox, plate_bbox2d, scaled(margin)); - if (!is_approx(offset[0], 0.f)) { - ConfigOptionFloat wt_x_opt(x + offset[0]); - dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0); - } - if (!is_approx(offset[1], 0.f)) { - ConfigOptionFloat wt_y_opt(y + offset[1]); - dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0); - } - int volume_idx_wipe_tower_new = m_volumes.load_real_wipe_tower_preview(1000 + plate_id, x + plate_origin(0) + offset[0], y + plate_origin(1) + offset[1], + int volume_idx_wipe_tower_new = m_volumes.load_real_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1), current_print->wipe_tower_data().wipe_tower_mesh_data->real_wipe_tower_mesh, current_print->wipe_tower_data().wipe_tower_mesh_data->real_brim_mesh, true,a,/*!print->is_step_done(psWipeTower)*/ true, m_initialized); @@ -3181,15 +3231,18 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } update_volumes_colors_by_extruder(); - // Update selection indices based on the old/new GLVolumeCollection. - if (m_selection.get_mode() == Selection::Instance) - m_selection.instances_changed(instance_ids_selected); - else - m_selection.volumes_changed(map_glvolume_old_to_new); - - m_gizmos.update_data(); - m_gizmos.update_assemble_view_data(); - m_gizmos.refresh_on_off_state(); + if (m_selection.is_enabled()) { + // Update selection indices based on the old/new GLVolumeCollection. + if (m_selection.get_mode() == Selection::Instance) + m_selection.instances_changed(instance_ids_selected); + else + m_selection.volumes_changed(map_glvolume_old_to_new); + } + if (m_gizmos.is_enabled()) { + m_gizmos.update_data(); + m_gizmos.update_assemble_view_data(); + m_gizmos.refresh_on_off_state(); + } // Update the toolbar //QDS: notify the PartPlateList to reload all objects @@ -3200,19 +3253,22 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re //QDS:exclude the assmble view if (m_canvas_type != ECanvasType::CanvasAssembleView) { - _set_warning_notification_if_needed(EWarning::GCodeConflict); - _set_warning_notification(EWarning::FilamentUnPrintableOnFirstLayer, false); - _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); - _set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside); + _update_slice_error_status(); // checks for geometry outside the print volume to render it accordingly if (!m_volumes.empty()) { ModelInstanceEPrintVolumeState state; ObjectFilamentResults object_results; - const bool contained_min_one = m_volumes.check_outside_state(m_bed.build_volume(), &state, &object_results); + const bool contained_min_one = m_volumes.check_outside_state(m_bed.build_volume(), &state, &object_results, *m_model); const bool partlyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Partly_Outside); const bool fullyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Fully_Outside); // const bool objectLimited = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Limited); + PartPlate *cur_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); + bool show_read_wipe_tower = cur_plate->fff_print()->is_step_done(psWipeTower); + bool wipe_tower_outside = m_volumes.check_wipe_tower_outside_state(m_bed.build_volume(), wxGetApp().plater()->get_partplate_list().get_curr_plate_index()); + bool show_wipe_tower_outside_error = show_read_wipe_tower ? !wipe_tower_outside : false; + _set_warning_notification(EWarning::PrimeTowerOutside, show_wipe_tower_outside_error); + auto clash_flag = construct_error_string(object_results, get_object_clashed_text()); auto unprintable_flag= construct_extruder_unprintable_error(object_results, get_left_extruder_unprintable_text(), get_right_extruder_unprintable_text()); @@ -3225,7 +3281,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re //if (printer_technology != ptSLA || !contained_min_one) // _set_warning_notification(EWarning::SlaSupportsOutside, false); - PartPlate* cur_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); bool tpu_valid = cur_plate->check_tpu_printable_status(wxGetApp().preset_bundle->full_config(), wxGetApp().preset_bundle->get_used_tpu_filaments(cur_plate->get_extruders(true))); _set_warning_notification(EWarning::TPUPrintableError, !tpu_valid); @@ -3249,15 +3304,63 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re _set_warning_notification(EWarning::TPUPrintableError, false); _set_warning_notification(EWarning::FilamentPrintableError, false); _set_warning_notification(EWarning::MixUsePLAAndPETG, false); + _set_warning_notification(EWarning::PrimeTowerOutside, false); _set_warning_notification(EWarning::MultiExtruderPrintableError,false); _set_warning_notification(EWarning::MultiExtruderHeightOutside,false); 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(); - if (m_selection.is_empty()) { + if (m_gizmos.is_enabled() && m_selection.is_empty()) { // If no object is selected, deactivate the active gizmo, if any // Otherwise it may be shown after cleaning the scene (if it was active while the objects were deleted) m_gizmos.reset_all_states(); @@ -3315,13 +3418,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co if (wxGetApp().is_editor()) { //QDS: always load shell at preview, do this in load_shells - //m_gcode_viewer.update_shells_color_by_extruder(m_config); - _set_warning_notification_if_needed(EWarning::ToolHeightOutside); - _set_warning_notification_if_needed(EWarning::ToolpathOutside); - _set_warning_notification_if_needed(EWarning::GCodeConflict); - _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); - _set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside); - _set_warning_notification_if_needed(EWarning::FilamentUnPrintableOnFirstLayer); + _update_slice_error_status(); } m_gcode_viewer.refresh(gcode_result, str_tool_colors); @@ -3398,11 +3495,7 @@ void GLCanvas3D::bind_event_handlers() m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this); m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this); - m_canvas->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& evt) { - ImGui::SetWindowFocus(nullptr); - render(); - evt.Skip(); - }); + m_canvas->Bind(wxEVT_KILL_FOCUS, &GLCanvas3D::on_kill_focus, this); m_event_handlers_bound = true; m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this); @@ -3469,7 +3562,7 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) } m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state(); _update_imgui_select_plate_toolbar(); - bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); + bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(get_active_camera()); m_dirty |= mouse3d_controller_applied; m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this); auto gizmo = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().get_current(); @@ -3662,7 +3755,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case '4': { select_view("rear"); break; } case '5': { select_view("left"); break; } case '6': { select_view("right"); break; } - case '7': { select_plate(); break; } + case '7': { select_view("iso");break; } #ifdef __APPLE__ case 'k': case 'K': @@ -3765,8 +3858,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) //} //case 'I': //case 'i': { _update_camera_zoom(1.0); break; } - //case 'K': - //case 'k': { wxGetApp().plater()->get_camera().select_next_type(); m_dirty = true; break; } + //case 'L': //case 'l': { //if (!m_main_toolbar.is_enabled()) { @@ -3919,7 +4011,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) Vec3d displacement; if (camera_space) { - Eigen::Matrix inv_view_3x3 = wxGetApp().plater()->get_camera().get_view_matrix().inverse().matrix().block(0, 0, 3, 3); + Eigen::Matrix inv_view_3x3 = get_active_camera().get_view_matrix().inverse().matrix().block(0, 0, 3, 3); displacement = multiplier * (inv_view_3x3 * direction); displacement.z() = 0.0; } @@ -4055,7 +4147,11 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) } case '7': case WXK_NUMPAD7: //7 on numpad - { select_plate(); break; } + { + select_view("iso"); + m_gizmos.update_paint_base_camera_rotate_rad(); + break; + } default: break; } } @@ -4267,15 +4363,15 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) } else { auto cnv_size = get_canvas_size(); - const Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); auto screen_center_3d_pos = _mouse_to_3d(camera, { cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }); auto mouse_3d_pos = _mouse_to_3d(camera, {evt.GetX(), evt.GetY()}); Vec3d displacement = mouse_3d_pos - screen_center_3d_pos; - wxGetApp().plater()->get_camera().translate(displacement); - auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom(); + camera.translate(displacement); + auto origin_zoom = camera.get_zoom(); _update_camera_zoom(delta); - auto new_zoom = wxGetApp().plater()->get_camera().get_zoom(); - wxGetApp().plater()->get_camera().translate((-displacement) / (new_zoom / origin_zoom)); + auto new_zoom = camera.get_zoom(); + camera.translate((-displacement) / (new_zoom / origin_zoom)); } } @@ -4382,7 +4478,7 @@ void GLCanvas3D::on_gesture(wxGestureEvent &evt) if (!m_initialized || !_set_current(true)) return; - auto & camera = wxGetApp().plater()->get_camera(); + auto & camera = get_active_camera(); if (evt.GetEventType() == wxEVT_GESTURE_PAN) { auto p = evt.GetPosition(); auto d = static_cast(evt).GetDelta(); @@ -4724,7 +4820,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) Vec3d cur_pos = m_mouse.drag.start_position_3D; // we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag if (m_selection.contains_volume(get_first_hover_volume_idx())) { - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); auto camera_up_down_rad_limit = abs(asin(camera.get_dir_forward()(2) / 1.0f)); if (camera_up_down_rad_limit < PI/20.0f) { // side view -> move selected volumes orthogonally to camera view direction @@ -4792,7 +4888,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) 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) { //QDS rotate around target - Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); Vec3d rotate_target = Vec3d::Zero(); if (!m_selection.is_empty()) rotate_target = m_selection.get_bounding_box().center(); @@ -4806,14 +4902,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #ifdef SUPPORT_FEEE_CAMERA if (wxGetApp().app_config->get("use_free_camera") == "1") // Virtual track ball (similar to the 3DConnexion mouse). - wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.)); + get_active_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). // See GH issue #3816. - Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); bool rotate_limit = current_printer_technology() != ptSLA; Vec3d rotate_target = m_selection.get_bounding_box().center(); @@ -4863,7 +4959,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_mouse.is_start_position_2D_defined()) { // get point in model space at Z = 0 float z = 0.0f; - Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); const Vec3d& cur_pos = _mouse_to_3d(camera, pos, &z); Vec3d orig = _mouse_to_3d(camera, m_mouse.drag.start_position_2D, &z); #ifdef SUPPORT_FREE_CAMERA @@ -4924,7 +5020,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) deselect_all(); } //QDS Select plate in this 3D canvas. - else if (evt.LeftUp() && !m_mouse.dragging && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled()) + else if (evt.LeftUp() && !m_mouse.rotating && !m_mouse.panning && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled()) { int hover_idx = m_hover_plate_idxs.front(); wxGetApp().plater()->select_plate_by_hover_id(hover_idx); @@ -5065,6 +5161,13 @@ void GLCanvas3D::on_paint(wxPaintEvent& evt) this->render(); } +void GLCanvas3D::on_kill_focus(wxFocusEvent &evt) +{ + ImGui::SetWindowFocus(nullptr); + render(); + evt.Skip(); +} + void GLCanvas3D::force_set_focus() { m_canvas->SetFocus(); }; @@ -5546,16 +5649,11 @@ void GLCanvas3D::update_ui_from_settings() if (new_scaling != orig_scaling) { BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << new_scaling; - Camera& camera = wxGetApp().plater()->get_camera(); + Camera& camera = get_active_camera(); camera.set_zoom(camera.get_zoom() * new_scaling / orig_scaling); _refresh_if_shown_on_screen(); } #endif // ENABLE_RETINA_GL - -#ifdef SUPPORT_COLLAPSE_BUTTON - if (wxGetApp().is_editor()) - wxGetApp().plater()->enable_collapse_toolbar(wxGetApp().app_config->get("show_collapse_button") == "1"); -#endif } // QDS: add partplate logic @@ -5602,7 +5700,7 @@ Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos) { float z0 = 0.0f; float z1 = 1.0f; - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); return Linef3(_mouse_to_3d(camera, mouse_pos, &z0), _mouse_to_3d(camera, mouse_pos, &z1)); } @@ -5980,12 +6078,12 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera //now change to left_up as {0,0}, and top is 0, bottom is canvas_h #if QDS_TOOLBAR_ON_TOP - const float x = left * float(wxGetApp().plater()->get_camera().get_zoom()) + 0.5f * canvas_w; + const float x = left * float(get_active_camera().get_zoom()) + 0.5f * canvas_w; ImGuiWrapper::push_toolbar_style(get_scale()); imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); #else const float x = canvas_w - m_main_toolbar.get_width(); - const float y = 0.5f * canvas_h - top * float(wxGetApp().plater()->get_camera().get_zoom()); + const float y = 0.5f * canvas_h - top * float(get_active_camera().get_zoom()); imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f); #endif @@ -6065,14 +6163,14 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera //now change to left_up as {0,0}, and top is 0, bottom is canvas_h #if QDS_TOOLBAR_ON_TOP - float zoom = (float)wxGetApp().plater()->get_camera().get_zoom(); + float zoom = (float)get_active_camera().get_zoom(); float left_pos = m_main_toolbar.get_item("arrange")->render_left_pos; const float x = 0.5 * canvas_w + left_pos * zoom; imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f); #else const float x = canvas_w - m_main_toolbar.get_width(); - const float y = 0.5f * canvas_h - top * float(wxGetApp().plater()->get_camera().get_zoom()); + const float y = 0.5f * canvas_h - top * float(get_active_camera().get_zoom()); imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f); #endif @@ -6248,7 +6346,7 @@ void GLCanvas3D::_render_3d_navigator() const float camDistance = 8.f; ImGuizmo::SetID(0); - Camera & camera = wxGetApp().plater()->get_camera(); + Camera & camera = get_active_camera(); Transform3d m = Transform3d::Identity(); m.matrix().block(0, 0, 3, 3) = camera.get_view_rotation().toRotationMatrix(); // Rotate along X and Z axis for 90 degrees to have Y-up @@ -6393,6 +6491,16 @@ void GLCanvas3D::render_thumbnail_framebuffer(const std::shared_ptrget_camera().zoom_to_box(box, margin_factor); + get_active_camera().zoom_to_box(box, margin_factor); m_dirty = true; } void GLCanvas3D::_update_camera_zoom(double zoom) { - wxGetApp().plater()->get_camera().update_zoom(zoom); + get_active_camera().update_zoom(zoom); m_dirty = true; } +Camera &GLCanvas3D::get_active_camera() +{ + /*if (m_canvas_type == CanvasThumbnailView) { + return wxGetApp().plater()->get_thumbnail_camera(); + } else {*/ + return wxGetApp().plater()->get_camera(); // global camera + //} +} + +const Camera &GLCanvas3D::get_active_camera() const +{ + /*if (m_canvas_type == CanvasThumbnailView) { + return wxGetApp().plater()->get_thumbnail_camera(); + } else {*/ + return wxGetApp().plater()->get_camera(); // global camera + //} +} + +std::vector> GLCanvas3D::get_active_colors() { + return GUI::wxGetApp().plater()->get_extruders_colors(); +} + void GLCanvas3D::_refresh_if_shown_on_screen() { if (_is_shown_on_screen()) { @@ -6961,7 +7091,7 @@ void GLCanvas3D::_picking_pass() picking_camera.apply_viewport(0, 0, 1, 1); float pick_eye_z = 0.0f; - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); Vec3d pick_eye = _mouse_to_3d(camera, { m_mouse.position(0), m_mouse.position(1) }, &pick_eye_z); float pick_target_z = 1.0f; @@ -6988,7 +7118,7 @@ void GLCanvas3D::_picking_pass() _render_volumes_for_picking(); //QDS: remove the bed picking logic - //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); + //_render_bed_for_picking(!get_active_camera().is_looking_downward()); m_gizmos.render_current_gizmo_for_picking_pass(); @@ -7077,7 +7207,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass() OpenGLManager::FrameBufferModifier picking_frame(*p_ogl_manager, "rectangular_selection_pickingframe", EMSAAType::Disabled); } - const auto camera = wxGetApp().plater()->get_camera(); + const auto& camera = get_active_camera(); const auto main_camera_type = camera.get_type(); auto& picking_camera = wxGetApp().plater()->get_picking_camera(); @@ -7086,7 +7216,6 @@ void GLCanvas3D::_rectangular_selection_picking_pass() picking_camera.set_zoom(camera.get_zoom()); float pick_eye_z = 0.0f; - const Camera& camera = wxGetApp().plater()->get_camera(); Vec3d pick_eye = _mouse_to_3d(camera, { center.x(), center.y() }, &pick_eye_z); float pick_target_z = 1.0f; Vec3d pick_target = _mouse_to_3d(camera, { center.x(), center.y() }, &pick_target_z); @@ -7113,7 +7242,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass() _render_volumes_for_picking(); //QDS: remove the bed picking logic - //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); + //_render_bed_for_picking(!get_active_camera().is_looking_downward()); glsafe(::glDisable(GL_SCISSOR_TEST)); } @@ -7316,7 +7445,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with } } if (m_requires_check_outside_state) { - m_volumes.check_outside_state(build_volume, nullptr, nullptr); + m_volumes.check_outside_state(build_volume, nullptr, nullptr, *m_model); m_requires_check_outside_state = false; } } @@ -7350,9 +7479,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with auto printable_height_option = GUI::wxGetApp().preset_bundle->printers.get_edited_preset().config.option("extruder_printable_height"); const GUI::ERenderPipelineStage render_pipeline_stage = _get_current_render_stage(); - const auto& camera = wxGetApp().plater()->get_camera(); - const auto& view_matrix = camera.get_view_matrix(); - const auto& projection_matrix = camera.get_projection_matrix(); + const auto& camera = get_active_camera(); + std::vector> colors = get_active_colors(); if ((GUI::ERenderPipelineStage::Silhouette == render_pipeline_stage) || shader != nullptr) { if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { @@ -7368,7 +7496,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with { if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f) && GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { int object_id = m_layers_editing.last_object_id; - m_volumes.render(render_pipeline_stage, type, false, view_matrix, projection_matrix, [object_id](const GLVolume& volume) { + m_volumes.render( + render_pipeline_stage, type, false, camera, colors, *m_model,[object_id](const GLVolume &volume) { // Which volume to paint without the layer height profile shader? return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); }); @@ -7383,7 +7512,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with }*/ //QDS:add assemble view related logic // do not cull backfaces to show broken geometry, if any - m_volumes.render(render_pipeline_stage, type, m_picking_enabled, view_matrix, projection_matrix, [this, canvas_type](const GLVolume& volume) { + m_volumes.render( + render_pipeline_stage, type, m_picking_enabled, camera, colors, + *m_model,[this, canvas_type](const GLVolume &volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { return !volume.is_modifier && !volume.is_wipe_tower; } @@ -7417,7 +7548,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with shader->set_uniform("show_wireframe", false); }*/ //QDS:add assemble view related logic - m_volumes.render(render_pipeline_stage, type, false, view_matrix, projection_matrix, [this, canvas_type](const GLVolume& volume) { + m_volumes.render( + render_pipeline_stage, type, false, camera, colors,*m_model, + [this, canvas_type](const GLVolume &volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { return !volume.is_modifier; } @@ -7432,6 +7565,18 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with gm.render_painter_assemble_view(); wxGetApp().bind_shader(shader); } + if (m_canvas_type == CanvasView3D && m_gizmos.is_paint_gizmo()) { + m_volumes.only_render_sinking( + render_pipeline_stage, type, false, camera, colors, *m_model, + [this, canvas_type](const GLVolume &volume) { + if (canvas_type == ECanvasType::CanvasAssembleView) { + return !volume.is_modifier; + } else { + return true; + } + }, + with_outline, body_color, partly_inside_enable, printable_height_option ? &printable_height_option->values : nullptr); + } break; } } @@ -7555,8 +7700,10 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() m_main_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size * scale); m_assemble_view_toolbar.set_icons_size(size); m_separator_toolbar.set_icons_size(size); - collapse_toolbar.set_icons_size(size); + collapse_toolbar.set_icons_size(wxGetApp().plater()->get_collapse_toolbar_size()); #endif // ENABLE_RETINA_GL + // Update collapse toolbar + collapse_toolbar.set_enabled(wxGetApp().plater()->get_sidebar_docking_state() != Sidebar::None); //QDS: GUI refactor: GLToolbar #if QDS_TOOLBAR_ON_TOP @@ -7610,7 +7757,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 @@ -7633,7 +7779,7 @@ void GLCanvas3D::_render_overlays() m_main_toolbar.set_icons_size(gizmo_size); m_assemble_view_toolbar.set_icons_size(gizmo_size); m_separator_toolbar.set_icons_size(gizmo_size); - wxGetApp().plater()->get_collapse_toolbar().set_icons_size(size); + wxGetApp().plater()->get_collapse_toolbar().set_icons_size(wxGetApp().plater()->get_collapse_toolbar_size()); m_gizmos.set_overlay_icon_size(gizmo_size); #endif // ENABLE_RETINA_GL @@ -7786,10 +7932,11 @@ void GLCanvas3D::_render_volumes_for_picking() const // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - const Camera& camera = wxGetApp().plater()->get_picking_camera(); + Camera& camera = wxGetApp().plater()->get_picking_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& proj_matrix = camera.get_projection_matrix(); shader->set_uniform("projection_matrix", proj_matrix); + std::vector> colors; for (size_t type = 0; type < 2; ++ type) { GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); for (const GLVolumeWithIdAndZ& volume : to_render) @@ -7812,7 +7959,7 @@ void GLCanvas3D::_render_volumes_for_picking() const std::array t_color{ (GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255 }; shader->set_uniform("uniform_color", t_color); volume.first->picking = true; - volume.first->render(view_matrix); + volume.first->render(camera, colors, *m_model); // colors is no use here volume.first->picking = false; } } @@ -7825,7 +7972,7 @@ void GLCanvas3D::_render_volumes_for_picking() const void GLCanvas3D::_render_current_gizmo() const { //QDS update inv_zoom - GLGizmoBase::INV_ZOOM = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + GLGizmoBase::INV_ZOOM = (float)get_active_camera().get_inv_zoom(); m_gizmos.render_current_gizmo(); } @@ -7859,16 +8006,11 @@ void GLCanvas3D::_render_main_toolbar() return; Size cnv_size = get_canvas_size(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float inv_zoom = (float)get_active_camera().get_inv_zoom(); #if QDS_TOOLBAR_ON_TOP - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; - float gizmo_width = m_gizmos.get_scaled_total_width(); - float assemble_width = m_assemble_view_toolbar.get_width(); - float separator_width = m_separator_toolbar.get_width(); float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width - collapse_toolbar_width)) * inv_zoom; + float left = get_main_toolbar_left(cnv_size.get_width(),inv_zoom); #else float gizmo_height = m_gizmos.get_scaled_total_height(); float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); @@ -7880,8 +8022,7 @@ void GLCanvas3D::_render_main_toolbar() #endif m_main_toolbar.set_position(top, left); m_main_toolbar.render(*this); - if (m_toolbar_highlighter.m_render_arrow) - { + if (m_toolbar_highlighter.m_render_arrow){ m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item); } } @@ -7991,7 +8132,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar() float margin_size = 4.0f * f_scale; float button_margin = frame_padding; - const float y_offset = 0; // is_collapse_toolbar_on_left() ? (get_collapse_toolbar_height() + 5) : 0; + const float y_offset = is_collapse_toolbar_on_left() ? (get_collapse_toolbar_height() + 5) : 0; // Make sure the window does not overlap the 3d navigator auto window_height_max = canvas_h - y_offset; if (wxGetApp().show_3d_navigator()) { @@ -8243,18 +8384,14 @@ void GLCanvas3D::_render_assemble_view_toolbar() const return; Size cnv_size = get_canvas_size(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float inv_zoom = (float)get_active_camera().get_inv_zoom(); #if QDS_TOOLBAR_ON_TOP - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; + const float separator_width = m_separator_toolbar.get_width(); float gizmo_width = m_gizmos.get_scaled_total_width(); - float assemble_width = m_assemble_view_toolbar.get_width(); - float separator_width = m_separator_toolbar.get_width(); float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width - separator_width - collapse_toolbar_width)) * inv_zoom; - float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width) * inv_zoom; - //float left = 0.5f * (m_main_toolbar.get_width() + gizmo_width - m_assemble_view_toolbar.get_width() + collapse_toolbar_width) * inv_zoom; + float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); + float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width) * inv_zoom; #else float gizmo_height = m_gizmos.get_scaled_total_height(); //float space_height = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); @@ -8283,11 +8420,11 @@ void GLCanvas3D::_render_return_toolbar() auto canvas_h = float(cnv_size.get_height()); float window_width = real_size.x + button_icon_size.x + imgui.scaled(2.0f); float window_height = button_icon_size.y + imgui.scaled(2.0f); - float window_pos_x = 30.0f; + float window_pos_x = 30.0f + (is_collapse_toolbar_on_left() ? (get_collapse_toolbar_width() + 5.f) : 0); float window_pos_y = 14.0f; {//solve ui overlap issue if (m_canvas_type == ECanvasType::CanvasView3D) { - float zoom = (float) wxGetApp().plater()->get_camera().get_zoom(); + float zoom = (float) get_active_camera().get_zoom(); float left_pos = m_main_toolbar.get_item("add")->render_left_pos; const float toolbar_x = 0.5 * canvas_w + left_pos * zoom; const float margin = 5; @@ -8418,7 +8555,7 @@ void GLCanvas3D::_render_separator_toolbar_right() const return; Size cnv_size = get_canvas_size(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float inv_zoom = (float)get_active_camera().get_inv_zoom(); GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; @@ -8426,8 +8563,8 @@ void GLCanvas3D::_render_separator_toolbar_right() const float assemble_width = m_assemble_view_toolbar.get_width(); float separator_width = m_separator_toolbar.get_width(); float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width - collapse_toolbar_width)) * inv_zoom; - float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width) * inv_zoom; + float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); + float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + 0.5 * separator_width) * inv_zoom; m_separator_toolbar.set_position(top, left); m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); @@ -8439,16 +8576,11 @@ void GLCanvas3D::_render_separator_toolbar_left() const return; Size cnv_size = get_canvas_size(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); - - GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); - float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0.0f; - float gizmo_width = m_gizmos.get_scaled_total_width(); - float assemble_width = m_assemble_view_toolbar.get_width(); - float separator_width = m_separator_toolbar.get_width(); + float inv_zoom = (float)get_active_camera().get_inv_zoom(); + float separator_width = m_separator_toolbar.get_width(); float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_size.get_width(), -0.5f * (m_main_toolbar.get_width() + gizmo_width + assemble_width + separator_width - collapse_toolbar_width)) * inv_zoom; - float left = main_toolbar_left + (m_main_toolbar.get_width()) * inv_zoom; + float main_toolbar_left = get_main_toolbar_left(cnv_size.get_width(), inv_zoom); + float left = main_toolbar_left + (m_main_toolbar.get_width()) * inv_zoom; m_separator_toolbar.set_position(top, left); m_separator_toolbar.render(*this,GLToolbarItem::SeparatorLine); @@ -8456,10 +8588,15 @@ void GLCanvas3D::_render_separator_toolbar_left() const void GLCanvas3D::_render_collapse_toolbar() const { + auto & plater = *wxGetApp().plater(); + const auto sidebar_docking_dir = plater.get_sidebar_docking_state(); + if (sidebar_docking_dir == Sidebar::None) { + return; + } GLToolbar& collapse_toolbar = wxGetApp().plater()->get_collapse_toolbar(); Size cnv_size = get_canvas_size(); - float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); + float inv_zoom = (float)get_active_camera().get_inv_zoom(); float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; //float left = (0.5f * (float)cnv_size.get_width() - (float)collapse_toolbar.get_width() - band) * inv_zoom; @@ -8857,7 +8994,7 @@ void GLCanvas3D::_render_camera_target() const wxGetApp().bind_shader(p_flat_shader); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& proj_matrix = camera.get_projection_matrix(); @@ -8866,7 +9003,7 @@ void GLCanvas3D::_render_camera_target() const const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); p_ogl_manager.set_line_width(2.0f); - const Vec3d& target = wxGetApp().plater()->get_camera().get_target(); + const Vec3d& target = get_active_camera().get_target(); const float scale = 2.0f * half_length; Transform3d model_matrix{ Transform3d::Identity() }; @@ -9015,7 +9152,7 @@ void GLCanvas3D::_render_sla_slices() } for (const SLAPrintObject::Instance& inst : obj->instances()) { - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(Vec3d(unscale(inst.shift.x()), unscale(inst.shift.y()), 0.0), inst.rotation * Vec3d::UnitZ(), Vec3d::Ones(), @@ -9187,7 +9324,7 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume) if (!print->has_skirt() && !print->has_brim()) return; - const std::array color = { 0.5f, 0.5f, 1.0f, 1.0f }; // y96 greenish + const std::array color = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish // number of skirt layers size_t total_layer_count = 0; @@ -9870,7 +10007,7 @@ void GLCanvas3D::_render_silhouette_effect() const auto& picking_color = wxGetApp().get_picking_color(); p_silhouette_shader->set_uniform("u_base_color", picking_color); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix(); const Matrix4d view_proj = projection_matrix.matrix() * view_matrix.matrix(); @@ -10022,6 +10159,22 @@ void GLCanvas3D::_composite_silhouette_effect() // QDS: end composite silhouette } +bool GLCanvas3D::is_volume_in_plate_boundingbox(const GLVolume &v, int plate_idx, const BoundingBoxf3 &plate_build_volume) +{ + bool ret = v.printable; + if (plate_idx >= 0) { + bool contained = false; + BoundingBoxf3 plate_bbox = plate_build_volume; + plate_bbox.min(2) = -1e10; + const BoundingBoxf3 &volume_bbox = v.transformed_convex_hull_bounding_box(); + if (plate_bbox.contains(volume_bbox) && (volume_bbox.max(2) > 0)) { contained = true; } + ret &= contained; + } else { + ret &= (!v.shader_outside_printer_detection_enabled || !v.is_outside); + } + return ret; +} + void GLCanvas3D::_init_fullscreen_mesh() { if (s_full_screen_mesh.is_initialized()) { @@ -10172,7 +10325,7 @@ void GLCanvas3D::_debug_draw_camera(const Camera& t_camera) wxGetApp().bind_shader(p_flat_shader); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& proj_matrix = camera.get_projection_matrix(); auto mv = view_matrix.matrix() * final_model_matrix.matrix(); @@ -10214,7 +10367,7 @@ void GLCanvas3D::_debug_draw_aabb() glsafe(::glLineWidth(2.0f)); wxGetApp().bind_shader(p_flat_shader); - const Camera& camera = wxGetApp().plater()->get_camera(); + const Camera& camera = get_active_camera(); const auto& view_matrix = camera.get_view_matrix(); const auto& proj_matrix = camera.get_projection_matrix(); p_flat_shader->set_uniform("projection_matrix", proj_matrix); @@ -10306,38 +10459,13 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const if (thumbnail_params.use_plate_box) { int plate_idx = thumbnail_params.plate_id; PartPlate* plate = partplate_list.get_plate(plate_idx); - plate_build_volume = plate->get_build_volume(); - plate_build_volume.min(0) -= Slic3r::BuildVolume::SceneEpsilon; - plate_build_volume.min(1) -= Slic3r::BuildVolume::SceneEpsilon; - plate_build_volume.min(2) -= Slic3r::BuildVolume::SceneEpsilon; - plate_build_volume.max(0) += Slic3r::BuildVolume::SceneEpsilon; - plate_build_volume.max(1) += Slic3r::BuildVolume::SceneEpsilon; - plate_build_volume.max(2) += Slic3r::BuildVolume::SceneEpsilon; - /*if (m_config != nullptr) { - double h = m_config->opt_float("printable_height"); - plate_build_volume.min(2) = std::min(plate_build_volume.min(2), -h); - plate_build_volume.max(2) = std::max(plate_build_volume.max(2), h); - }*/ - - auto is_visible = [plate_idx, plate_build_volume](const GLVolume& v) { - bool ret = v.printable; - if (plate_idx >= 0) { - bool contained = false; - BoundingBoxf3 plate_bbox = plate_build_volume; - plate_bbox.min(2) = -1e10; - const BoundingBoxf3& volume_bbox = v.transformed_convex_hull_bounding_box(); - if (plate_bbox.contains(volume_bbox) && (volume_bbox.max(2) > 0)) { contained = true; } - ret &= contained; - } - else { - ret &= (!v.shader_outside_printer_detection_enabled || !v.is_outside); - } - return ret; - }; + plate_build_volume = plate->get_build_volume(); for (GLVolume* vol : volumes.volumes) { if (!vol->is_modifier && !vol->is_wipe_tower && (!thumbnail_params.parts_only || vol->composite_id.volume_id >= 0)) { - if (is_visible(*vol)) { visible_volumes.emplace_back(vol); } + if (is_volume_in_plate_boundingbox(*vol, plate_idx, plate_build_volume)) { + visible_volumes.emplace_back(vol); + } } } BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%, use_top_view=%4%, for_picking=%5%") % plate_idx % @@ -10546,7 +10674,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; @@ -10715,6 +10844,14 @@ 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::PrimeTowerOutside: + text = _u8L("The prime tower extends beyond the plate boundary."); + break; + case EWarning::AsemblyInvalid: + { + error = ErrorType::ASSEMBLY_WARNNING; + break; + } } //QDS: this may happened when exit the app, plater is null if (!wxGetApp().plater()) @@ -10829,6 +10966,15 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) else notification_manager.close_slicing_customize_error_notification(NotificationType::QDTSliceMultiExtruderHeightOutside, 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 e35f4af..a46128d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -282,7 +282,7 @@ class GLCanvas3D float last_z{ 0.0f }; LayerHeightEditActionType last_action{ LAYER_HEIGHT_EDIT_ACTION_INCREASE }; - LayersEditing() = default; + LayersEditing(GLCanvas3D &canvas) : m_canvas(canvas) {} ~LayersEditing(); void init(); @@ -326,6 +326,9 @@ class GLCanvas3D void update_slicing_parameters(); static float thickness_bar_width(const GLCanvas3D& canvas); + + private: + GLCanvas3D &m_canvas; }; struct Mouse @@ -402,7 +405,9 @@ class GLCanvas3D MultiExtruderPrintableError, // after slice MultiExtruderHeightOutside, // after slice FilamentUnPrintableOnFirstLayer, - MixUsePLAAndPETG + MixUsePLAAndPETG, + PrimeTowerOutside, + AsemblyInvalid // for asembly view only }; class RenderStats @@ -636,8 +641,6 @@ private: //QDS 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}; - //QDS 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) @@ -724,6 +727,7 @@ public: public: //QDS: add the height logic + SequentialPrintClearance(GLCanvas3D &m_canvas) : m_canvas(m_canvas) {} ~SequentialPrintClearance(); void set_polygons(const Polygons& polygons, const std::vector>& height_polygons); void set_render_fill(bool render_fill) { m_render_fill = render_fill; } @@ -732,6 +736,9 @@ public: void reset(); friend class GLCanvas3D; + + private: + GLCanvas3D &m_canvas; }; SequentialPrintClearance m_sequential_print_clearance; @@ -798,9 +805,10 @@ public: unsigned int get_volumes_count() const; const GLVolumeCollection& get_volumes() const { return m_volumes; } - void reset_volumes(); + void reset_volumes(bool set_notice = true); ModelInstanceEPrintVolumeState check_volumes_outside_state(ObjectFilamentResults* object_results = nullptr) const; bool is_all_plates_selected() { return m_sel_plate_toolbar.m_all_plates_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item->selected; } + bool is_volumes_selected_and_sinking() const; const float get_scale() const; //QDS @@ -820,6 +828,7 @@ public: void set_process(BackgroundSlicingProcess* process); void set_model(Model* model); const Model* get_model() const { return m_model; } + Model& get_ref_model() const { return *m_model; } const Selection& get_selection() const { return m_selection; } Selection& get_selection() { return m_selection; } @@ -832,9 +841,6 @@ public: //QDS: add part plate related logic void plates_count_changed(); - //QDS get camera - Camera& get_camera(); - void set_clipping_plane(unsigned int id, const ClippingPlane& plane) { if (id < 2) @@ -899,15 +905,18 @@ public: //QDS: add part plate related logic void select_plate(); //QDS: GUI refactor: GLToolbar&&gizmo - float get_main_toolbar_height() { return m_main_toolbar.get_height();} - float get_main_toolbar_width() { return m_main_toolbar.get_width();} - float get_assemble_view_toolbar_width() { return m_assemble_view_toolbar.get_width(); } - float get_assemble_view_toolbar_height() { return m_assemble_view_toolbar.get_height(); } - float get_assembly_paint_toolbar_width() { return m_paint_toolbar_width; } - float get_separator_toolbar_width() { return m_separator_toolbar.get_width(); } - float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); } - float get_collapse_toolbar_width(); - float get_collapse_toolbar_height(); + int get_main_toolbar_offset() const; + float get_main_toolbar_left(int cnv_width,float inv_zoom) const; + int get_main_toolbar_height() const { return m_main_toolbar.get_height(); } + int get_main_toolbar_width() const { return m_main_toolbar.get_width(); } + float get_assemble_view_toolbar_width() const { return m_assemble_view_toolbar.get_width(); } + float get_assemble_view_toolbar_height() const { return m_assemble_view_toolbar.get_height(); } + float get_assembly_paint_toolbar_width() const { return m_paint_toolbar_width; } + float get_separator_toolbar_width() const { return m_separator_toolbar.get_width(); } + float get_separator_toolbar_height() const { return m_separator_toolbar.get_height(); } + bool is_collapse_toolbar_on_left() const; + float get_collapse_toolbar_width() const; + float get_collapse_toolbar_height() const; void update_volumes_colors_by_extruder(); @@ -1010,6 +1019,7 @@ public: void on_mouse(wxMouseEvent& evt); void on_gesture(wxGestureEvent& evt); void on_paint(wxPaintEvent& evt); + void on_kill_focus(wxFocusEvent &evt); void on_set_focus(wxFocusEvent& evt); void force_set_focus(); @@ -1164,9 +1174,15 @@ public: void mark_context_dirty(); + Camera & get_active_camera(); + const Camera & get_active_camera() const; + std::vector> get_active_colors(); + private: bool _is_shown_on_screen() const; + void _update_slice_error_status(); + void _switch_toolbars_icon_filename(); bool _init_toolbars(); bool _init_main_toolbar(); @@ -1300,7 +1316,7 @@ private: void _init_unit_cube(); void _append_to_frame_callback(const FrameCallback& cb); - + static bool is_volume_in_plate_boundingbox(const GLVolume &v, int plate_idx, const BoundingBoxf3 &plate_build_volume); static void _init_fullscreen_mesh(); static void _rebuild_postprocessing_pipeline(const std::shared_ptr& p_ogl_manager, const std::string& input_framebuffer_name, std::string& output_framebuffer_name, uint32_t width, uint32_t height); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 7311748..5164db6 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1098,10 +1098,11 @@ void GUI_App::post_init() std::string download_params_url = url_decode(this->init_params->input_files.front()); auto input_str_arr = split_str(download_params_url, "file="); - + if (input_str_arr.size() > 1) {input_str_arr.erase(input_str_arr.begin());} std::string download_url; #if QDT_RELEASE_TO_PUBLIC + short ext_url_open_state = -1; // -1 not set, wxNO not open, wxYES open for (auto input_str : input_str_arr) { if (boost::starts_with(input_str, "http://makerworld") || boost::starts_with(input_str, "https://makerworld") || @@ -1111,6 +1112,18 @@ void GUI_App::post_init() boost::algorithm::contains(input_str, "aliyuncs.com")) { download_url = input_str; } + else { + if (ext_url_open_state == -1) { + + MessageDialog msg_dlg(nullptr, + _L("This file is not from a trusted site, do you want to open it anyway?"), "", + wxAPPLY | wxYES_NO); + ext_url_open_state = msg_dlg.ShowModal(); + } + if (ext_url_open_state == wxID_YES) { + download_url = input_str; + } + } } #else for (auto input_str : input_str_arr) { @@ -2050,10 +2063,25 @@ void GUI_App::init_networking_callbacks() //subscribe device if (m_agent->is_user_login()) { m_agent->start_device_subscribe(); + + /*disconnect lan*/ + DeviceManager* dev = this->getDeviceManager(); + if (!dev) return; + + MachineObject *obj = dev->get_selected_machine(); + if (!obj) return; + + if (obj->nt_try_local_tunnel && obj->connection_type() == "cloud") { + if (obj->is_connected()) { + obj->disconnect(); + } + obj->nt_reset_data(); + } + /* resubscribe the cache dev list */ if (this->is_enable_multi_machine()) { - DeviceManager* dev = this->getDeviceManager(); - if (dev && !dev->subscribe_list_cache.empty()) { + + if (!dev->subscribe_list_cache.empty()) { dev->subscribe_device_list(dev->subscribe_list_cache); } } @@ -2085,9 +2113,7 @@ void GUI_App::init_networking_callbacks() obj->command_get_access_code(); if (m_agent) m_agent->install_device_cert(obj->dev_id, obj->is_lan_mode_printer()); - if (!is_enable_multi_machine()) { - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); - } + GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); } }); }); @@ -2191,18 +2217,16 @@ void GUI_App::init_networking_callbacks() auto sel = this->m_device_manager->get_selected_machine(); if (sel && sel->dev_id == dev_id) { - obj->parse_json(msg); + obj->parse_json("cloud", msg); } else { - obj->parse_json(msg, true); + obj->parse_json("cloud", msg, true); } - if (!this->is_enable_multi_machine()) { - if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) { - GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); - obj->is_ams_need_update = false; - } + if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) { + GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); + obj->is_ams_need_update = false; } } @@ -2242,20 +2266,13 @@ void GUI_App::init_networking_callbacks() this->process_network_msg(dev_id, msg); MachineObject* obj = m_device_manager->get_my_machine(dev_id); - if (!obj || !obj->is_lan_mode_printer()) { - obj = m_device_manager->get_local_machine(dev_id); - } if (obj) { - obj->parse_json(msg, DeviceManager::key_field_only); + obj->parse_json("lan", msg, DeviceManager::key_field_only); if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) { GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj); } } - obj = m_device_manager->get_local_machine(dev_id); - if (obj) { - obj->parse_json(msg, DeviceManager::key_field_only); - } if (GUI::wxGetApp().plater()) GUI::wxGetApp().plater()->update_machine_sync_status(); @@ -2298,8 +2315,10 @@ bool GUI_App::is_blocking_printing(MachineObject *obj_) if (!dev) return true; std::string target_model; if (obj_ == nullptr) { - auto obj_ = dev->get_selected_machine(); - target_model = obj_->printer_type; + auto obj_ = dev->get_selected_machine(); + if (obj_) { + target_model = obj_->printer_type; + } } else { target_model = obj_->printer_type; } @@ -2910,6 +2929,9 @@ bool GUI_App::on_init_inner() const bool gizmo_keep_screen_size = app_config->get_bool("gizmo_keep_screen_size"); p_ogl_manager->set_gizmo_keep_screen_size_enabled(gizmo_keep_screen_size); + + const bool cancel_glmultidraw = app_config->get_bool("cancel_glmultidraw"); + p_ogl_manager->set_cancle_glmultidraw(cancel_glmultidraw); } QDTSplashScreen * scrn = nullptr; @@ -3615,7 +3637,11 @@ static void update_dark_children_ui(wxWindow* window, bool just_buttons_update = is_btn = false;*/ if (!window) return; - wxGetApp().UpdateDarkUI(window); + if (ScalableButton* btn = dynamic_cast(window)) { + btn->UpdateDarkUI(); + } else { + wxGetApp().UpdateDarkUI(window); + } auto children = window->GetChildren(); for (auto child : children) { @@ -5432,23 +5458,33 @@ void GUI_App::show_dialog(wxString msg) } } -void GUI_App::push_notification(wxString msg, wxString title, UserNotificationStyle style) +void GUI_App::push_notification(const MachineObject* obj, wxString msg, wxString title, UserNotificationStyle style) { - if (!this->is_enable_multi_machine()) { - if (style == UserNotificationStyle::UNS_NORMAL) { - if (m_info_dialog_content.empty()) { - wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_DIALOG); - evt->SetString(msg); - GUI::wxGetApp().QueueEvent(evt); - m_info_dialog_content = msg; - } + if (this->is_enable_multi_machine()) + { + if (m_device_manager && (obj != m_device_manager->get_selected_machine())) + { + return; } - else if (style == UserNotificationStyle::UNS_WARNING_CONFIRM) { - GUI::wxGetApp().CallAfter([msg, title] { + } + + if (style == UserNotificationStyle::UNS_NORMAL) + { + if (m_info_dialog_content.empty()) + { + wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_DIALOG); + evt->SetString(msg); + GUI::wxGetApp().QueueEvent(evt); + m_info_dialog_content = msg; + } + } + else if (style == UserNotificationStyle::UNS_WARNING_CONFIRM) + { + GUI::wxGetApp().CallAfter([msg, title] + { GUI::MessageDialog msg_dlg(nullptr, msg, title, wxICON_WARNING | wxOK); msg_dlg.ShowModal(); }); - } } } @@ -6863,6 +6899,7 @@ void GUI_App::MacOpenURL(const wxString& url) if (!url.empty() && boost::starts_with(url, "qidistudioopen://")) { auto input_str_arr = split_str(url.ToStdString(), "qidistudioopen://"); + if (input_str_arr.size() > 1) {input_str_arr.erase(input_str_arr.begin());} std::string download_origin_url; for (auto input_str : input_str_arr) { @@ -7696,6 +7733,41 @@ void GUI_App::disassociate_files(std::wstring extend) #endif // __WXMSW__ +bool is_soluble_filament(int extruder_id) +{ + auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets; + auto &filaments = Slic3r::GUI::wxGetApp().preset_bundle->filaments; + + if (extruder_id >= filament_presets.size()) return false; + + Slic3r::Preset *filament = filaments.find_preset(filament_presets[extruder_id]); + if (filament == nullptr) return false; + + Slic3r::ConfigOptionBools *support_option = dynamic_cast(filament->config.option("filament_soluble")); + if (support_option == nullptr) return false; + + return support_option->get_at(0); +}; + +bool has_filaments(const std::vector& model_filaments) { + auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets; + auto model_objects = Slic3r::GUI::wxGetApp().plater()->model().objects; + const Slic3r::DynamicPrintConfig &config = wxGetApp().preset_bundle->full_config(); + Model::setExtruderParams(config, filament_presets.size()); + + auto get_filament_name = [](int id) { return Model::extruderParamsMap.find(id) != Model::extruderParamsMap.end() ? Model::extruderParamsMap.at(id).materialName : "PLA"; }; + for (const ModelObject *mo : model_objects) { + for (auto vol : mo->volumes) { + auto ve = vol->get_extruders(); + for (auto id : ve) { + auto name = get_filament_name(id); + if (find(model_filaments.begin(), model_filaments.end(), name) != model_filaments.end()) return true; + } + } + } + return false; +} + bool is_support_filament(int extruder_id) { auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets; @@ -7706,9 +7778,20 @@ bool is_support_filament(int extruder_id) Slic3r::Preset *filament = filaments.find_preset(filament_presets[extruder_id]); if (filament == nullptr) return false; - Slic3r::ConfigOptionBools *support_option = dynamic_cast(filament->config.option("filament_is_support")); - if (support_option == nullptr) return false; + std::string filament_type = filament->config.option("filament_type")->values[0]; + Slic3r::ConfigOptionBools *support_option = dynamic_cast(filament->config.option("filament_is_support")); + + if (filament_type == "PETG" || filament_type == "PLA") { + std::vector model_filaments; + if (filament_type == "PETG") + model_filaments.emplace_back("PLA"); + else { + model_filaments = {"PETG", "TPU", "TPU-BOX"}; + } + if (has_filaments(model_filaments)) return true; + } + if (support_option == nullptr) return false; return support_option->get_at(0); }; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 82fa626..0ff693e 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -509,7 +509,7 @@ public: static std::string format_display_version(); std::string format_IP(const std::string& ip); void show_dialog(wxString msg); - void push_notification(wxString msg, wxString title = wxEmptyString, UserNotificationStyle style = UserNotificationStyle::UNS_NORMAL); + void push_notification(const MachineObject* obj, wxString msg, wxString title = wxEmptyString, UserNotificationStyle style = UserNotificationStyle::UNS_NORMAL); void reload_settings(); void remove_user_presets(); void sync_preset(Preset* preset); @@ -766,6 +766,9 @@ DECLARE_APP(GUI_App) wxDECLARE_EVENT(EVT_CONNECT_LAN_MODE_PRINT, wxCommandEvent); bool is_support_filament(int extruder_id); +bool is_soluble_filament(int extruder_id); +// check if the filament for model is in the list +bool has_filaments(const std::vector& model_filaments); } // namespace GUI } // Slic3r diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index bf97edb..ee015a8 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -1283,6 +1283,7 @@ void MenuFactory::create_part_menu() [](wxCommandEvent&) { plater()->split_volume(); }, "split_parts", nullptr, []() { return plater()->can_split(false); }, m_parent); m_part_menu.AppendSeparator(); + append_menu_item_per_object_process(&m_part_menu); append_menu_item_per_object_settings(&m_part_menu); } @@ -1296,6 +1297,7 @@ void MenuFactory::create_text_part_menu() append_menu_item_simplify(menu); append_menu_items_mirror(menu); menu->AppendSeparator(); + append_menu_item_per_object_process(menu); append_menu_item_per_object_settings(menu); append_menu_item_change_type(menu); } @@ -1310,6 +1312,7 @@ void MenuFactory::create_svg_part_menu() append_menu_item_simplify(menu); append_menu_items_mirror(menu); menu->AppendSeparator(); + append_menu_item_per_object_process(menu); append_menu_item_per_object_settings(menu); append_menu_item_change_type(menu); } @@ -1338,6 +1341,7 @@ void MenuFactory::create_qdt_part_menu() append_submenu(menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "", []() { return plater()->can_split(true); }, m_parent); menu->AppendSeparator(); + append_menu_item_per_object_process(menu); append_menu_item_per_object_settings(menu); append_menu_item_change_type(menu); append_menu_item_reload_from_disk(menu); @@ -1600,12 +1604,26 @@ wxMenu* MenuFactory::multi_selection_menu() wxDataViewItemArray sels; obj_list()->GetSelections(sels); bool multi_volume = true; - + int count = 0; + int obj_idx = -1; for (const wxDataViewItem& item : sels) { multi_volume = list_model()->GetItemType(item) & itVolume; if (!(list_model()->GetItemType(item) & (itVolume | itObject | itInstance))) // show this menu only for Objects(Instances mixed with Objects)/Volumes selection return nullptr; + if (multi_volume) { + auto temp_obj_idx = obj_list()->GetModel()->GetObjectIdByItem(item); + if (temp_obj_idx >= 0 && temp_obj_idx != obj_idx) { + if (obj_idx == -1) { + obj_idx = temp_obj_idx; + } + else { + multi_volume = false; + break; + } + } + } + count++; } wxMenu* menu = new MenuWithSeparators(); @@ -1632,6 +1650,10 @@ wxMenu* MenuFactory::multi_selection_menu() } else { append_menu_item_center(menu); + auto mo = (*obj_list()->objects())[obj_idx]; + if (count < mo->volumes.size()) { + append_menu_item_sub_merge(menu); + } append_menu_item_fix_through_netfabb(menu); //append_menu_item_simplify(menu); append_menu_item_delete(menu); @@ -1649,6 +1671,7 @@ wxMenu* MenuFactory::multi_selection_menu() append_submenu(menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "", []() { return plater()->can_split(true); }, m_parent); } + append_menu_item_per_object_process(menu); } { @@ -1786,6 +1809,26 @@ void MenuFactory::append_menu_item_center(wxMenu* menu) }, m_parent); } +void MenuFactory::append_menu_item_sub_merge(wxMenu *menu) +{ + append_menu_item( + menu, wxID_ANY, _L("Sub merge"), "", + [this](wxCommandEvent &) { + obj_list()->add_new_model_object_from_old_object(); + }, + "", nullptr, + []() { + if (plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasView3D) + return false; + else { + if (obj_list()->has_selected_cut_object()) + return false; + return true; + } + }, + m_parent); +} + void MenuFactory::append_menu_item_per_object_process(wxMenu* menu) { const std::vector names = { _L("Edit Process Settings"), _L("Edit Process Settings") }; @@ -1802,6 +1845,28 @@ void MenuFactory::append_menu_item_per_object_process(wxMenu* menu) selection.is_single_volume() || selection.is_multiple_volume(); }, m_parent); + + const std::vector names2 = {_L("Copy Process Settings"), _L("Copy Process Settings")}; + append_menu_item( + menu, wxID_ANY, names2[0], names2[1], [](wxCommandEvent &) { + wxGetApp().obj_list()->copy_settings_to_clipboard(); + }, "", nullptr, + []() { + Selection &selection = plater()->canvas3D()->get_selection(); + return selection.is_single_full_object() || selection.is_single_full_instance() || + selection.is_single_volume_or_modifier(); + }, + m_parent); + + const std::vector names3 = {_L("Paste Process Settings"), _L("Paste Process Settings")}; + append_menu_item( + menu, wxID_ANY, names3[0], names3[1], [](wxCommandEvent &) { + wxGetApp().obj_list()->paste_settings_into_list(); + }, "", nullptr, + []() { + return wxGetApp().obj_list()->can_paste_settings_into_list(); + }, + m_parent); } void MenuFactory::append_menu_item_per_object_settings(wxMenu* menu) diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index 9e09ccd..4ccfceb 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -171,6 +171,7 @@ private: void append_menu_item_clone(wxMenu* menu); void append_menu_item_simplify(wxMenu* menu); void append_menu_item_center(wxMenu* menu); + void append_menu_item_sub_merge(wxMenu *menu); void append_menu_item_per_object_process(wxMenu* menu); void append_menu_item_per_object_settings(wxMenu* menu); void append_menu_item_change_filament(wxMenu* menu); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 70110ce..ab8c79f 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -443,7 +443,7 @@ coordf_t LayerRangeEditor::get_value() else { if (!str.ToDouble(&layer_height) || layer_height < 0.0f) { show_error(m_parent, _L("Invalid numeric.")); - SetValue(double_to_string(layer_height)); + SetValue(m_valid_value); // reset to a valid value } } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 87227ce..b3a6c5c 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1222,38 +1222,95 @@ void ObjectList::copy_settings_to_clipboard() if (m_objects_model->GetItemType(item) & itSettings) item = m_objects_model->GetParent(item); - m_clipboard.get_config_cache() = get_item_config(item).get(); + wxDataViewItemArray items; + items.push_back(item); + while ((m_objects_model->GetItemType(items.back()) & itObject) == 0) { + if (m_objects_model->GetItemType(items.back()) & itLayerRoot) + items.back() = m_objects_model->GetParent(items.back()); + else + items.push_back(m_objects_model->GetParent(items.back())); + } + auto &config = m_clipboard.get_config_cache(); + config.clear(); + while (!items.empty()) { + config.apply(get_item_config(items.back()).get()); + items.pop_back(); + } + + m_clipboard.set_type(ItemType(m_objects_model->GetItemType(item) | itSettings)); +} + +bool GUI::ObjectList::can_paste_settings_into_list() +{ + wxDataViewItemArray sels; + GetSelections(sels); + if (sels.empty()) + return false; + return m_clipboard.get_type() == (m_objects_model->GetItemType(sels.front()) | itSettings); } void ObjectList::paste_settings_into_list() { - wxDataViewItem item = GetSelection(); - assert(item.IsOk()); - if (m_objects_model->GetItemType(item) & itSettings) - item = m_objects_model->GetParent(item); + wxDataViewItemArray sels; + GetSelections(sels); + take_snapshot("Paste settings"); - ItemType item_type = m_objects_model->GetItemType(item); - if(!(item_type & (itObject | itVolume |itLayer))) - return; + std::unique_ptr global_keys; // need copy from global - DynamicPrintConfig& config_cache = m_clipboard.get_config_cache(); - assert(!config_cache.empty()); + for (auto item : sels) { - auto keys = config_cache.keys(); - auto part_options = SettingsFactory::get_options(true); + if (m_objects_model->GetItemType(item) & itSettings) + item = m_objects_model->GetParent(item); - for (const std::string& opt_key: keys) { - if (item_type & (itVolume | itLayer) && - std::find(part_options.begin(), part_options.end(), opt_key) == part_options.end()) - continue; // we can't to add object specific options for the part's(itVolume | itLayer) config + ItemType item_type = m_objects_model->GetItemType(item); + if(!(item_type & (itObject | itVolume |itLayer))) + return; - const ConfigOption* option = config_cache.option(opt_key); - if (option) - m_config->set_key_value(opt_key, option->clone()); + DynamicPrintConfig& config_cache = m_clipboard.get_config_cache(); + assert(!config_cache.empty()); + + auto keys = config_cache.keys(); + auto part_options = SettingsFactory::get_options(true); + auto config = &get_item_config(item); + auto extruder = config->option("extruder") ? config->option("extruder")->clone() : nullptr; + config->reset(); + + if (item_type & (itVolume | itLayer)) { + if (global_keys == nullptr) { + auto object = m_objects_model->GetParent(item); + DynamicPrintConfig config; + config.apply_only(*wxGetApp().get_tab(Preset::TYPE_PRINT)->get_config(), keys); + config.apply_only(get_item_config(object).get(), keys); + auto equals = config.equal(config_cache); + global_keys.reset(new t_config_option_keys); + auto keys2 = get_item_config(object).keys(); + std::copy_if(keys2.begin(), keys2.end(), std::back_inserter(*global_keys), + [&equals](auto &e) { return std::find(equals.begin(), equals.end(), e) == equals.end(); }); + keys.erase(std::remove_if(keys.begin(), keys.end(), + [&equals](auto &e) { return std::find(equals.begin(), equals.end(), e) != equals.end(); }), keys.end()); + } + config->apply_only(*wxGetApp().get_tab(Preset::TYPE_PRINT)->get_config(), *global_keys); + } + + for (const std::string& opt_key: keys) { + if (item_type & (itVolume | itLayer) && + std::find(part_options.begin(), part_options.end(), opt_key) == part_options.end()) + continue; // we can't to add object specific options for the part's(itVolume | itLayer) config + + const ConfigOption* option = config_cache.option(opt_key); + if (option) + config->set_key_value(opt_key, option->clone()); + } + if (extruder) + config->set_key_value("extruder", extruder); + else + config->erase("extruder"); + + // Add settings item for object/sub-object and show them + add_settings_item(item, &config->get()); } - // Add settings item for object/sub-object and show them - show_settings(add_settings_item(item, &m_config->get())); + part_selection_changed(); } void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes) @@ -1429,6 +1486,7 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me dynamic_cast(wxGetApp().get_layer_tab())->reset_model_config(); else dynamic_cast(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config(); + wxGetApp().params_panel()->notify_object_config_changed(); } else if (col_num == colName) { @@ -1605,7 +1663,7 @@ bool ObjectList::paste_from_clipboard() if (m_clipboard.get_type() & itSettings) paste_settings_into_list(); - if (m_clipboard.get_type() & (itLayer | itLayerRoot)) + else if (m_clipboard.get_type() & (itLayer | itLayerRoot)) paste_layers_into_list(); return true; @@ -2361,6 +2419,83 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode } } +void GUI::ObjectList::add_new_model_object_from_old_object() { + const Selection &selection = scene_selection(); + int instance_idx = *selection.get_instance_idxs().begin(); + assert(instance_idx != -1); + if (instance_idx == -1) + return; + wxDataViewItemArray sels; + GetSelections(sels); + if (sels.IsEmpty()) return; + int obj_idx = -1; + std::vector vol_idxs; + for (wxDataViewItem item : sels) { + const int temp_obj_idx = m_objects_model->GetObjectIdByItem(item); + if (temp_obj_idx < 0) //&& object(obj_idx)->is_cut() + return; + obj_idx = temp_obj_idx; + const int vol_idx = m_objects_model->GetVolumeIdByItem(item); + vol_idxs.emplace_back(vol_idx); + } + if (vol_idxs.empty()) { + return; + } + take_snapshot("Add new model object"); + wxBusyCursor cursor; + std::sort(vol_idxs.begin(), vol_idxs.end()); + ModelVolumePtrs sel_volumes; + auto mo = (*m_objects)[obj_idx]; + for (int i = vol_idxs.size() - 1; i >= 0; i--) { + if (vol_idxs[i] > mo->volumes.size()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "check error:array bound"; + continue; + } + auto vol_idx = vol_idxs[i]; + auto mv = mo->volumes[vol_idx]; + sel_volumes.emplace_back(mv); + mo->volumes.erase(mo->volumes.begin() + vol_idx); + } + for (int i = vol_idxs.size() - 1; i >= 0; i--) { + auto vol_idx = vol_idxs[i]; + delete_volume_from_list(obj_idx, vol_idx); + } + // Add mesh to model as a new object + Model &model = wxGetApp().plater()->model(); + + std::vector object_idxs; + ModelObject * new_object = model.add_object(); + new_object->name = into_u8(_L("Sub-merged body")); + new_object->add_instance(); // each object should have at least one instance + int min_extruder = (int) EnforcerBlockerType::ExtruderMax; + for (auto mv : sel_volumes) { + new_object->add_volume(*mv, mv->type()); + auto option = mv->config.option("extruder"); + if (option) { + auto volume_extruder_id = (dynamic_cast(option))->getInt(); + if (min_extruder > volume_extruder_id) { + min_extruder = volume_extruder_id; + } + } else { + auto opt = mo->config.option("extruder"); + if (opt && min_extruder != opt->getInt()) { min_extruder = opt->getInt(); } + } + } + new_object->sort_volumes(true); + // set a default extruder value, since user can't add it manually + new_object->config.set_key_value("extruder", new ConfigOptionInt(min_extruder)); + new_object->invalidate_bounding_box(); + new_object->instances[0]->set_transformation(mo->instances[0]->get_transformation()); + // BBS: backup + Slic3r::save_object_mesh(*new_object); + new_object->ensure_on_bed(); + // BBS init assmeble transformation + new_object->get_model()->set_assembly_pos(new_object); + object_idxs.push_back(model.objects.size() - 1); + paste_objects_into_list(object_idxs); + wxGetApp().mainframe->update_title(); +} + void ObjectList::switch_to_object_process() { wxGetApp().params_panel()->switch_to_object(true); @@ -2856,6 +2991,7 @@ void ObjectList::split() void ObjectList::merge(bool to_multipart_object) { + wxBusyCursor wait; // merge selected objects to the multipart object if (to_multipart_object) { auto get_object_idxs = [this](std::vector& obj_idxs, wxDataViewItemArray& sels) @@ -2972,8 +3108,20 @@ void ObjectList::merge(bool to_multipart_object) const Transform3d& transformation_matrix = transformation.get_matrix(); // merge volumes - for (const ModelVolume* volume : object->volumes) { + for(int volume_idx = 0; volume_idx < object->volumes.size(); volume_idx++) { + const ModelVolume* volume = object->volumes[volume_idx]; ModelVolume* new_volume = new_object->add_volume(*volume); + int new_volume_idx = new_object->volumes.size() - 1; + // merge brim ears + for (auto p : object->brim_points) { + if (p.volume_idx == volume_idx) { + Transform3d v_matrix = object->volumes[p.volume_idx]->get_matrix(); + p.set_transform(v_matrix); + p.set_transform(transformation_matrix); + p.volume_idx = new_volume_idx; + new_object->brim_points.push_back(p); + } + } //QDS: keep volume's transform const Transform3d& volume_matrix = new_volume->get_matrix(); @@ -3000,11 +3148,14 @@ void ObjectList::merge(bool to_multipart_object) //for volume config, it only has settings of PrintRegionConfig //so we can not copy settings from object to volume //but we can copy settings from volume to object - if (object->volumes.size() > 1) - { + if (object->volumes.size() > 1){ new_volume->config.assign_config(volume->config); } - + auto option = new_volume->config.option("extruder"); + if (!option) { + auto opt = object->config.option("extruder"); + if (opt) { new_volume->config.set_key_value("extruder", new ConfigOptionInt(opt->getInt())); } + } new_volume->mmu_segmentation_facets.assign(std::move(volume->mmu_segmentation_facets)); } new_object->sort_volumes(true); @@ -3038,10 +3189,12 @@ void ObjectList::merge(bool to_multipart_object) new_object->layer_config_ranges.emplace(range); // merge brim ears - BrimPoints temp_brim_points = object->brim_points; - for(auto& p : temp_brim_points) { - p.set_transform(transformation_matrix); - new_object->brim_points.push_back(p); + for(auto& p : object->brim_points) { + if (p.volume_idx < 0) { + Transform3d v_matrix = Transform3d::Identity(); + p.set_transform(transformation_matrix * v_matrix); + new_object->brim_points.push_back(p); + } } } @@ -3056,7 +3209,11 @@ void ObjectList::merge(bool to_multipart_object) const Transform3d& new_object_inverse_matrix = new_object_trsf.get_matrix().inverse(); for (auto& p : new_object->brim_points) { + Transform3d v_matrix_inverse = Transform3d::Identity(); + if (p.volume_idx >= 0) + v_matrix_inverse = new_object->volumes[p.volume_idx]->get_matrix().inverse(); p.set_transform(new_object_inverse_matrix); + p.set_transform(v_matrix_inverse); } //QDS: notify it before remove notify_instance_updated(m_objects->size() - 1); @@ -3680,6 +3837,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_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 5a65906..4ce78d6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -288,6 +288,7 @@ public: //void load_part(ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); + void add_new_model_object_from_old_object(); void load_shape_object(const std::string &type_name); void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true); // QDS @@ -436,6 +437,7 @@ public: void paste_layers_into_list(); void copy_settings_to_clipboard(); void paste_settings_into_list(); + bool can_paste_settings_into_list(); bool clipboard_is_empty() const { return m_clipboard.empty(); } void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); void paste_objects_into_list(const std::vector& object_idxs); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 4fd692e..bedc0d9 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 6f38ba4..0887e94 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/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 8d9f89d..d008b85 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -337,7 +338,26 @@ private: }; typedef DPIAware DPIFrame; -typedef DPIAware DPIDialog; +class DPIDialog : public DPIAware +{ +public: + using DPIAware::DPIAware; + +public: + void EndModal(int retCode) override + { + if (!dialogStack.empty() && dialogStack.front() != this) { + // This is a bug in wxWidgets + // when the dialog is not top modal dialog, EndModal() just hide dialog without quit + // the modal event loop. And the modal event loop blocks us from bottom widgets. + // Solution: let user click it manually or close outside. FIXME + BOOST_LOG_TRIVIAL(warning) << "DPIAware::EndModal Error: dialogStack is not empty, but top dialog is not this one. retCode=" << retCode; + return; + } + + return wxDialog::EndModal(retCode); + } +}; class EventGuard diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 7d3b2c4..5580722 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -385,23 +385,9 @@ BoundingBoxf3 GLGizmoAdvancedCut::get_bounding_box() const t_aabb.reset(); // rotate aabb - if (m_is_dragging) { - auto t_rotate_aabb = GLGizmoRotate3D::get_bounding_box(); - if (t_rotate_aabb.defined) { - t_aabb.merge(t_rotate_aabb); - t_aabb.defined = true; - } - } - else { - const auto t_x_aabb = m_gizmos[X].get_bounding_box(); - t_aabb.merge(t_x_aabb); - - const auto t_y_aabb = m_gizmos[Y].get_bounding_box(); - t_aabb.merge(t_y_aabb); - - const auto t_z_aabb = m_gizmos[Z].get_bounding_box(); - t_aabb.merge(t_z_aabb); - + auto t_rotate_aabb = GLGizmoRotate3D::get_bounding_box(); + if (t_rotate_aabb.defined) { + t_aabb.merge(t_rotate_aabb); t_aabb.defined = true; } // end rotate aabb @@ -539,6 +525,7 @@ void GLGizmoAdvancedCut::on_save(cereal::BinaryOutputArchive &ar) const void GLGizmoAdvancedCut::data_changed(bool is_serializing) { + reset_rotation(); if (m_hover_id < 0) { // QDT update_bb(); if (auto oc = m_c->object_clipper()) { @@ -1046,7 +1033,7 @@ void GLGizmoAdvancedCut::perform_cut(const Selection& selection) if (its_num_open_edges(new_objects[i]->volumes[j]->mesh().its) > 0) { if (!is_showed_dialog) { is_showed_dialog = true; - MessageDialog dlg(nullptr, _L("non-manifold edges be caused by cut tool, do you want to fix it now?"), "", wxYES | wxCANCEL); + MessageDialog dlg(nullptr, _L("non-manifold edges be caused by cut tool, do you want to fix it now?"), "", wxYES | wxNO); int ret = dlg.ShowModal(); if (ret == wxID_YES) { user_fix_model = true; @@ -1168,7 +1155,7 @@ Vec3d GLGizmoAdvancedCut::get_plane_center() const { return m_plane_center; } -void GLGizmoAdvancedCut::finish_rotation() +void GLGizmoAdvancedCut::reset_rotation() { for (int i = 0; i < 3; i++) { m_gizmos[i].set_angle(0.); @@ -2011,7 +1998,6 @@ void GLGizmoAdvancedCut::update_bb() m_groove.flaps_angle = m_groove.flaps_angle_init = float(PI) / 3.f; m_groove.angle = m_groove.angle_init = 0.f; m_plane.reset(); - clear_selection(); if (CommonGizmosDataObjects::SelectionInfo *selection = m_c->selection_info(); selection && selection->model_object()) m_selected.resize(selection->model_object()->cut_connectors.size(), false); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index 1753e1d..7e04c76 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -214,7 +214,7 @@ public: bool on_key(const wxKeyEvent &evt) override; double get_movement() const { return m_movement; } - void finish_rotation(); + void reset_rotation(); std::string get_tooltip() const override; BoundingBoxf3 bounding_box() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 3a0cbf3..6739734 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -227,7 +227,7 @@ bool GLGizmoBase::render_combo(const std::string &label, const std::vectorset_line_width(2.0f); Transform3d model_matrix{ Transform3d::Identity() }; - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target); p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); p_flat_shader->set_uniform("projection_matrix", proj_matrix); m_cross_mark.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); m_cross_mark.render_geometry(); - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target); p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); m_cross_mark.set_color({ 0.0f, 1.0f, 0.0f, 1.0f }); m_cross_mark.render_geometry(); - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target); p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); m_cross_mark.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); m_cross_mark.render_geometry(); @@ -370,6 +370,14 @@ void GLGizmoBase::set_highlight_color(const std::array& color) m_highlight_color = color; } +void GLGizmoBase::enable_grabber(unsigned int id , bool enable) { + if (enable) { + enable_grabber(id); + } else { + disable_grabber(id); + } +} + void GLGizmoBase::enable_grabber(unsigned int id) { if (id < m_grabbers.size()) @@ -595,7 +603,7 @@ void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup) m_parent.refresh_camera_scene_box(); } -BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const Vec3f& target, bool is_single) const +BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const Vec3f& target) const { BoundingBoxf3 t_aabb; t_aabb.reset(); @@ -604,7 +612,7 @@ BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const const auto& t_cross_aabb = m_cross_mark.get_bounding_box(); Transform3d model_matrix{ Transform3d::Identity() }; // x axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target); auto t_x_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); t_x_axis_aabb.defined = true; t_aabb.merge(t_x_axis_aabb); @@ -612,7 +620,7 @@ BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const // end x axis aabb // y axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target); auto t_y_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); t_y_axis_aabb.defined = true; t_aabb.merge(t_y_axis_aabb); @@ -620,7 +628,7 @@ BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const // end y axis aabb // z axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target, is_single); + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target); auto t_z_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); t_z_axis_aabb.defined = true; t_aabb.merge(t_z_axis_aabb); @@ -645,11 +653,11 @@ void GLGizmoBase::modify_radius(float& radius) const } } -Transform3d GLGizmoBase::get_corss_mask_model_matrix(ECrossMaskType type, const Vec3f& target, bool is_single) const +Transform3d GLGizmoBase::get_corss_mask_model_matrix(ECrossMaskType type, const Vec3f& target) const { double half_length = 4.0; - const auto center_x = is_single ? target + Vec3f(half_length * 0.5f, 0.0f, 0.0f) : target; - const float scale = is_single ? half_length : 2.0f * half_length; + const auto center_x = target; + const float scale = 2.0f * half_length; Transform3d model_matrix{ Transform3d::Identity() }; if (ECrossMaskType::X == type) { model_matrix.data()[3 * 4 + 0] = center_x.x(); @@ -660,14 +668,14 @@ Transform3d GLGizmoBase::get_corss_mask_model_matrix(ECrossMaskType type, const model_matrix.data()[2 * 4 + 2] = 1.0f; } else if (ECrossMaskType::Y == type) { - const auto center_y = is_single ? target + Vec3f(0.0f, half_length * 0.5f, 0.0f) : target; + const auto center_y = target; model_matrix = Geometry::translation_transform(center_y.cast()) * Geometry::rotation_transform({ 0.0f, 0.0f, 0.5 * PI }) * Geometry::scale_transform({ scale, 1.0f, 1.0f }); } else if (ECrossMaskType::Z == type) { - const auto center_z = is_single ? target + Vec3f(0.0f, 0.0f, half_length * 0.5f) : target; + const auto center_z = target; model_matrix = Geometry::translation_transform(center_z.cast()) * Geometry::rotation_transform({ 0.0f, -0.5 * PI, 0.0f }) * Geometry::scale_transform({ scale, 1.0f, 1.0f }); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 411ad73..fec5131 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -175,7 +175,7 @@ protected: DoubleShowType show_type = DoubleShowType::Normal); bool render_combo(const std::string &label, const std::vector &lines, size_t &selection_idx, float label_width, float item_width); - void render_cross_mark(const Transform3d& matrix, const Vec3f& target,bool is_single =false); + void render_cross_mark(const Transform3d& matrix, const Vec3f& target); static float get_grabber_size(); public: @@ -221,6 +221,7 @@ public: void set_highlight_color(const std::array& color); + void enable_grabber(unsigned int id, bool enable); void enable_grabber(unsigned int id); void disable_grabber(unsigned int id); @@ -300,7 +301,7 @@ protected: if (value <= _min) { value = _min; } } - BoundingBoxf3 get_cross_mask_aabb(const Transform3d& matrix, const Vec3f& target, bool is_single = false) const; + BoundingBoxf3 get_cross_mask_aabb(const Transform3d& matrix, const Vec3f& target) const; void modify_radius(float& radius) const; @@ -311,7 +312,7 @@ private: Y, Z }; - Transform3d get_corss_mask_model_matrix(ECrossMaskType type, const Vec3f& target, bool is_single = false) const; + Transform3d get_corss_mask_model_matrix(ECrossMaskType type, const Vec3f& target) const; private: // Flag for dirty visible state of Gizmo diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp index 1fd2ad1..20aac31 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp @@ -58,18 +58,6 @@ bool GLGizmoBrimEars::on_init() return true; } -void GLGizmoBrimEars::set_brim_data(ModelObject *model_object, const Selection &selection) -{ - if (!m_c->selection_info()) return; - - ModelObject *mo = m_c->selection_info()->model_object(); - - if (m_state == On && mo && mo->id() != m_old_mo_id) { - reload_cache(); - m_old_mo_id = mo->id(); - } -} - void GLGizmoBrimEars::on_render() { ModelObject *mo = m_c->selection_info()->model_object(); @@ -103,8 +91,16 @@ void GLGizmoBrimEars::on_render_for_picking() bool GLGizmoBrimEars::is_use_point(const BrimPoint &point) const { const Selection &selection = m_parent.get_selection(); - const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Transform3d trsf = volume->get_instance_transformation().get_matrix(); + Transform3d trsf; + if (point.volume_idx >= 0) { + const GLVolume* volume = selection.get_volume_by_object_volumn_id(point.volume_idx); + trsf = volume->world_matrix(); + }else { + const Selection& selection = m_parent.get_selection(); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + trsf = volume->get_instance_transformation().get_matrix(); + } + auto world_point = trsf * point.pos.cast(); if (world_point[2] > 0) return false; return true; @@ -128,8 +124,6 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co wxGetApp().bind_shader(shader); const GLVolume *vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d &instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d &instance_matrix = vol->get_instance_transformation().get_matrix(); const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); @@ -143,8 +137,16 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co const bool &point_selected = editing_cache[i].selected; const bool &hover = editing_cache[i].is_hover; const bool &error = editing_cache[i].is_error; + Transform3d volume_matrix = Transform3d::Identity(); if (!is_use_point(brim_point) && !hover) continue; + if (brim_point.volume_idx >= 0) { + const GLVolume* v = selection.get_volume_by_object_volumn_id(brim_point.volume_idx); + volume_matrix = v->world_matrix(); + }else { + volume_matrix = vol->get_instance_transformation().get_matrix(); + } + // keep show brim ear // if (is_mesh_point_clipped(brim_point.pos.cast())) // continue; @@ -175,7 +177,8 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - const Transform3d brim_matrix = Geometry::assemble_transform(brim_point.pos.cast()) * instance_scaling_matrix_inverse; + double radius = (double)brim_point.head_front_radius * RenderPointScale; + const Transform3d brim_matrix = Geometry::assemble_transform(brim_point.pos.cast()); if (vol->is_left_handed()) glFrontFace(GL_CW); @@ -185,13 +188,8 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co if (editing_cache[i].normal == Vec3f::Zero()) m_c->raycaster()->raycaster()->get_closest_point(editing_cache[i].brim_point.pos, &editing_cache[i].normal); - double radius = (double)brim_point.head_front_radius * RenderPointScale; - - Eigen::Quaterniond q; - q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * editing_cache[i].normal.cast()); - Eigen::AngleAxisd aa(q); - - const Transform3d view_model_matrix = view_matrix * instance_matrix * brim_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::Transformation volume_trans(volume_matrix); + const Transform3d view_model_matrix = view_matrix * volume_matrix * brim_matrix * volume_trans.get_matrix(true, false, false, true).inverse() * Geometry::assemble_transform(Vec3d(0.0, 0.0, 0.0), Vec3d(PI, 0.0, 0.0), Vec3d(radius, radius, .2)); @@ -241,8 +239,7 @@ bool GLGizmoBrimEars::unproject_on_mesh2(const Vec2d &mouse_pos, std::pairget_volume_transformation().get_matrix(); - position_on_model = (m_last_hit_volume->get_volume_transformation().get_matrix() * hit.cast()).cast(); + position_on_model = hit; normal_on_model = normal; } } @@ -260,7 +257,7 @@ bool GLGizmoBrimEars::unproject_on_mesh(const Vec2d &mouse_pos, std::pairget_camera(); const Selection &selection = m_parent.get_selection(); const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trafo = volume->get_instance_transformation(); + const auto& trafo = volume->world_matrix(); // trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));//sla shift看起来可以删掉 double clp_dist = m_c->object_clipper()->get_position(); @@ -269,7 +266,7 @@ bool GLGizmoBrimEars::unproject_on_mesh(const Vec2d &mouse_pos, std::pairraycaster()->raycaster()->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, clp_dist != 0. ? clp : nullptr)) { + if (m_c->raycaster()->raycaster()->unproject_on_mesh(mouse_pos, trafo, camera, hit, normal, clp_dist != 0. ? clp : nullptr)) { pos_and_normal = std::make_pair(hit, normal); return true; } @@ -286,6 +283,19 @@ void GLGizmoBrimEars::data_changed(bool is_serializing) reset_all_pick(); register_single_mesh_pick(); } + set_brim_data(); +} + +void GLGizmoBrimEars::set_brim_data() +{ + if (!m_c->selection_info()) return; + + ModelObject *mo = m_c->selection_info()->model_object(); + + if (m_state == On && mo && mo->id() != m_old_mo_id) { + reload_cache(); + m_old_mo_id = mo->id(); + } } // Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event. @@ -308,7 +318,10 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p Transform3d inverse_trsf = volume->get_instance_transformation().get_matrix(true).inverse(); std::pair pos_and_normal; if (unproject_on_mesh2(mouse_position, pos_and_normal)) { - render_hover_point = CacheEntry(BrimPoint(pos_and_normal.first, m_new_point_head_diameter / 2.f), false, (inverse_trsf * m_world_normal).cast(), true); + int volume_idx = m_last_hit_volume->volume_idx(); + Transform3d v_trsf = selection.get_volume_by_object_volumn_id(volume_idx)->world_matrix(); + Vec3d set_volume_trsf_pos = pos_and_normal.first.cast(); + render_hover_point = CacheEntry(BrimPoint(set_volume_trsf_pos.cast(), m_new_point_head_diameter / 2.f, volume_idx), false, (inverse_trsf * m_world_normal).cast(), true); } else { render_hover_point.reset(); } @@ -337,17 +350,18 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p std::pair pos_and_normal; if (unproject_on_mesh2(mouse_position, pos_and_normal)) { // we got an intersection + int volume_idx = m_last_hit_volume->volume_idx(); const Selection &selection = m_parent.get_selection(); - const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Transform3d trsf = volume->get_instance_transformation().get_matrix(); - Transform3d inverse_trsf = volume->get_instance_transformation().get_matrix(true).inverse(); + const GLVolume *volume = selection.get_volume_by_object_volumn_id(volume_idx); + Transform3d trsf = volume->world_matrix(); + Transform3d inverse_trsf = trsf.inverse(); // QDS brim ear postion is placed on the bottom side Vec3d world_pos = trsf * pos_and_normal.first.cast(); world_pos[2] = -0.0001; Vec3d object_pos = trsf.inverse() * world_pos; // brim ear always face up Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Add brim ear"); - add_point_to_cache(object_pos.cast(), m_new_point_head_diameter / 2.f, false, (inverse_trsf * m_world_normal).cast()); + add_point_to_cache(object_pos.cast(), m_new_point_head_diameter / 2.f, false, (inverse_trsf * m_world_normal).cast(), volume_idx); m_parent.set_as_dirty(); m_wait_for_up_event = true; find_single(); @@ -889,7 +903,7 @@ void GLGizmoBrimEars::first_layer_slicer() if (model_volume->type() == ModelVolumeType::MODEL_PART || model_volume->type() == ModelVolumeType::NEGATIVE_VOLUME) { indexed_triangle_set volume_its = model_volume->mesh().its; if (volume_its.indices.size() <= 0) continue; - Transform3d trsf = volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix(); + Transform3d trsf = volume->world_matrix(); MeshSlicingParamsEx params_ex(params); params_ex.trafo = params_ex.trafo * trsf; if (params_ex.trafo.rotation().determinant() < 0.) its_flip_triangles(volume_its); @@ -982,9 +996,9 @@ void GLGizmoBrimEars::get_detection_radius_max() } } -bool GLGizmoBrimEars::add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal) +bool GLGizmoBrimEars::add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal, int volume_idx) { - BrimPoint point(pos, head_radius); + BrimPoint point(pos, head_radius, volume_idx); for (int i = 0; i < m_editing_cache.size(); i++) { if (m_editing_cache[i].brim_point == point) { return false; } } @@ -1002,13 +1016,13 @@ void GLGizmoBrimEars::register_single_mesh_pick() GLVolume *v = const_cast(selection.get_volume(idx)); const ModelVolume* mv = get_model_volume(*v, wxGetApp().model()); if (!mv->is_model_part()) continue; - auto world_tran = v->get_instance_transformation() * v->get_volume_transformation(); + auto world_tran = v->world_matrix(); auto mesh = const_cast(v->ori_mesh); if (m_mesh_raycaster_map.find(v) != m_mesh_raycaster_map.end()) { - m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran.get_matrix()); + m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran); } else { m_mesh_raycaster_map[v] = std::make_shared(mesh, -1); - m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran.get_matrix()); + m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran); } } } @@ -1017,8 +1031,8 @@ void GLGizmoBrimEars::register_single_mesh_pick() void GLGizmoBrimEars::update_single_mesh_pick(GLVolume *v) { if (m_mesh_raycaster_map.find(v) != m_mesh_raycaster_map.end()) { - auto world_tran = v->get_instance_transformation() * v->get_volume_transformation(); - m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran.get_matrix()); + auto world_tran = v->world_matrix(); + m_mesh_raycaster_map[v]->world_tran.set_from_transform(world_tran); } } @@ -1030,11 +1044,11 @@ float GLGizmoBrimEars::get_brim_default_radius() const return pring_cfg.get_abs_value("initial_layer_line_width") * 16.0f; } -ExPolygon GLGizmoBrimEars::make_polygon(BrimPoint point, const Geometry::Transformation &trsf) +ExPolygon GLGizmoBrimEars::make_polygon(BrimPoint point, const Transform3d&trsf) { ExPolygon point_round; - Transform3d model_trsf = trsf.get_matrix(); - Vec3f world_pos = point.transform(trsf.get_matrix()); + Transform3d model_trsf = trsf; + Vec3f world_pos = point.transform(model_trsf); coord_t size_ear = scale_(point.head_front_radius); for (size_t i = 0; i < POLY_SIDE_COUNT; i++) { double angle = (2.0 * PI * i) / POLY_SIDE_COUNT; @@ -1055,7 +1069,6 @@ void GLGizmoBrimEars::find_single() } const Selection &selection = m_parent.get_selection(); const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trsf = volume->get_instance_transformation(); ExPolygons model_pl = m_first_layer; m_single_brim.clear(); @@ -1071,6 +1084,11 @@ void GLGizmoBrimEars::find_single() } auto end = --m_single_brim.end(); for (auto it = m_single_brim.begin(); it != m_single_brim.end(); ++it) { + int volume_idx = it->second.brim_point.volume_idx; + auto trsf = volume->get_instance_transformation().get_matrix(); + if (volume_idx >= 0) { + trsf = volume->world_matrix(); + } ExPolygon point_pl = make_polygon(it->second.brim_point, trsf); if (overlaps(model_pl, point_pl)) { model_pl.emplace_back(point_pl); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp index f76516c..abe4037 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp @@ -75,7 +75,6 @@ public: GLGizmoBrimEars(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoBrimEars() = default; void data_changed(bool is_serializing) override; - void set_brim_data(ModelObject* model_object, const Selection& selection); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); void delete_selected_points(); void update_model_object(); @@ -88,6 +87,7 @@ public: std::string get_gizmo_leaving_text() const override { return "Leaving Brim Ears"; } private: + void set_brim_data(); bool on_init() override; void on_update(const UpdateData& data) override; void on_render() override; @@ -164,9 +164,9 @@ protected: void register_single_mesh_pick(); void update_single_mesh_pick(GLVolume* v); void reset_all_pick(); - bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal); + bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal, int volume_idx=-1); float get_brim_default_radius() const; - ExPolygon make_polygon(BrimPoint point, const Geometry::Transformation &trsf); + ExPolygon make_polygon(BrimPoint point, const Transform3d& trsf); void find_single(); bool is_use_point(const BrimPoint &point) const; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index fdbf670..51dd57f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -29,6 +29,10 @@ GLGizmoFdmSupports::GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& ic m_cursor_type = TriangleSelector::CursorType::CIRCLE; } +void GLGizmoFdmSupports::data_changed(bool is_serializing) { + set_painter_gizmo_data(m_parent.get_selection()); +} + void GLGizmoFdmSupports::on_shutdown() { //QDS @@ -124,9 +128,9 @@ void GLGizmoFdmSupports::render_painter_gizmo() const { m_support_volume->set_render_color({ 0.f, 0.7f, 0.f, 0.7f }); - const auto& camera = GUI::wxGetApp().plater()->get_camera(); - const auto& view_matrix = camera.get_view_matrix(); - m_support_volume->render(view_matrix); + const auto & camera = m_parent.get_active_camera(); + std::vector> colors = m_parent.get_active_colors(); + m_support_volume->render(camera, colors, m_parent.get_ref_model()); } m_c->object_clipper()->render_cut(); @@ -279,7 +283,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_left_width + sliders_width - space_size; - + float window_width = minimal_slider_width + sliders_left_width + slider_icon_width; float drag_pos_times = 0.7; ImGui::AlignTextToFramePadding(); @@ -458,6 +462,11 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l } ImGui::Separator(); + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width+ m_imgui->scaled(3)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index b63a864..881bc60 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -14,7 +14,7 @@ class GLGizmoFdmSupports : public GLGizmoPainterBase { public: GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - + void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; //QDS: add edit state diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index cbafc44..29790ca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -39,7 +39,7 @@ void GLGizmoFlatten::on_set_state() CommonGizmosDataID GLGizmoFlatten::on_get_requirements() const { - return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::InstancesHider) | int(CommonGizmosDataID::Raycaster) | + return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::Raycaster)| int(CommonGizmosDataID::ObjectClipper)); } @@ -293,15 +293,6 @@ void GLGizmoFlatten::on_render_for_picking() glsafe(::glEnable(GL_CULL_FACE)); } -void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) -{ - m_starting_center = Vec3d::Zero(); - if (model_object != m_old_model_object) { - m_planes.clear(); - m_planes_valid = false; - } -} - void GLGizmoFlatten::update_planes() { const ModelObject* mo = m_c->selection_info()->model_object(); @@ -533,7 +524,7 @@ void GLGizmoFlatten::update_planes() m_first_instance_scale = mo->instances.front()->get_scaling_factor(); m_first_instance_mirror = mo->instances.front()->get_mirror(); m_old_model_object = mo; - + m_old_instance_id = m_c->selection_info()->get_active_instance(); // And finally create respective VBOs. The polygon is convex with // the vertices in order, so triangulation is trivial. for (auto& plane : m_planes) { @@ -584,5 +575,21 @@ Vec3d GLGizmoFlatten::get_flattening_normal() const return out; } +void GLGizmoFlatten::data_changed(bool is_serializing) +{ + const Selection & selection = m_parent.get_selection(); + const ModelObject *model_object = nullptr; + int instance_id = -1; + if (selection.is_single_full_instance() || selection.is_from_single_object()) { + model_object = selection.get_model()->objects[selection.get_object_idx()]; + instance_id = selection.get_instance_idx(); + } + m_starting_center = Vec3d::Zero(); + if (model_object != m_old_model_object || instance_id != m_old_instance_id) { + m_planes.clear(); + m_planes_valid = false; + } +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index b355ac1..cd21e8b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -47,8 +47,8 @@ private: public: GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - void set_flattening_data(const ModelObject* model_object); Vec3d get_flattening_normal() const; + void data_changed(bool is_serializing) override; protected: virtual bool on_init() override; @@ -68,6 +68,7 @@ private: mutable int m_last_hit_facet; mutable GLModel m_one_tri_model; Vec3f m_hit_object_normal; + int m_old_instance_id{-1}; private: bool update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector &trafo_matrices, int &facet); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index e5389de..928ca5c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -142,6 +142,10 @@ GLGizmoMmuSegmentation::GLGizmoMmuSegmentation(GLCanvas3D& parent, const std::st { } +void GLGizmoMmuSegmentation::data_changed(bool is_serializing) { + set_painter_gizmo_data(m_parent.get_selection()); +} + void GLGizmoMmuSegmentation::render_painter_gizmo() const { const Selection& selection = m_parent.get_selection(); @@ -475,7 +479,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, buttons_width); - window_width = std::max(window_width, max_filament_items_per_line * filament_item_width + +m_imgui->scaled(0.5f)); + window_width = std::max(window_width, max_filament_items_per_line * filament_item_width + m_imgui->scaled(0.5f)); const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_width - space_size; @@ -838,7 +842,11 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->disabled_end(); ImGui::Separator(); } - + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width + m_imgui->scaled(1)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 2bbc218..e2c8d6f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -66,10 +66,9 @@ class GLGizmoMmuSegmentation : public GLGizmoPainterBase public: GLGizmoMmuSegmentation(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); ~GLGizmoMmuSegmentation() override = default; - + void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; void render_non_manifold_edges() const; - void set_painter_gizmo_data(const Selection& selection) override; void render_triangles(const Selection& selection) const override; @@ -87,6 +86,7 @@ public: protected: // QDS + void set_painter_gizmo_data(const Selection &selection) override; std::array get_cursor_hover_color() const override; void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index b9dc56a..688e8e3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -60,6 +60,7 @@ std::string GLGizmoMove3D::get_tooltip() const void GLGizmoMove3D::data_changed(bool is_serializing) { + enable_grabber(2, !m_parent.get_selection().is_wipe_tower()); change_cs_by_selection(); } @@ -104,7 +105,7 @@ BoundingBoxf3 GLGizmoMove3D::get_bounding_box() const cur_tran = selection.get_first_volume()->get_instance_transformation(); } - auto t_cross_mask_aabb = get_cross_mask_aabb(cur_tran.get_matrix(), Vec3f::Zero(), true); + auto t_cross_mask_aabb = get_cross_mask_aabb(cur_tran.get_matrix(), Vec3f::Zero()); t_cross_mask_aabb.defined = true; t_aabb.merge(t_cross_mask_aabb); t_aabb.defined = true; @@ -299,7 +300,7 @@ void GLGizmoMove3D::on_render() else { cur_tran = selection.get_first_volume()->get_instance_transformation(); } - render_cross_mark(cur_tran.get_matrix(), Vec3f::Zero(), true); + render_cross_mark(cur_tran.get_matrix(), Vec3f::Zero()); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index b42ebea..f0a172b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -65,7 +65,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl // z_range is calculated in the same way as in GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) if (m_c->get_canvas()->get_use_clipping_planes()) { const std::array &clps = m_c->get_canvas()->get_clipping_planes(); - clp_data_out.z_range = {float(-clps[0].get_data()[3]), float(clps[1].get_data()[3])}; + clp_data_out.z_range = {-FLT_MAX, float(clps[1].get_data()[3])}; } return clp_data_out; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 80ca31b..6fc1a09 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -222,7 +222,6 @@ private: public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); ~GLGizmoPainterBase() override = default; - virtual void set_painter_gizmo_data(const Selection& selection); virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); // Following function renders the triangles and cursor. Having this separated @@ -242,6 +241,7 @@ public: void update_front_view_radian(); protected: + virtual void set_painter_gizmo_data(const Selection &selection); virtual void render_triangles(const Selection& selection) const; void render_cursor() const; void render_cursor_circle() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 1a7b8fa..cc94229 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -460,6 +460,7 @@ Transform3d GLGizmoRotate::calculate_circle_model_matrix() const { auto radius = m_radius; modify_radius(radius); + radius *= 1.3; Transform3d redius_scale_matrix; Geometry::scale_transform(redius_scale_matrix, { radius, radius, radius }); const Selection& selection = m_parent.get_selection(); @@ -576,35 +577,6 @@ BoundingBoxf3 GLGizmoRotate::get_bounding_box() const t_aabb.defined = true; } // end m_circle aabb - - // m_grabber_connection aabb - if (m_grabber_connection.model.is_initialized()) { - BoundingBoxf3 t_grabber_connection_aabb = m_grabber_connection.model.get_bounding_box(); - t_grabber_connection_aabb = t_grabber_connection_aabb.transformed(t_circle_model_matrix); - t_grabber_connection_aabb.defined = true; - t_aabb.merge(t_grabber_connection_aabb); - t_aabb.defined = true; - } - - - // m_grabbers aabb - if (m_grabbers.front().get_cube().is_initialized()) { - auto t_grabbers_aabb = m_grabbers.front().get_cube().get_bounding_box(); - t_grabbers_aabb = t_grabbers_aabb.transformed(m_grabbers.front().m_matrix); - t_grabbers_aabb.defined = true; - t_aabb.merge(t_grabbers_aabb); - t_aabb.defined = true; - } - // end m_grabbers aabb - - // m_cone aabb - if (m_cone.is_initialized()) { - auto t_cone_aabb = m_cone.get_bounding_box(); - t_cone_aabb = t_cone_aabb.transformed(m_grabbers.front().m_matrix); - t_cone_aabb.defined = true; - t_aabb.merge(t_cone_aabb); - t_aabb.defined = true; - } return t_aabb; } @@ -630,21 +602,18 @@ BoundingBoxf3 GLGizmoRotate3D::get_bounding_box() const BoundingBoxf3 t_aabb; t_aabb.reset(); - if (m_hover_id == -1 || m_hover_id == 0) { const auto t_x_aabb = m_gizmos[X].get_bounding_box(); t_aabb.merge(t_x_aabb); t_aabb.defined = true; } - if (m_hover_id == -1 || m_hover_id == 1) { const auto t_y_aabb = m_gizmos[Y].get_bounding_box(); t_aabb.merge(t_y_aabb); t_aabb.defined = true; } - if (m_hover_id == -1 || m_hover_id == 2) { const auto t_z_aabb = m_gizmos[Z].get_bounding_box(); t_aabb.merge(t_z_aabb); @@ -691,6 +660,14 @@ void GLGizmoRotate3D::on_set_state() void GLGizmoRotate3D::data_changed(bool is_serializing) { const Selection &selection = m_parent.get_selection(); + enable_grabber(0, !selection.is_wipe_tower()); + enable_grabber(1, !selection.is_wipe_tower()); + if (selection.is_wipe_tower()) { + DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config; + set_rotation(Vec3d(0., 0., (M_PI / 180.) * dynamic_cast(config.option("wipe_tower_rotation_angle"))->value)); + } else { + set_rotation(Vec3d::Zero()); + } const GLVolume * volume = selection.get_first_volume(); if (volume == nullptr) { m_last_volume = nullptr; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp index 9d492e8..e322db8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp @@ -613,7 +613,7 @@ void GLGizmoSVG::on_render() render_glmodel(m_move_grabber.get_cube(), render_color, view_matrix * cube_mat, projection_matrix); } #ifdef DEBUG_SVG - render_cross_mark(tran.get_matrix(), Vec3f::Zero(), true); + render_cross_mark(tran.get_matrix(), Vec3f::Zero()); #endif if (is_rotate_by_grabbers || (!is_surface_dragging && !is_parent_dragging)) { if (m_hover_id == c_move_cube_id && m_dragging) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index c6107e9..37ede46 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -84,6 +84,8 @@ std::string GLGizmoScale3D::get_tooltip() const void GLGizmoScale3D::data_changed(bool is_serializing) { + set_scale(Vec3d::Ones()); + change_cs_by_selection(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 2c53513..afcc7c1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -55,6 +55,10 @@ GLGizmoSeam::GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, u } +void GLGizmoSeam::data_changed(bool is_serializing) { + set_painter_gizmo_data(m_parent.get_selection()); +} + std::string GLGizmoSeam::on_get_name() const { @@ -226,10 +230,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float sliders_left_width = std::max(cursor_size_slider_left, clipping_slider_left); const float slider_icon_width = m_imgui->get_slider_icon_size().x; - + const float minimal_slider_width = m_imgui->scaled(4.f); const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_left_width + sliders_width - space_size; - + float window_width = minimal_slider_width + sliders_left_width + slider_icon_width; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; float textbox_width = 1.5 * slider_icon_width; @@ -349,6 +353,11 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) } m_imgui->disabled_end(); ImGui::Separator(); + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width + m_imgui->scaled(3)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index 99a982b..de232ff 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -9,7 +9,7 @@ class GLGizmoSeam : public GLGizmoPainterBase { public: GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - + void data_changed(bool is_serializing) override; void render_painter_gizmo() const override; //QDS diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 4b11ba3..8fc87b5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -656,10 +656,10 @@ void GLGizmoText::on_render() Geometry::Transformation tran(m_text_volume_tran); if (tran.get_offset().norm() > 1) { auto text_volume_tran_world = mi->get_transformation().get_matrix() * m_text_volume_tran; - render_cross_mark(text_volume_tran_world, Vec3f::Zero(), true); + render_cross_mark(text_volume_tran_world, Vec3f::Zero()); } - render_cross_mark(m_text_tran_in_world, Vec3f::Zero(), true); + render_cross_mark(m_text_tran_in_world, Vec3f::Zero()); glsafe(::glLineWidth(2.0f)); ::glBegin(GL_LINES); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 5256433..6d4b3d2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -154,8 +154,13 @@ void InstancesHider::on_update() double z_min; if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView) z_min = std::numeric_limits::max(); - else - z_min = -SINKING_Z_THRESHOLD; + else { + if (canvas->get_gizmos_manager().is_paint_gizmo()) { + z_min = -FLT_MAX; + } else { + z_min = -SINKING_Z_THRESHOLD; + } + } if (mo && active_inst != -1) { canvas->toggle_model_objects_visibility(false); @@ -420,7 +425,8 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectormodel_object(); Geometry::Transformation inst_trafo; - bool is_assem_cnv = get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView; + GLCanvas3D * canvas = get_pool()->get_canvas(); + bool is_assem_cnv = canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView; inst_trafo = is_assem_cnv ? mo->instances[sel_info->get_active_instance()]->get_assemble_transformation() : mo->instances[sel_info->get_active_instance()]->get_transformation(); auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); @@ -428,6 +434,13 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectorget_sla_shift(); std::vector ignore_idxs_local = ignore_idxs ? *ignore_idxs : std::vector(); + double z_min; + if (canvas->get_gizmos_manager().is_paint_gizmo()) { + z_min = -FLT_MAX; + } else { + z_min = -SINKING_Z_THRESHOLD; + } + for (auto &clipper : m_clippers) { auto vol_trafo = clipper.second; Geometry::Transformation trafo = inst_trafo * vol_trafo; @@ -438,7 +451,7 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectorset_plane(*m_clp); clipper.first->set_transformation(trafo); - clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), z_min)); clipper.first->render_cut(OpenGLManager::get_cut_plane_color(), &ignore_idxs_local); clipper.first->render_contour({1.f, 1.f, 1.f, 1.f}, &ignore_idxs_local); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index b8ea56e..1bfa2e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -93,9 +93,15 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const float width = get_scaled_total_width(); #if QDS_TOOLBAR_ON_TOP //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; - float top_x = std::max(m_parent.get_main_toolbar_width() + border, 0.5f * (cnv_w - width + m_parent.get_main_toolbar_width() + m_parent.get_collapse_toolbar_width() - m_parent.get_assemble_view_toolbar_width()) + border); - if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) + float top_x = 0; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width()); + } else { + const float separator_width = m_parent.get_separator_toolbar_width(); + + top_x = m_parent.get_main_toolbar_offset(); + top_x += m_parent.get_main_toolbar_width() + separator_width / 2 + border; + } float top_y = 0; float stride_x = m_layout.scaled_stride_x(); @@ -439,17 +445,6 @@ void GLGizmosManager::set_hover_id(int id) m_gizmos[m_current]->set_hover_id(id); } -void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable) -{ - if (!m_enabled || type == Undefined || m_gizmos.empty()) - return; - - if (enable) - m_gizmos[type]->enable_grabber(id); - else - m_gizmos[type]->disable_grabber(id); -} - void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos) { if (!m_enabled) @@ -477,18 +472,6 @@ void GLGizmosManager::update_data() const Selection& selection = m_parent.get_selection(); - bool is_wipe_tower = selection.is_wipe_tower(); - enable_grabber(Move, 2, !is_wipe_tower); - enable_grabber(Rotate, 0, !is_wipe_tower); - enable_grabber(Rotate, 1, !is_wipe_tower); - - // QDS: when select multiple objects, uniform scale can be deselected, display the 0-5 grabbers - //bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); - //for (unsigned int i = 0; i < 6; ++i) - //{ - // enable_grabber(Scale, i, enable_scale_xyz); - //} - if (m_common_gizmos_data) { m_common_gizmos_data->update(get_current() ? get_current()->get_requirements() @@ -497,56 +480,12 @@ void GLGizmosManager::update_data() if (m_current != Undefined) m_gizmos[m_current]->data_changed(m_serializing); - if (selection.is_single_full_instance()) - { - // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - set_scale(volume->get_instance_scaling_factor()); - set_rotation(Vec3d::Zero()); - // QDS - finish_cut_rotation(); - ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()]; - set_flattening_data(model_object); - set_sla_support_data(model_object); - set_brim_data(model_object); - set_painter_gizmo_data(); - } - else if (selection.is_single_volume() || selection.is_single_modifier()) - { - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - set_scale(volume->get_volume_scaling_factor()); - set_rotation(Vec3d::Zero()); - // QDS - finish_cut_rotation(); - set_flattening_data(nullptr); - set_sla_support_data(nullptr); - set_brim_data(nullptr); - set_painter_gizmo_data(); - } - else if (is_wipe_tower) - { - DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config; - set_scale(Vec3d::Ones()); - set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast(proj_cfg.option("wipe_tower_rotation_angle"))->value)); - set_flattening_data(nullptr); - set_sla_support_data(nullptr); - set_brim_data(nullptr); - set_painter_gizmo_data(); - } - else - { - set_scale(Vec3d::Ones()); - set_rotation(Vec3d::Zero()); - set_flattening_data(selection.is_from_single_object() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); - set_sla_support_data(selection.is_from_single_instance() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); - set_brim_data(selection.is_from_single_instance() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr); - set_painter_gizmo_data(); - } - //QDS: GUI refactor: add object manipulation in gizmo - if (!selection.is_empty()) { - m_object_manipulation.update_ui_from_settings(); - m_object_manipulation.UpdateAndShow(true); + if (m_current == EType::Move || m_current == EType::Rotate || m_current == EType::Scale) { + if (!selection.is_empty()) { + m_object_manipulation.update_ui_from_settings(); + m_object_manipulation.UpdateAndShow(true); + } } } @@ -649,12 +588,6 @@ void GLGizmosManager::set_rotation(const Vec3d& rotation) dynamic_cast(m_gizmos[Rotate].get())->set_rotation(rotation); } -// QDS -void GLGizmosManager::finish_cut_rotation() -{ - dynamic_cast(m_gizmos[Cut].get())->finish_rotation(); -} - void GLGizmosManager::update_paint_base_camera_rotate_rad() { if (m_current == MmuSegmentation || m_current == Seam) { @@ -671,45 +604,6 @@ Vec3d GLGizmosManager::get_flattening_normal() const return dynamic_cast(m_gizmos[Flatten].get())->get_flattening_normal(); } -void GLGizmosManager::set_flattening_data(const ModelObject* model_object) -{ - if (!m_enabled || m_gizmos.empty()) - return; - - dynamic_cast(m_gizmos[Flatten].get())->set_flattening_data(model_object); -} - -void GLGizmosManager::set_sla_support_data(ModelObject* model_object) -{ - if (! m_enabled - || m_gizmos.empty() - || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA) - return; - - auto* gizmo_hollow = dynamic_cast(m_gizmos[Hollow].get()); - auto* gizmo_supports = dynamic_cast(m_gizmos[SlaSupports].get()); - gizmo_hollow->set_sla_support_data(model_object, m_parent.get_selection()); - gizmo_supports->set_sla_support_data(model_object, m_parent.get_selection()); -} - -void GLGizmosManager::set_brim_data(ModelObject* model_object) -{ - if (!m_enabled || m_gizmos.empty()) - return; - auto* gizmo_brim = dynamic_cast(m_gizmos[BrimEars].get()); - gizmo_brim->set_brim_data(model_object, m_parent.get_selection()); -} - -void GLGizmosManager::set_painter_gizmo_data() -{ - if (!m_enabled || m_gizmos.empty()) - return; - - dynamic_cast(m_gizmos[FdmSupports].get())->set_painter_gizmo_data(m_parent.get_selection()); - dynamic_cast(m_gizmos[Seam].get())->set_painter_gizmo_data(m_parent.get_selection()); - dynamic_cast(m_gizmos[MmuSegmentation].get())->set_painter_gizmo_data(m_parent.get_selection()); -} - bool GLGizmosManager::is_gizmo_activable_when_single_full_instance() { if (get_current_type() == GLGizmosManager::EType::Flatten || get_current_type() == GLGizmosManager::EType::Cut || @@ -836,7 +730,7 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p return false; } -bool GLGizmosManager::is_paint_gizmo() +bool GLGizmosManager::is_paint_gizmo() const { return m_current == EType::FdmSupports || m_current == EType::MmuSegmentation || @@ -1159,7 +1053,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) processed = true; else if (!selection.is_empty() && grabber_contains_mouse()) { if (!(m_current == Measure || m_current == Assembly)) { - update_data(); + selection.start_dragging(); start_dragging(); @@ -1729,12 +1623,13 @@ void GLGizmosManager::do_render_overlay() const float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); float collapse_width = (float)m_parent.get_collapse_toolbar_width(); + float separator_width = m_parent.get_separator_toolbar_width(); //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom; + float main_toolbar_left = m_parent.get_main_toolbar_left(cnv_w, inv_zoom); //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; - zoomed_top_x = main_toolbar_left + (main_toolbar_width)*inv_zoom; + zoomed_top_x = main_toolbar_left + (main_toolbar_width + separator_width /2.f) * inv_zoom; } float zoomed_top_y = 0.5f * cnv_h * inv_zoom; #else @@ -2020,6 +1915,9 @@ bool GLGizmosManager::is_in_editing_mode(bool error_notification) const bool GLGizmosManager::is_hiding_instances() const { + if (is_paint_gizmo()) { + return false; + } return (m_common_gizmos_data && m_common_gizmos_data->instances_hider() && m_common_gizmos_data->instances_hider()->is_valid()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 003a974..95ab37d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -240,7 +240,6 @@ public: bool check_gizmos_closed_except(EType) const; void set_hover_id(int id); - void enable_grabber(EType type, unsigned int id, bool enable); void update(const Linef3& mouse_ray, const Point& mouse_pos); void update_data(); @@ -268,9 +267,6 @@ public: Vec3d get_rotation() const; void set_rotation(const Vec3d& rotation); - // QDS - void finish_cut_rotation(); - //QDS void* get_icon_texture_id(MENU_ICON_NAME icon) { if (icon_list.find((int)icon) != icon_list.end()) @@ -287,13 +283,6 @@ public: void update_paint_base_camera_rotate_rad(); Vec3d get_flattening_normal() const; - void set_flattening_data(const ModelObject* model_object); - - void set_sla_support_data(ModelObject* model_object); - void set_brim_data(ModelObject* model_object); - - void set_painter_gizmo_data(); - bool is_gizmo_activable_when_single_full_instance(); bool is_gizmo_click_empty_not_exit(); bool is_show_only_active_plate(); @@ -302,7 +291,7 @@ public: void check_object_located_outside_plate(bool change_plate =true); bool get_object_located_outside_plate() { return m_object_located_outside_plate; } bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); - bool is_paint_gizmo(); + bool is_paint_gizmo()const; bool is_allow_select_all(); ClippingPlane get_clipping_plane() const; ClippingPlane get_assemble_view_clipping_plane() const; diff --git a/src/slic3r/GUI/IMSlider.hpp b/src/slic3r/GUI/IMSlider.hpp index 56965a1..b83e9f3 100644 --- a/src/slic3r/GUI/IMSlider.hpp +++ b/src/slic3r/GUI/IMSlider.hpp @@ -131,6 +131,9 @@ public: void on_change_color_mode(bool is_dark); void set_menu_enable(bool enable = true) { m_menu_enable = enable; } + //y65 + bool get_is_can_change_color() const { return m_can_change_color; } + protected: void add_custom_gcode(std::string custom_gcode); void add_code_as_tick(Type type, int selected_extruder = -1); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index f4fe13c..920dc67 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -1138,6 +1138,10 @@ void ImGuiWrapper::tooltip(const char *label, float wrap_width) ImGui::EndTooltip(); } +void ImGuiWrapper::tooltip(const std::string &label, float wrap_width) { + tooltip(label.c_str(), wrap_width); +} + void ImGuiWrapper::tooltip(const wxString &label, float wrap_width) { ImGui::BeginTooltip(); @@ -2479,7 +2483,7 @@ void ImGuiWrapper::push_confirm_button_style() { if (m_is_dark_mode) { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255.0f, 1.f)); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255.0f, 1.f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(61.f / 255.f, 203.f / 255.f, 115.f / 255.f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(100.f / 255.f, 150.f / 255.f, 255.f / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f / 255.f, 0.f / 255.f, 121.f / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.f, 1.f, 1.f, 0.88f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 0.88f)); @@ -2487,7 +2491,7 @@ void ImGuiWrapper::push_confirm_button_style() { else { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255.0f, 1.f)); ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(68.0f/ 255.0f, 121.0f / 255.0f, 251.0f / 255.0f, 1.f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(61.f / 255.f, 203.f / 255.f, 115.f / 255.f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(100.f / 255.f, 150.f / 255.f, 255.f / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f / 255.f, 0.f / 255.f, 121.f / 255.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.f, 1.f, 1.f, 1.f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f)); diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp index 9ba2fc0..5298aa6 100644 --- a/src/slic3r/GUI/ImGuiWrapper.hpp +++ b/src/slic3r/GUI/ImGuiWrapper.hpp @@ -168,6 +168,7 @@ public: void text_wrapped(const std::string &label, float wrap_width); void text_wrapped(const wxString &label, float wrap_width); void tooltip(const char *label, float wrap_width); + void tooltip(const std::string &label, float wrap_width); void tooltip(const wxString &label, float wrap_width); void filament_group(const std::string &filament_type, const char *hex_color, unsigned char filament_id, float align_width); diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index d6db52d..bfcc061 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -230,11 +230,16 @@ void FillBedJob::process() if (m_selected.size() > 100){ // too many items, just find grid empty cells to put them - Vec2f step = unscaled(get_extents(m_selected.front().poly).size()) + Vec2f(m_selected.front().brim_width, m_selected.front().brim_width); + Vec2f step = unscaled(get_extents(m_selected.front().poly).size()) + 2 * Vec2f(m_selected.front().brim_width, m_selected.front().brim_width); + + // calc the polygon position offset based on origin, in order to normalize the initial position of the arrange polygon + auto offset_on_origin = m_selected.front().poly.contour.bounding_box().center(); + std::vector empty_cells = Plater::get_empty_cells(step); size_t n=std::min(m_selected.size(), empty_cells.size()); for (size_t i = 0; i < n; i++) { m_selected[i].translation = scaled(empty_cells[i]); + m_selected[i].translation -= offset_on_origin; m_selected[i].bed_idx= 0; } for (size_t i = n; i < m_selected.size(); i++) { diff --git a/src/slic3r/GUI/Jobs/PrintJob.cpp b/src/slic3r/GUI/Jobs/PrintJob.cpp index 1835a1f..cadc474 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.cpp +++ b/src/slic3r/GUI/Jobs/PrintJob.cpp @@ -528,8 +528,11 @@ void PrintJob::process() return true; }; - - if (params.connection_type != "lan") { + if (m_print_type == "from_sdcard_view") { + BOOST_LOG_TRIVIAL(info) << "print_job: try to send with cloud, model is sdcard view"; + this->update_status(curr_percent, _L("Sending print job through cloud service")); + result = m_agent->start_sdcard_print(params, update_fn, cancel_fn); + } else if (params.connection_type != "lan") { if (params.dev_ip.empty()) params.comments = "no_ip"; else if (this->cloud_print_only) @@ -541,12 +544,7 @@ void PrintJob::process() //use ftp only - if (m_print_type == "from_sdcard_view") { - BOOST_LOG_TRIVIAL(info) << "print_job: try to send with cloud, model is sdcard view"; - this->update_status(curr_percent, _L("Sending print job through cloud service")); - result = m_agent->start_sdcard_print(params, update_fn, cancel_fn); - } - else if (!wxGetApp().app_config->get("lan_mode_only").empty() && wxGetApp().app_config->get("lan_mode_only") == "1") { + if (!wxGetApp().app_config->get("lan_mode_only").empty() && wxGetApp().app_config->get("lan_mode_only") == "1") { if (params.password.empty() || params.dev_ip.empty()) { error_text = wxString::Format("Access code:%s Ip address:%s", params.password, params.dev_ip); diff --git a/src/slic3r/GUI/Jobs/SendJob.cpp b/src/slic3r/GUI/Jobs/SendJob.cpp index 270da90..748400a 100644 --- a/src/slic3r/GUI/Jobs/SendJob.cpp +++ b/src/slic3r/GUI/Jobs/SendJob.cpp @@ -206,8 +206,15 @@ void SendJob::process() params.dev_id = m_dev_id; params.project_name = m_project_name + ".gcode.3mf"; params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name(); - params.filename = job_data._3mf_path.string(); + + if (wxGetApp().plater()->using_exported_file()) + params.filename = wxGetApp().plater()->get_3mf_filename(); + else + params.filename = job_data._3mf_path.string(); + + params.config_filename = job_data._3mf_config_path.string(); + params.plate_index = curr_plate_idx; params.ams_mapping = this->task_ams_mapping; params.connection_type = this->connection_type; diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 622ce1c..b73490b 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -247,8 +247,9 @@ void KBShortcutsDialog::fill_shortcuts() {ctrl + "2", L("Camera view - Bottom")}, {ctrl + "3", L("Camera view - Front")}, {ctrl + "4", L("Camera view - Behind")}, - {ctrl + "5", L("Camera Angle - Left side")}, - {ctrl + "6", L("Camera Angle - Right side")}, + {ctrl + "5", L("Camera view - Left")}, + {ctrl + "6", L("Camera view - Right")}, + {ctrl + "7", L("Camera view - Isometric")}, {ctrl + "A", L("Select all objects")}, {ctrl + L("Shift+D"), L("Delete all")}, diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 83d9d64..f123dfa 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -65,6 +65,7 @@ #ifdef _WIN32 #include #include +#include #endif // _WIN32 #include @@ -735,6 +736,54 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ } #ifdef __WIN32__ +// Orca: Fix maximized window overlaps taskbar when taskbar auto hide is enabled (#8085) +// Adopted from https://gist.github.com/MortenChristiansen/6463580 +static void AdjustWorkingAreaForAutoHide(const HWND hWnd, MINMAXINFO *mmi) +{ + const auto taskbarHwnd = FindWindowA("Shell_TrayWnd", nullptr); + if (!taskbarHwnd) { return; } + const auto monitorContainingApplication = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL); + const auto monitorWithTaskbarOnIt = MonitorFromWindow(taskbarHwnd, MONITOR_DEFAULTTONULL); + if (monitorContainingApplication != monitorWithTaskbarOnIt) { return; } + APPBARDATA abd; + abd.cbSize = sizeof(APPBARDATA); + abd.hWnd = taskbarHwnd; + + // Find if task bar has auto-hide enabled + const auto uState = (UINT) SHAppBarMessage(ABM_GETSTATE, &abd); + if ((uState & ABS_AUTOHIDE) != ABS_AUTOHIDE) { return; } + + RECT borderThickness; + SetRectEmpty(&borderThickness); + AdjustWindowRectEx(&borderThickness, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, 0); + + // Determine taskbar position + SHAppBarMessage(ABM_GETTASKBARPOS, &abd); + const auto &rc = abd.rc; + if (rc.top == rc.left && rc.bottom > rc.right) { + // Left + const auto offset = borderThickness.left + 2; + mmi->ptMaxPosition.x += offset; + mmi->ptMaxTrackSize.x -= offset; + mmi->ptMaxSize.x -= offset; + } else if (rc.top == rc.left && rc.bottom < rc.right) { + // Top + const auto offset = borderThickness.top + 2; + mmi->ptMaxPosition.y += offset; + mmi->ptMaxTrackSize.y -= offset; + mmi->ptMaxSize.y -= offset; + } else if (rc.top > rc.left) { + // Bottom + const auto offset = borderThickness.bottom + 2; + mmi->ptMaxSize.y -= offset; + mmi->ptMaxTrackSize.y -= offset; + } else { + // Right + const auto offset = borderThickness.right + 2; + mmi->ptMaxSize.x -= offset; + mmi->ptMaxTrackSize.x -= offset; + } +} WXLRESULT MainFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { @@ -779,6 +828,15 @@ WXLRESULT MainFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam } } break; + case WM_GETMINMAXINFO: { + if (lParam) { + HWND hWnd = GetHandle(); + auto mmi = (MINMAXINFO *) lParam; + HandleGetMinMaxInfo(mmi); + AdjustWorkingAreaForAutoHide(hWnd, mmi); + return 0; + } + } } return wxFrame::MSWWindowProc(nMsg, wParam, lParam); } @@ -896,7 +954,7 @@ void MainFrame::update_layout() //QDS: add bed exclude area m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, {}, 0.0, {}, {}, {}, {}, true); m_plater->get_collapse_toolbar().set_enabled(false); - m_plater->collapse_sidebar(true); + m_plater->enable_sidebar(false); m_plater->Show(); break; } @@ -1133,7 +1191,7 @@ void MainFrame::init_tabpanel() m_calibration->m_print_choice->update(); } //y53 - else if (new_sel != tpMonitor){ + if (new_sel != tpMonitor){ wxString url; if (m_printer_view->GetNetMode()) { url = wxString::Format("file://%s/web/qidi/link_missing_connection.html", from_u8(resources_dir())); @@ -1704,6 +1762,11 @@ wxBoxSizer* MainFrame::create_side_tools() m_filament_group_popup = new FilamentGroupPopup(m_slice_btn); auto try_hover_pop_up = [this]() { +#ifdef __APPLE__ + if (!IsActive()) { + return; + } +#endif wxPoint pos = m_slice_btn->ClientToScreen(wxPoint(0, 0)); pos.y += m_slice_btn->GetRect().height * 1.25; pos.x -= (m_slice_option_btn->GetRect().width + FromDIP(380) * 0.6); @@ -2216,8 +2279,8 @@ void MainFrame::update_side_button_style() m_slice_btn->SetExtraSize(wxSize(FromDIP(38), FromDIP(10))); m_slice_btn->SetBottomColour(wxColour(0x3B4446));*/ StateColor m_btn_bg_enable = StateColor( - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(48, 221, 112), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) // y96 ); @@ -2581,6 +2644,16 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Right", "Camera"), "Camera") + "\t" + ctrl + "6", _L("Right View"),[mainFrame](wxCommandEvent &) { mainFrame->select_view("right"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); + append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Isometric", "Camera"), "Camera") + "\t" + ctrl + "7", _L("Isometric View"), [mainFrame](wxCommandEvent &) { mainFrame->select_view("iso"); }, "", + nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); +#if !QDT_RELEASE_TO_PUBLIC + append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Isometric", "Camera"), "Camera") + " 1", _L("Isometric View") + " 1", + [mainFrame](wxCommandEvent &) { mainFrame->select_view("iso_1"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); + append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Isometric", "Camera"), "Camera") + " 2", _L("Isometric View") + " 2", + [mainFrame](wxCommandEvent &) { mainFrame->select_view("iso_2"); },"", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); + append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Isometric", "Camera"), "Camera") + " 3", _L("Isometric View") + " 3", + [mainFrame](wxCommandEvent &) { mainFrame->select_view("iso_3"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); +#endif } void MainFrame::init_menubar_as_editor() @@ -2705,6 +2778,11 @@ void MainFrame::init_menubar_as_editor() append_menu_item(export_menu, wxID_ANY, _L("Export G-code") + dots/* + "\tCtrl+G"*/, _L("Export current plate as G-code"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(false); }, "menu_export_gcode", nullptr, [this]() {return can_export_gcode(); }, this); + + append_menu_item(export_menu, wxID_ANY, _L("Export toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), + [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "", nullptr, + [this]() {return can_export_toolpaths(); }, this); + append_menu_item( export_menu, wxID_ANY, _L("Export Preset Bundle") + dots /* + "\tCtrl+E"*/, _L("Export current configuration to files"), [this](wxCommandEvent &) { export_config(); }, diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index 4d30feb..ae99bdf 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -224,7 +224,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj) m_lan_passwd = obj->get_access_code(); m_dev_ver = obj->get_ota_version(); m_device_busy = obj->is_camera_busy_off(); - m_sdcard_exist = obj->sdcard_state == MachineObject::SdcardState::HAS_SDCARD_NORMAL || obj->sdcard_state == MachineObject::SdcardState::HAS_SDCARD_READONLY; + m_sdcard_exist = obj->sdcard_state == MachineObject::SdcardState::HAS_SDCARD_NORMAL; m_local_proto = obj->file_local; m_remote_proto = obj->get_file_remote(); m_model_download_support = obj->file_model_download; diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index c4ddff2..61baf03 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -187,7 +187,7 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj) auto close = wxGetApp().app_config->get("liveview", "auto_stop_liveview") == "true"; if (close || obj == nullptr || !obj->is_in_printing()) { m_next_retry = wxDateTime(); - Stop(_L("Temporarily closed because there is no operating for a long time.")); + Stop(_L("Temporarily closed because there is no operation for a while.")); return; } } diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index bb7410c..9e956ce 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -132,8 +132,6 @@ AddMachinePanel::~AddMachinePanel() { update_hms_tag(); e.Skip(); }); - - Bind(EVT_JUMP_TO_HMS, &MonitorPanel::jump_to_HMS, this); } MonitorPanel::~MonitorPanel() @@ -216,10 +214,10 @@ MonitorPanel::~MonitorPanel() //m_tabpanel->AddPage(m_media_file_panel, _L("Internal Storage"), "", false); m_upgrade_panel = new UpgradePanel(m_tabpanel); - m_tabpanel->AddPage(m_upgrade_panel, _L("Update"), "", false); + m_tabpanel->AddPage(m_upgrade_panel, _CTX(L_CONTEXT("Update", "Firmware"), "Firmware"), "", false); m_hms_panel = new HMSPanel(m_tabpanel); - m_tabpanel->AddPage(m_hms_panel, "HMS","", false); + m_tabpanel->AddPage(m_hms_panel, _L("Assistant(HMS)"), "", false); m_initialized = true; show_status((int)MonitorStatus::MONITOR_NO_PRINTER); diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index a945925..f220880 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -157,8 +157,8 @@ Button* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, con btn->SetCornerRadius(FromDIP(12)); StateColor btn_bg_blue( - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) ); @@ -613,13 +613,13 @@ wxBoxSizer *Newer3mfVersionDialog::get_btn_sizer() horizontal_sizer->Add(0, 0, 1, wxEXPAND, 0); // y96 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), std::pair(*wxWHITE, StateColor::Normal)); bool file_version_newer = (*m_file_version) > (*m_cloud_version); if (!file_version_newer) { - m_update_btn = new Button(this, _L("Update")); + m_update_btn = new Button(this, _CTX(L_CONTEXT("Update", "Software"), "Software")); m_update_btn->SetBackgroundColor(btn_bg_blue); m_update_btn->SetBorderColor(*wxWHITE); m_update_btn->SetTextColor(wxColour(0xFFFFFE)); @@ -731,7 +731,7 @@ NetworkErrorDialog::NetworkErrorDialog(wxWindow* parent) e.Skip(); }); - auto bt_enable = (std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + auto bt_enable = (std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_button_confirm = new Button(this, _L("Confirm")); @@ -797,7 +797,7 @@ CleanCacheDialog::CleanCacheDialog(wxWindow* parent) content_sizer->Add(vertical_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); main_sizer->Add(content_sizer, 0, wxEXPAND | wxALL, FromDIP(10)); - m_btn_bg_enable = StateColor(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + m_btn_bg_enable = StateColor(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); Button* ok_btn = new Button(this, _L("OK")); diff --git a/src/slic3r/GUI/MultiMachineManagerPage.cpp b/src/slic3r/GUI/MultiMachineManagerPage.cpp index 59e0551..669ca6c 100644 --- a/src/slic3r/GUI/MultiMachineManagerPage.cpp +++ b/src/slic3r/GUI/MultiMachineManagerPage.cpp @@ -187,7 +187,7 @@ void MultiMachineItem::doRender(wxDC& dc) else if (state_device > 2 && state_device < 7) { dc.SetFont(Label::Body_12); dc.SetTextForeground(wxColour(68, 121, 251)); - if (obj_->get_curr_stage().IsEmpty() && obj_->subtask_) { + if (obj_->get_curr_stage() == _L("Printing") && obj_->subtask_) { //wxString layer_info = wxString::Format(_L("Layer: %d/%d"), obj_->curr_layer, obj_->total_layers); wxString progress_info = wxString::Format("%d", obj_->subtask_->task_progress); wxString left_time = wxString::Format("%s", get_left_time(obj_->mc_left_time)); @@ -281,8 +281,8 @@ MultiMachineManagerPage::MultiMachineManagerPage(wxWindow* parent) //edit prints auto m_btn_bg_enable = StateColor( - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) ); diff --git a/src/slic3r/GUI/MultiTaskManagerPage.cpp b/src/slic3r/GUI/MultiTaskManagerPage.cpp index 5141830..a5b40e2 100644 --- a/src/slic3r/GUI/MultiTaskManagerPage.cpp +++ b/src/slic3r/GUI/MultiTaskManagerPage.cpp @@ -34,8 +34,8 @@ MultiTaskItem::MultiTaskItem(wxWindow* parent, MachineObject* obj, int type) // y96 auto m_btn_bg_enable = StateColor( - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) ); @@ -387,7 +387,7 @@ void MultiTaskItem::doRender(wxDC& dc) else if (state_device > 2 && state_device < 7) { dc.SetFont(Label::Body_12); dc.SetTextForeground(wxColour(68, 121, 251)); - if (obj_->get_curr_stage().IsEmpty()) { + if (obj_->get_curr_stage() == _L("Printing") && obj_->subtask_) { //wxString layer_info = wxString::Format(_L("Layer: %d/%d"), obj_->curr_layer, obj_->total_layers); wxString progress_info = wxString::Format("%d", obj_->subtask_->task_progress); wxString left_time = wxString::Format("%s", get_left_time(obj_->mc_left_time)); diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 778c53b..a0db00a 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1790,7 +1790,6 @@ void NotificationManager::push_slicing_customize_error_notification(Notification set_all_slicing_errors_gray(false); std::string prefix_msg = level == NotificationLevel::WarningNotificationLevel ? _u8L("Warning:") : _u8L("Error:"); push_notification_data({type, level, 0, prefix_msg + "\n" + text, hypertext, callback}, 0); - set_slicing_progress_hidden(); } void NotificationManager::close_slicing_customize_error_notification(NotificationType type, NotificationLevel level) @@ -1802,6 +1801,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, QDT_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 @@ -1818,8 +1859,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) @@ -2389,15 +2429,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->qdt_render_block_notification(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale); + notification->qdt_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; } @@ -2527,24 +2577,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::QDTPlateInfo) - 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::QDTObjectInfo) - notification->hide(preview); + notification->hide(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D); if (notification->get_type() == NotificationType::QDTSeqPrintInfo) - notification->hide(preview); - if (m_in_preview && notification->get_type() == NotificationType::DidYouKnowHint) - notification->close(); - if (notification->get_type() == NotificationType::ValidateWarning) - notification->hide(preview); + 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(m_canvas_type != GLCanvas3D::ECanvasType::CanvasView3D); } } @@ -2959,4 +3009,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 be12018..04ede51 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -154,6 +154,8 @@ enum class NotificationType QDTSliceMultiExtruderHeightOutside, QDTBedFilamentIncompatible, QDTMixUsePLAAndPETG, + AssemblyWarning, + AssemblyInfo, NotificationTypeCount }; @@ -247,6 +249,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()); @@ -305,9 +313,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 @@ -811,6 +819,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; @@ -879,9 +896,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/ObjColorDialog.cpp b/src/slic3r/GUI/ObjColorDialog.cpp index 79337cc..0605342 100644 --- a/src/slic3r/GUI/ObjColorDialog.cpp +++ b/src/slic3r/GUI/ObjColorDialog.cpp @@ -40,8 +40,8 @@ static void update_ui(wxWindow* window) static const char g_min_cluster_color = 1; static const char g_max_color = (int) EnforcerBlockerType::ExtruderMax; -const StateColor ok_btn_bg(std::pair(wxColour(27, 136, 68), StateColor::Pressed), - std::pair(wxColour(61, 203, 115), StateColor::Hovered), +const StateColor ok_btn_bg(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); const StateColor ok_btn_disable_bg(std::pair(wxColour(205, 201, 201), StateColor::Pressed), std::pair(wxColour(205, 201, 201), StateColor::Hovered), @@ -89,8 +89,8 @@ wxBoxSizer* ObjColorDialog::create_btn_sizer(long flags,bool exist_error) std::pair(wxColour(38, 46, 48), StateColor::Normal) ); StateColor calc_btn_bg( - std::pair(wxColour(95, 82, 253), StateColor::Pressed), - std::pair(wxColour(129, 150, 255), StateColor::Hovered), + std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal) ); StateColor calc_btn_bd( @@ -200,7 +200,7 @@ ObjColorDialog::ObjColorDialog(wxWindow *parent, Slic3r::ObjDialogInOut &in_out, else { wxBoxSizer * error_mtl_sizer = new wxBoxSizer(wxVERTICAL); - wxStaticText *error_mtl_title = new wxStaticText(this, wxID_ANY, _L("Some faces not define color.")); + wxStaticText *error_mtl_title = new wxStaticText(this, wxID_ANY, _L("Some faces don't have color defined.")); if (!in_out.lost_material_name.empty()) { error_mtl_title->SetLabel(_L("mtl file exist error,could not find the material:") + " " + in_out.lost_material_name + "."); } @@ -236,7 +236,7 @@ ObjColorDialog::ObjColorDialog(wxWindow *parent, Slic3r::ObjDialogInOut &in_out, EndModal(wxCANCEL); return; } - m_panel_ObjColor->clear_instance(); + m_panel_ObjColor->clear_instance_and_revert_offset(); m_panel_ObjColor->send_new_filament_to_ui(); EndModal(wxID_OK); }, wxID_OK); @@ -360,9 +360,11 @@ ObjColorPanel::ObjColorPanel(wxWindow *parent, Slic3r::ObjDialogInOut &in_out, c auto mo = m_obj_in_out.model->objects[0]; mo->add_instance(); auto mv = mo->volumes[0]; + m_thumbnail_offset = Slic3r::Vec3d::Zero(); auto box = mo->bounding_box(); if (box.min.x() < 0 || box.min.y() < 0 || box.min.z() < 0) { - mv->translate(box.min.x() < 0 ? -box.min.x() : 0, box.min.y() < 0 ? -box.min.y() : 0, box.min.z() < 0 ? -box.min.z() : 0); + m_thumbnail_offset = Slic3r::Vec3d(box.min.x() < 0 ? -box.min.x() : 0, box.min.y() < 0 ? -box.min.y() : 0, box.min.z() < 0 ? -box.min.z() : 0); + mv->translate(m_thumbnail_offset); } } @@ -521,7 +523,7 @@ void ObjColorPanel::cancel_paint_color() { m_filament_ids.clear(); auto mo = m_obj_in_out.model->objects[0]; mo->config.set("extruder", 1); - clear_instance(); + clear_instance_and_revert_offset(); auto mv = mo->volumes[0]; mv->mmu_segmentation_facets.reset(); mv->config.set("extruder", 1); @@ -558,7 +560,7 @@ wxBoxSizer *ObjColorPanel::create_approximate_match_btn_sizer(wxWindow *parent) { auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); // y96 - StateColor calc_btn_bg(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor calc_btn_bg(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_bd(std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); @@ -584,7 +586,7 @@ wxBoxSizer *ObjColorPanel::create_approximate_match_btn_sizer(wxWindow *parent) wxBoxSizer *ObjColorPanel::create_add_btn_sizer(wxWindow *parent) { auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); - StateColor calc_btn_bg(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor calc_btn_bg(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_bd(std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); @@ -610,7 +612,7 @@ wxBoxSizer *ObjColorPanel::create_add_btn_sizer(wxWindow *parent) wxBoxSizer *ObjColorPanel::create_reset_btn_sizer(wxWindow *parent) { auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); - StateColor calc_btn_bg(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor calc_btn_bg(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_bd(std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); @@ -935,10 +937,15 @@ void ObjColorPanel::set_view_angle_type(int value) } -void ObjColorPanel::clear_instance() +void ObjColorPanel::clear_instance_and_revert_offset() { auto mo = m_obj_in_out.model->objects[0]; mo->clear_instances(); + auto mv = mo->volumes[0]; + auto box = mo->bounding_box(); + if (!m_thumbnail_offset.isApprox(Slic3r::Vec3d::Zero())) { + mv->translate(-m_thumbnail_offset); + } } bool ObjColorPanel::do_show(bool show) { diff --git a/src/slic3r/GUI/ObjColorDialog.hpp b/src/slic3r/GUI/ObjColorDialog.hpp index c234112..c635d02 100644 --- a/src/slic3r/GUI/ObjColorDialog.hpp +++ b/src/slic3r/GUI/ObjColorDialog.hpp @@ -36,7 +36,7 @@ public: void set_layout_callback(LayoutChanggeCallback); void do_layout_callback(); bool do_show(bool show); - void clear_instance(); + void clear_instance_and_revert_offset(); private: wxBoxSizer *create_approximate_match_btn_sizer(wxWindow *parent); @@ -105,6 +105,8 @@ private: bool m_is_add_filament{false}; unsigned char& m_first_extruder_id; std::vector &m_filament_ids; + + Slic3r::Vec3d m_thumbnail_offset; }; class ObjColorDialog : public Slic3r::GUI::DPIDialog diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 0a6d895..bcca692 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -316,6 +316,7 @@ OpenGLManager::EMultisampleState OpenGLManager::s_multisample = OpenGLManager::E OpenGLManager::EFramebufferType OpenGLManager::s_framebuffers_type = OpenGLManager::EFramebufferType::Unknown; bool OpenGLManager::s_b_initialized = false; ColorRGBA OpenGLManager::s_cut_plane_color = {1.0f, 0.37f, 0.0f, 1.0f}; +bool OpenGLManager::s_cancle_glmultidraw = false; #ifdef __APPLE__ // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets OpenGLManager::OSInfo OpenGLManager::s_os_info; @@ -852,6 +853,34 @@ const ColorRGBA &OpenGLManager::get_cut_plane_color(){ return s_cut_plane_color; } +unsigned int OpenGLManager::get_draw_primitive_type(EDrawPrimitiveType type) +{ + switch (type) { + case EDrawPrimitiveType::Points: { + return GL_POINTS; + } + default: + case EDrawPrimitiveType::Triangles: { + return GL_TRIANGLES; + } + case EDrawPrimitiveType::TriangleStrip: { + return GL_TRIANGLE_STRIP; + } + case EDrawPrimitiveType::TriangleFan: { + return GL_TRIANGLE_FAN; + } + case EDrawPrimitiveType::Lines: { + return GL_LINES; + } + case EDrawPrimitiveType::LineStrip: { + return GL_LINE_STRIP; + } + case EDrawPrimitiveType::LineLoop: { + return GL_LINE_LOOP; + } + } +} + void OpenGLManager::detect_multisample(int* attribList) { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index a693cad..dc941ac 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -45,6 +45,16 @@ enum class EPixelDataType : uint16_t Float }; +enum class EDrawPrimitiveType : uint8_t{ + Points, + Triangles, + TriangleStrip, + TriangleFan, + Lines, + LineStrip, + LineLoop +}; + struct FrameBufferParams { uint32_t m_width{ 0 }; @@ -232,6 +242,7 @@ private: static EFramebufferType s_framebuffers_type; static bool m_use_manually_generated_mipmaps; static ColorRGBA s_cut_plane_color; + static bool s_cancle_glmultidraw; public: OpenGLManager(); @@ -280,6 +291,9 @@ public: static bool use_manually_generated_mipmaps() { return m_use_manually_generated_mipmaps; } static void set_cut_plane_color(ColorRGBA); static const ColorRGBA &get_cut_plane_color(); + static bool get_cancle_glmultidraw() { return s_cancle_glmultidraw; } + static void set_cancle_glmultidraw(bool flag) { s_cancle_glmultidraw = flag; } + static unsigned int get_draw_primitive_type(EDrawPrimitiveType type); private: static void detect_multisample(int* attribList); diff --git a/src/slic3r/GUI/ParamsPanel.cpp b/src/slic3r/GUI/ParamsPanel.cpp index 367af5e..9e71958 100644 --- a/src/slic3r/GUI/ParamsPanel.cpp +++ b/src/slic3r/GUI/ParamsPanel.cpp @@ -54,7 +54,7 @@ TipsDialog::TipsDialog(wxWindow *parent, const wxString &title, const wxString & wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL); auto dont_show_again = create_item_checkbox(_L("Don't show again"), this, _L("Don't show again"), "do_not_show_tips"); - m_sizer_left->Add(dont_show_again, 1, wxALL, FromDIP(5)); + m_sizer_left->Add(dont_show_again, 1, wxALL, FromDIP(0)); m_sizer_bottom->Add(m_sizer_left, 1, wxEXPAND, FromDIP(5)); @@ -105,7 +105,7 @@ wxBoxSizer *TipsDialog::create_item_checkbox(wxString title, wxWindow *parent, w { wxBoxSizer *m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL); - m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 5); + //m_sizer_checkbox->Add(0, 0, 0, wxEXPAND | wxLEFT, 5); auto checkbox = new ::CheckBox(parent); m_sizer_checkbox->Add(checkbox, 0, wxALIGN_CENTER, 0); @@ -131,8 +131,8 @@ wxBoxSizer *TipsDialog::create_item_checkbox(wxString title, wxWindow *parent, w Button *TipsDialog::add_button(wxWindowID btn_id, const wxString &label, bool set_focus /*= false*/) { Button* btn = new Button(this, label, "", 0, 0, btn_id); - StateColor btn_bg_blue(std::pair(wxColour(54, 97, 201), StateColor::Pressed), - std::pair(wxColour(78, 133, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), + std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bd_blue(std::pair(wxColour(68, 121, 251), StateColor::Normal)); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 4aa6fc3..a9fee2e 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1239,7 +1239,7 @@ std::vector PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D bool PartPlate::check_objects_empty_and_gcode3mf(std::vector &result) const { if (m_model->objects.empty()) {//objects is empty - if (wxGetApp().plater()->is_gcode_3mf()) { // if gcode.3mf file + if (wxGetApp().plater() && wxGetApp().plater()->is_gcode_3mf()) { // if gcode.3mf file for (int i = 0; i < slice_filaments_info.size(); i++) { result.push_back(slice_filaments_info[i].id + 1); } @@ -1348,17 +1348,12 @@ bool PartPlate::check_filament_printable(const DynamicPrintConfig &config, wxStr for (auto filament_idx : used_filaments) { int filament_id = filament_idx - 1; std::string filament_type = config.option("filament_type")->values.at(filament_id); + int filament_printable_status = config.option("filament_printable")->values.at(filament_id); std::vector filament_map = get_real_filament_maps(config); int extruder_idx = filament_map[filament_id] - 1; - std::string filament_types_str; - auto unprintable_filament_types = config.option("unprintable_filament_types")->values; - if (extruder_idx < unprintable_filament_types.size()) - filament_types_str = unprintable_filament_types.at(extruder_idx); - std::vector filament_types = split_string(filament_types_str, ','); - auto iter = std::find(filament_types.begin(), filament_types.end(), filament_type); - if (iter != filament_types.end()) { + if (!(filament_printable_status >> extruder_idx & 1)) { wxString extruder_name = extruder_idx == 0 ? _L("left") : _L("right"); - error_message = wxString::Format(_L("The %s nozzle can not print %s."), extruder_name, filament_type); + error_message = wxString::Format(_L("The %s nozzle can not print %s."), extruder_name, filament_type); return false; } } @@ -1368,10 +1363,8 @@ bool PartPlate::check_filament_printable(const DynamicPrintConfig &config, wxStr bool PartPlate::check_tpu_printable_status(const DynamicPrintConfig & config, const std::vector &tpu_filaments) { - bool tpu_valid = true; - - // only support at most 1 tpu - return tpu_filaments.size() <=1; + // do not limit the num of tpu filament in slicing + return true; } bool PartPlate::check_mixture_of_pla_and_petg(const DynamicPrintConfig &config) @@ -3206,11 +3199,6 @@ void PartPlateList::init() m_plate_cols = 1; m_current_plate = 0; - if (m_plater) { - // In GUI mode - set_default_wipe_tower_pos_for_plate(0); - } - select_plate(0); unprintable_plate.set_index(1); @@ -3767,7 +3755,7 @@ void PartPlateList::release_icon_textures() } } -void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx) +void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool init_pos) { DynamicConfig & proj_cfg = wxGetApp().preset_bundle->project_config; ConfigOptionFloats *wipe_tower_x = proj_cfg.opt("wipe_tower_x"); @@ -3777,12 +3765,61 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx) auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option>("printer_structure"); // set the default position, the same with print config(left top) - ConfigOptionFloat wt_x_opt(WIPE_TOWER_DEFAULT_X_POS); - ConfigOptionFloat wt_y_opt(WIPE_TOWER_DEFAULT_Y_POS); + float x = WIPE_TOWER_DEFAULT_X_POS; + float y = WIPE_TOWER_DEFAULT_Y_POS; if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) { - wt_x_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_X_POS); - wt_y_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_Y_POS); + x = I3_WIPE_TOWER_DEFAULT_X_POS; + y = I3_WIPE_TOWER_DEFAULT_Y_POS; } + + const float margin = WIPE_TOWER_MARGIN; + PartPlate* part_plate = get_plate(plate_idx); + Vec3d plate_origin = part_plate->get_origin(); + BoundingBoxf3 plate_bbox = part_plate->get_bounding_box(); + BoundingBoxf plate_bbox_2d(Vec2d(plate_bbox.min(0), plate_bbox.min(1)), Vec2d(plate_bbox.max(0), plate_bbox.max(1))); + const std::vector &extruder_areas = part_plate->get_extruder_areas(); + for (Pointfs points : extruder_areas) { + BoundingBoxf bboxf(points); + plate_bbox_2d.min = plate_bbox_2d.min(0) >= bboxf.min(0) ? plate_bbox_2d.min : bboxf.min; + plate_bbox_2d.max = plate_bbox_2d.max(0) <= bboxf.max(0) ? plate_bbox_2d.max : bboxf.max; + } + + coordf_t plate_bbox_x_min_local_coord = plate_bbox_2d.min(0) - plate_origin(0); + coordf_t plate_bbox_x_max_local_coord = plate_bbox_2d.max(0) - plate_origin(0); + coordf_t plate_bbox_y_max_local_coord = plate_bbox_2d.max(1) - plate_origin(1); + + std::vector filament_maps = part_plate->get_real_filament_maps(proj_cfg); + DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(false, filament_maps); + const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; + float w = dynamic_cast(print_cfg.option("prime_tower_width"))->value; + std::vector v = dynamic_cast(full_config.option("filament_prime_volume"))->values; + int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count(); + double wipe_vol = get_max_element(v); + Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, init_pos ? 2 : 0); + + if (!init_pos && (is_approx(wipe_tower_size(0), 0.0) || is_approx(wipe_tower_size(1), 0.0))) { + wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 2); + } + + // update for wipe tower position + { + bool need_update = false; + if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) { + x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin; + } else if (x < margin + plate_bbox_x_min_local_coord) { + x = margin + plate_bbox_x_min_local_coord; + } + + if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) { + y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin; + } else if (y < margin) { + y = margin; + } + } + + ConfigOptionFloat wt_x_opt(x); + ConfigOptionFloat wt_y_opt(y); + dynamic_cast(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_idx, 0); dynamic_cast(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_idx, 0); } @@ -3893,6 +3930,11 @@ void PartPlateList::reinit() //re-calc the bounding boxes calc_bounding_boxes(); + if (m_plater) { + // In GUI mode + set_default_wipe_tower_pos_for_plate(0, true); + } + return; } @@ -3961,7 +4003,7 @@ int PartPlateList::create_plate(bool adjust_position) // update wipe tower config if (m_plater) { // In GUI mode - set_default_wipe_tower_pos_for_plate(new_index); + set_default_wipe_tower_pos_for_plate(new_index, true); } unprintable_plate.set_index(new_index+1); @@ -4146,6 +4188,32 @@ void PartPlateList::delete_selected_plate() delete_plate(m_current_plate); } +bool PartPlateList::check_all_plate_local_bed_type(const std::vector &cur_bed_types) +{ + std::string bed_type_key = "curr_bed_type"; + bool is_ok = true; + for (int i = 0; i < m_plate_list.size(); i++) { + PartPlate *plate = m_plate_list[i]; + if (plate->config() && plate->config()->has(bed_type_key)) { + BedType bed_type = plate->config()->opt_enum(bed_type_key); + if (bed_type == BedType::btDefault) + continue; + bool find = false; + for (auto tmp_type : cur_bed_types) { + if (bed_type == tmp_type) { + find = true; + break; + } + } + if (!find) { + plate->set_bed_type(BedType::btDefault); + is_ok = false; + } + } + } + return is_ok; +} + //get a plate pointer by index PartPlate* PartPlateList::get_plate(int index) { @@ -4329,11 +4397,6 @@ void PartPlateList::update_all_plates_pos_and_size(bool adjust_position, bool wi //compute origin1 for PartPlate origin1 = compute_origin(i, m_plate_cols); plate->set_pos_and_size(origin1, m_plate_width, m_plate_depth, m_plate_height, adjust_position, do_clear); - - // set default wipe pos when switch plate - if (switch_plate_type && m_plater/* && plate->get_used_extruders().size() <= 0*/) { - set_default_wipe_tower_pos_for_plate(i); - } } origin2 = compute_origin_for_unprintable(); diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 9820f99..8a79f81 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -603,8 +603,6 @@ class PartPlateList : public ObjectBase void generate_icon_textures(); void release_icon_textures(); - void set_default_wipe_tower_pos_for_plate(int plate_idx); - friend class cereal::access; friend class UndoRedo::StackImpl; friend class PartPlate; @@ -737,6 +735,7 @@ public: //int delete_plate(PartPlate* plate); void delete_selected_plate(); + bool check_all_plate_local_bed_type(const std::vector& cur_bed_types); //get a plate pointer by index PartPlate* get_plate(int index); @@ -762,6 +761,7 @@ public: std::vector get_nonempty_plate_list(); std::vector get_nonempty_plates_slice_results(); + void set_default_wipe_tower_pos_for_plate(int plate_idx, bool init_pos = false); //compute the origin for printable plate with index i Vec3d get_current_plate_origin() { return compute_origin(m_current_plate, m_plate_cols); } diff --git a/src/slic3r/GUI/PlateSettingsDialog.cpp b/src/slic3r/GUI/PlateSettingsDialog.cpp index a0fba18..5637c4c 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.cpp +++ b/src/slic3r/GUI/PlateSettingsDialog.cpp @@ -381,8 +381,25 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title // Plate type m_bed_type_choice = new ComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240),-1), 0, NULL, wxCB_READONLY ); - for (BedType i = btDefault; i < btCount; i = BedType(int(i) + 1)) { - m_bed_type_choice->Append(to_bed_type_name(i)); + auto pm = wxGetApp().plater()->get_curr_printer_model(); + if (pm) { + m_cur_combox_bed_types.clear(); + m_bed_type_choice->AppendString(_L("Same as Global Plate Type")); + const ConfigOptionDef *bed_type_def = print_config_def.get("curr_bed_type"); + int index = 0; + for (auto item : bed_type_def->enum_labels) { + index++; + bool find = std::find(pm->not_support_bed_types.begin(), pm->not_support_bed_types.end(), item) != pm->not_support_bed_types.end(); + if (!find) { + m_bed_type_choice->AppendString(_L(item)); + m_cur_combox_bed_types.emplace_back(BedType(index)); + } + } + + } else { + for (BedType i = btDefault; i < btCount; i = BedType(int(i) + 1)) { + m_bed_type_choice->Append(to_bed_type_name(i)); + } } wxStaticText* m_bed_type_txt = new wxStaticText(this, wxID_ANY, _L("Bed type")); m_bed_type_txt->SetFont(Label::Body_14); @@ -451,7 +468,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title auto sizer_button = new wxBoxSizer(wxHORIZONTAL); // y96 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), @@ -528,7 +545,13 @@ PlateSettingsDialog::~PlateSettingsDialog() void PlateSettingsDialog::sync_bed_type(BedType type) { if (m_bed_type_choice != nullptr) { - m_bed_type_choice->SetSelection(int(type)); + for (int i = 0; i < m_cur_combox_bed_types.size(); i++) { + if (m_cur_combox_bed_types[i] == type) { + m_bed_type_choice->SetSelection(i + 1);//+1 because same as global + return; + } + } + m_bed_type_choice->SetSelection(0); } } @@ -615,6 +638,17 @@ void PlateSettingsDialog::on_dpi_changed(const wxRect& suggested_rect) m_button_cancel->Rescale(); } +BedType PlateSettingsDialog::get_bed_type_choice() +{ + if (m_bed_type_choice != nullptr) { + int choice = m_bed_type_choice->GetSelection(); + if (choice > 0) { + return m_cur_combox_bed_types[choice - 1];//-1 because same as globlal + } + } + return BedType::btDefault; +}; + std::vector PlateSettingsDialog::get_first_layer_print_seq() { return m_drag_canvas->get_shape_list_order(); @@ -656,7 +690,7 @@ PlateNameEditDialog::PlateNameEditDialog(wxWindow *parent, wxWindowID id, const m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxALL, FromDIP(30)); auto sizer_button = new wxBoxSizer(wxHORIZONTAL); - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), diff --git a/src/slic3r/GUI/PlateSettingsDialog.hpp b/src/slic3r/GUI/PlateSettingsDialog.hpp index 3f43afd..69f3f3c 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.hpp +++ b/src/slic3r/GUI/PlateSettingsDialog.hpp @@ -112,14 +112,9 @@ public: if (m_print_seq_choice != nullptr) choice = m_print_seq_choice->GetSelection(); return choice; - }; + } - int get_bed_type_choice() { - int choice = 0; - if (m_bed_type_choice != nullptr) - choice = m_bed_type_choice->GetSelection(); - return choice; - }; + BedType get_bed_type_choice(); int get_first_layer_print_seq_choice() { int choice = 0; @@ -164,6 +159,7 @@ protected: protected: ComboBox* m_bed_type_choice { nullptr }; + std::vector m_cur_combox_bed_types; ComboBox* m_print_seq_choice { nullptr }; ComboBox* m_first_layer_print_seq_choice { nullptr }; ComboBox* m_spiral_mode_choice { nullptr }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 250a6fd..89a07ba 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -38,6 +38,7 @@ #endif #include #include +#include #include "libslic3r/libslic3r.h" #include "libslic3r/Format/STL.hpp" @@ -423,7 +424,7 @@ struct Sidebar::priv ExtruderGroup *single_extruder = nullptr; int FromDIP(int n) { return plater->FromDIP(n); } - void layout_printer(bool isQDT, bool isDual); + void layout_printer(bool is_support_box, bool isDual); void flush_printer_sync(bool restart = false); @@ -449,7 +450,7 @@ struct Sidebar::priv ScalableButton * m_bpButton_box_filament; ScalableButton * m_bpButton_set_filament; int m_menu_filament_id = -1; - wxPanel* m_panel_filament_content; + wxScrolledWindow* m_panel_filament_content; wxScrolledWindow* m_scrolledWindow_filament_content; wxStaticLine* m_staticline2; wxPanel* m_panel_project_title; @@ -475,7 +476,6 @@ struct Sidebar::priv //ScalableButton *btn_eject_device; ScalableButton* btn_export_gcode_removable; //exports to removable drives (appears only if removable drive is connected) - bool is_collapsed {false}; bool is_switching_diameter{false}; Search::OptionsSearcher searcher; std::string ams_list_device; @@ -499,18 +499,18 @@ struct Sidebar::priv #endif }; -void Sidebar::priv::layout_printer(bool isQDT, bool isDual) +void Sidebar::priv::layout_printer(bool is_support_box, bool isDual) { - isDual = isDual && isQDT; // It indicates a multi-extruder layout. + isDual = isDual && is_support_box; // It indicates a multi-extruder layout. // Printer - preset if (auto sizer = static_cast(panel_printer_preset->GetSizer()); - sizer == nullptr || isDual != (sizer->GetOrientation() == wxVERTICAL)) { + sizer == nullptr || is_support_box != (sizer->GetOrientation() == wxVERTICAL)) { wxBoxSizer *hsizer_printer_btn = new wxBoxSizer(wxHORIZONTAL); hsizer_printer_btn->AddStretchSpacer(1); hsizer_printer_btn->Add(btn_edit_printer, 0); hsizer_printer_btn->Add(btn_connect_printer, 0, wxALIGN_CENTER | wxLEFT, FromDIP(4)); - combo_printer->SetWindowStyle(combo_printer->GetWindowStyle() & ~wxALIGN_MASK | (isDual ? wxALIGN_CENTER_HORIZONTAL : wxALIGN_RIGHT)); - if (isDual) { + combo_printer->SetWindowStyle(combo_printer->GetWindowStyle() & ~wxALIGN_MASK | (is_support_box ? wxALIGN_CENTER_HORIZONTAL : wxALIGN_RIGHT)); + if (is_support_box) { wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->AddStretchSpacer(1); @@ -521,7 +521,6 @@ void Sidebar::priv::layout_printer(bool isQDT, bool isDual) vsizer->Add(hsizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(8)); vsizer->Add(combo_printer, 0, wxEXPAND | wxALL, FromDIP(4)); panel_printer_preset->SetSizer(vsizer); - panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE_SMALL); } else { wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(image_printer, 0, wxLEFT | wxALIGN_CENTER, FromDIP(4)); @@ -529,7 +528,6 @@ void Sidebar::priv::layout_printer(bool isQDT, bool isDual) hsizer->Add(hsizer_printer_btn, 0, wxALIGN_TOP | wxTOP | wxRIGHT, FromDIP(4)); hsizer->AddSpacer(FromDIP(10)); panel_printer_preset->SetSizer(hsizer); - panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE_WIDEN); } } @@ -556,9 +554,10 @@ void Sidebar::priv::layout_printer(bool isQDT, bool isDual) vsizer_printer->AddSpacer(FromDIP(4)); } - //y + //y65 //btn_connect_printer->Show(!isQDT); - btn_sync_printer->Show(isDual); + bool isQDT = true; + btn_sync_printer->Show(is_support_box); panel_printer_bed->Show(isQDT); vsizer_printer->GetItem(2)->GetSizer()->GetItem(1)->Show(isDual); vsizer_printer->GetItem(2)->Show(isQDT && isDual); @@ -571,7 +570,7 @@ void Sidebar::priv::flush_printer_sync(bool restart) *counter_sync_printer = 6; timer_sync_printer->Start(500); } - btn_sync_printer->SetBackgroundColorNormal((*counter_sync_printer & 1) ? 0xF8F8F8 : 0x4479fb); + btn_sync_printer->SetBackgroundColorNormal((*counter_sync_printer & 1) ? "#F8F8F8" : "#4479fb"); if (--*counter_sync_printer <= 0) timer_sync_printer->Stop(); } @@ -847,7 +846,7 @@ public: Bind(wxEVT_PAINT, [this](wxPaintEvent& evt) { wxPaintDC dc(this); - dc.SetPen(wxColour(0xEEEEEE)); + dc.SetPen(wxColour("#EEEEEE")); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); }); @@ -904,8 +903,8 @@ ExtruderGroup::ExtruderGroup(wxWindow * parent, int index, wxString const &title : StaticGroup(parent, wxID_ANY, title) { SetFont(Label::Body_10); - SetForegroundColour(wxColour(0xCECECE)); - SetBorderColor(wxColour(0xEEEEEE)); + SetForegroundColour(wxColour("#CECECE")); + SetBorderColor(wxColour("#EEEEEE")); ShowBadge(true); // Nozzle wxStaticText *label_diameter = new wxStaticText(this, wxID_ANY, _L("Diameter")); @@ -1153,10 +1152,10 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::NOT_CONNECTED, _L("Sync printer information")); return false; } - if (obj->m_extder_data.extders.size() != 2) {//wxString(obj->get_preset_printer_model_name(machine_print_name)) - plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::INCONSISTENT, _L("Sync printer information")); - return false; - } + // if (obj->m_extder_data.extders.size() != 2) {//wxString(obj->get_preset_printer_model_name(machine_print_name)) + // plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::INCONSISTENT, _L("Sync printer information")); + // return false; + // } if (!plater->check_printer_initialized(obj)) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " check_printer_initialized fail"; @@ -1203,17 +1202,19 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) for (size_t index = 0; index < extruder_nums; ++index) { int extruder_id = extruder_map[index]; nozzle_diameters[extruder_id] = obj->m_extder_data.extders[index].current_nozzle_diameter; - if (obj->m_extder_data.extders[index].current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { - MessageDialog dlg(this->plater, _L("There are unset nozzle types. Please set the nozzle types of all extruders before synchronizing."), - _L("Sync extruder infomation"), wxICON_WARNING | wxOK); - dlg.ShowModal(); - continue; - } - auto printer_tab = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_PRINTER)); NozzleVolumeType target_type = NozzleVolumeType::nvtStandard; - // hack code, only use standard flow for 0.2 - if (std::fabs(nozzle_diameters[extruder_id] - 0.2) > EPSILON) - target_type = NozzleVolumeType(obj->m_extder_data.extders[extruder_id].current_nozzle_flow_type - 1); + auto printer_tab = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_PRINTER)); + if (obj->is_nozzle_flow_type_supported()) { + if (obj->m_extder_data.extders[index].current_nozzle_flow_type == NozzleFlowType::NONE_FLOWTYPE) { + MessageDialog dlg(this->plater, _L("There are unset nozzle types. Please set the nozzle types of all extruders before synchronizing."), + _L("Sync extruder infomation"), wxICON_WARNING | wxOK); + dlg.ShowModal(); + continue; + } + // hack code, only use standard flow for 0.2 + if (std::fabs(nozzle_diameters[extruder_id] - 0.2) > EPSILON) + target_type = NozzleVolumeType(obj->m_extder_data.extders[extruder_id].current_nozzle_flow_type - 1); + } printer_tab->set_extruder_volume_type(index, target_type); } @@ -1239,25 +1240,36 @@ bool Sidebar::priv::sync_extruder_list(bool &only_external_material) int main_index = obj->is_main_extruder_on_left() ? 0 : 1; int deputy_index = obj->is_main_extruder_on_left() ? 1 : 0; - int left_index = left_extruder->combo_diameter->FindString(get_diameter_string(nozzle_diameters[0])); - int right_index = left_extruder->combo_diameter->FindString(get_diameter_string(nozzle_diameters[1])); - assert(left_index != -1 && right_index != -1); - left_extruder->combo_diameter->SetSelection(left_index); - right_extruder->combo_diameter->SetSelection(right_index); - is_switching_diameter = true; - switch_diameter(false); - is_switching_diameter = false; - AMSCountPopupWindow::SetAMSCount(deputy_index, deputy_4, deputy_1); - AMSCountPopupWindow::SetAMSCount(main_index, main_4, main_1); - AMSCountPopupWindow::UpdateAMSCount(0, left_extruder); - AMSCountPopupWindow::UpdateAMSCount(1, right_extruder); + if (extruder_nums > 1) { + int left_index = left_extruder->combo_diameter->FindString(get_diameter_string(nozzle_diameters[0])); + int right_index = left_extruder->combo_diameter->FindString(get_diameter_string(nozzle_diameters[1])); + assert(left_index != -1 && right_index != -1); + left_extruder->combo_diameter->SetSelection(left_index); + right_extruder->combo_diameter->SetSelection(right_index); + is_switching_diameter = true; + switch_diameter(false); + is_switching_diameter = false; + AMSCountPopupWindow::SetAMSCount(deputy_index, deputy_4, deputy_1); + AMSCountPopupWindow::SetAMSCount(main_index, main_4, main_1); + AMSCountPopupWindow::UpdateAMSCount(0, left_extruder); + AMSCountPopupWindow::UpdateAMSCount(1, right_extruder); + } else { + int index = single_extruder->combo_diameter->FindString(get_diameter_string(nozzle_diameters[0])); + assert(index != -1); + single_extruder->combo_diameter->SetSelection(index); + is_switching_diameter = true; + switch_diameter(true); + is_switching_diameter = false; + } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " finish sync_extruder_list"; return true; } void Sidebar::priv::update_sync_status(const MachineObject *obj) { - auto clear_all_sync_status = [this]() { + StateColor not_synced_colour(std::pair(wxColour("#4479FB"), StateColor::Normal)); + auto clear_all_sync_status = [this, ¬_synced_colour]() { panel_printer_preset->ShowBadge(false); panel_printer_bed->ShowBadge(false); left_extruder->ShowBadge(false); @@ -1266,6 +1278,8 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) right_extruder->sync_ams(nullptr, {}, {}); single_extruder->ShowBadge(false); single_extruder->sync_ams(nullptr, {}, {}); + btn_sync_printer->SetBorderColor(not_synced_colour); + btn_sync_printer->SetIcon("printer_sync"); }; //y59 @@ -1316,6 +1330,13 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) } }; + auto is_same_nozzle_info = [obj](const ExtruderInfo &left, const ExtruderInfo &right) { + bool is_same_nozzle_type = true; + if (obj->is_nozzle_flow_type_supported()) + is_same_nozzle_type = left.nozzle_volue_type == right.nozzle_volue_type; + return abs(left.diameter - right.diameter) < EPSILON && is_same_nozzle_type; + }; + // 2. update extruder status int extruder_nums = preset_bundle->get_printer_extruder_count(); //if (extruder_nums != obj->m_extder_data.extders.size()) @@ -1377,7 +1398,7 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) //std::vector extruder_synced(extruder_nums, false); //if (extruder_nums == 1) { - // if (extruder_infos == machine_extruder_infos) { + // if (is_same_nozzle_info(extruder_infos[0], machine_extruder_infos[0])) { // single_extruder->ShowBadge(true); // single_extruder->sync_ams(obj, machine_extruder_infos[0].ams_v4, machine_extruder_infos[0].ams_v1); // extruder_synced[0] = true; @@ -1410,7 +1431,6 @@ void Sidebar::priv::update_sync_status(const MachineObject *obj) //} //StateColor synced_colour(std::pair(wxColour("#CECECE"), StateColor::Normal)); - //StateColor not_synced_colour(std::pair(wxColour("#4479fb"), StateColor::Normal)); //bool all_extruder_synced = std::all_of(extruder_synced.begin(), extruder_synced.end(), [](bool value) { return value; }); //if (printer_synced && all_extruder_synced) { // btn_sync_printer->SetBorderColor(synced_colour); @@ -1535,14 +1555,14 @@ Sidebar::Sidebar(Plater *parent) p->m_panel_printer_content = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); p->m_panel_printer_content->SetBackgroundColour(wxColour(255, 255, 255)); - StateColor panel_bd_col(std::pair(wxColour("#0042AE"), StateColor::Pressed), - std::pair(wxColour("#0042AE"), StateColor::Hovered), + StateColor panel_bd_col(std::pair(wxColour("#4479FB"), StateColor::Pressed), + std::pair(wxColour("#4479FB"), StateColor::Hovered), std::pair(wxColour("#EEEEEE"), StateColor::Normal)); p->panel_printer_preset = new StaticBox(p->m_panel_printer_content); p->panel_printer_preset->SetCornerRadius(8); p->panel_printer_preset->SetBorderColor(panel_bd_col); - p->panel_printer_preset->SetMinSize(PRINTER_PANEL_SIZE_SMALL); + p->panel_printer_preset->SetMinSize(PRINTER_PANEL_SIZE); p->panel_printer_preset->Bind(wxEVT_LEFT_DOWN, [this](auto & evt) { p->combo_printer->wxEvtHandler::ProcessEvent(evt); }); @@ -1590,7 +1610,7 @@ Sidebar::Sidebar(Plater *parent) p->panel_printer_bed = new StaticBox(p->m_panel_printer_content); p->panel_printer_bed->SetCornerRadius(8); p->panel_printer_bed->SetBorderColor(panel_bd_col); - p->panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE_SMALL); + p->panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE); p->panel_printer_bed->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) { p->combo_printer_bed->wxEvtHandler::ProcessEvent(evt); }); @@ -1619,12 +1639,12 @@ Sidebar::Sidebar(Plater *parent) p->combo_printer_bed = new ComboBox(p->panel_printer_bed, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY | wxALIGN_CENTER_HORIZONTAL); p->combo_printer_bed->SetBorderWidth(0); p->combo_printer_bed->GetDropDown().SetUseContentWidth(true); - reset_bed_type_combox_choices(); + reset_bed_type_combox_choices(true); p->combo_printer_bed->Bind(wxEVT_COMBOBOX, [this](auto &e) { bool isDual = static_cast(p->panel_printer_preset->GetSizer())->GetOrientation() == wxVERTICAL; auto image_path = get_cur_select_bed_image(); - p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, isDual ? 48 : 32)); + p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, 48)); if (p->big_bed_image_popup) { p->big_bed_image_popup->set_bitmap(create_scaled_bitmap("big_" + image_path, p->big_bed_image_popup, p->big_bed_image_popup->get_image_px())); } @@ -1676,13 +1696,13 @@ Sidebar::Sidebar(Plater *parent) btn_sync->SetToolTip(_L("Synchronize nozzle information and the number of BOX")); btn_sync->SetCornerRadius(8); StateColor btn_sync_bg_col( - std::pair(wxColour(0xCECECE), StateColor::Pressed), - std::pair(wxColour(0xF8F8F8), StateColor::Hovered), - std::pair(wxColour(0xF8F8F8), StateColor::Normal)); + std::pair(wxColour("#CECECE"), StateColor::Pressed), + std::pair(wxColour("#F8F8F8"), StateColor::Hovered), + std::pair(wxColour("#F8F8F8"), StateColor::Normal)); StateColor btn_sync_bd_col( - std::pair(wxColour(0x4479fb), StateColor::Pressed), - std::pair(wxColour(0x4479fb), StateColor::Hovered), - std::pair(wxColour(0xEEEEEE), StateColor::Normal)); + std::pair(wxColour("#4479fb"), StateColor::Pressed), + std::pair(wxColour("#4479fb"), StateColor::Hovered), + std::pair(wxColour("#EEEEEE"), StateColor::Normal)); btn_sync->SetBackgroundColor(btn_sync_bg_col); btn_sync->SetBorderColor(btn_sync_bd_col); btn_sync->SetCanFocus(false); @@ -1731,10 +1751,16 @@ Sidebar::Sidebar(Plater *parent) if (e.GetPosition().x > (p->m_flushing_volume_btn->IsShown() ? p->m_flushing_volume_btn->GetPosition().x : p->m_bpButton_add_filament->GetPosition().x)) return; - if (p->m_panel_filament_content->GetMaxHeight() == 0) - p->m_panel_filament_content->SetMaxSize({-1, -1}); - else + if (p->m_panel_filament_content->GetMaxHeight() == 0) { + p->m_panel_filament_content->SetMaxSize({-1, FromDIP(174)}); + auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize({-1, min_size.y}); + } else { + p->m_panel_filament_content->SetMinSize({-1, 0}); p->m_panel_filament_content->SetMaxSize({-1, 0}); + } m_scrolled_sizer->Layout(); }); @@ -1945,8 +1971,11 @@ Sidebar::Sidebar(Plater *parent) bSizer39->Add(FromDIP(15), 0, 0, 0, 0); // add filament content - p->m_panel_filament_content = new wxPanel( p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - p->m_panel_filament_content->SetBackgroundColour( wxColour( 255, 255, 255 ) ); + p->m_panel_filament_content = new wxScrolledWindow( p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + p->m_panel_filament_content->SetScrollbars(0, 100, 1, 2); + p->m_panel_filament_content->SetScrollRate(0, 5); + p->m_panel_filament_content->SetMaxSize(wxSize{-1, FromDIP(174)}); + p->m_panel_filament_content->SetBackgroundColour(wxColour(255, 255, 255)); //wxBoxSizer* bSizer_filament_content; //bSizer_filament_content = new wxBoxSizer( wxHORIZONTAL ); @@ -1968,6 +1997,10 @@ Sidebar::Sidebar(Plater *parent) sizer_filaments2->AddSpacer(FromDIP(16)); p->m_panel_filament_content->SetSizer(sizer_filaments2); p->m_panel_filament_content->Layout(); + auto min_size = sizer_filaments2->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize(min_size); scrolled_sizer->Add(p->m_panel_filament_content, 0, wxEXPAND, 0); } @@ -2058,12 +2091,14 @@ void Sidebar::on_enter_image_printer_bed(wxMouseEvent &evt) { } void Sidebar::on_leave_image_printer_bed(wxMouseEvent &evt) { - auto pos_x = evt.GetX(); - auto pos_y = evt.GetY(); - auto rect = p->image_printer_bed->GetRect(); - if ((pos_x <= 0 || pos_y <= 0 || pos_x >= rect.GetWidth()) && p->big_bed_image_popup) { - p->big_bed_image_popup->on_hide(); - } + //y67 + //auto pos_x = evt.GetX(); + //auto pos_y = evt.GetY(); + //auto rect = p->image_printer_bed->GetRect(); + //if ((pos_x <= 0 || pos_y <= 0 || pos_x >= rect.GetWidth()) && p->big_bed_image_popup) { + // p->big_bed_image_popup->on_hide(); + //} + p->big_bed_image_popup->on_hide(); } void Sidebar::on_change_color_mode(bool is_dark) { @@ -2221,13 +2256,34 @@ void Sidebar::update_all_preset_comboboxes() if (config) { m_update_3d_state = true; bool has_changed = reset_bed_type_combox_choices(); - if (m_begin_sync_printer_status && !has_changed) { - return; - } - if (m_soft_first_start && !wxGetApp().get_app_conf_exists()) { - use_default_bed_type(); + bool flag = m_begin_sync_printer_status && !has_changed; + if (!(flag)) { + if (m_soft_first_start && !wxGetApp().get_app_conf_exists()) { + use_default_bed_type(); + } else { + auto user_bed_type_flag = config->get("user_bed_type") == "true"; + if (!user_bed_type_flag) { // bed_type not follow machine + set_bed_by_curr_bed_type(config); + } else { // bed_type follow machine + if (m_is_gcode_file) { //.gcode.3mf case + m_is_gcode_file = false; + set_bed_by_curr_bed_type(config); + } else if (user_bed_type_flag) { + if (config->has_section("user_bed_type_list")) { + auto user_bed_type_list = config->get_section("user_bed_type_list"); + if (user_bed_type_list.size() > 0 && user_bed_type_list[cur_preset_name].size() > 0) { + set_bed_type(user_bed_type_list[cur_preset_name]); + } else { + use_default_bed_type(); + } + } else { + use_default_bed_type(); + } + } + } + } } else { - //w34 + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":no need reset_bed_type_combox_choices"; } } else { BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":error:AppConfig is nullptr"; @@ -2238,6 +2294,7 @@ void Sidebar::update_all_preset_comboboxes() // p->btn_connect_printer->Show(); // p->m_bpButton_ams_filament->Hide(); + reset_bed_type_combox_choices(); p_mainframe->set_print_button_to_default(MainFrame::PrintSelectType::eSendGcode); auto cfg = preset_bundle.printers.get_edited_preset().config; wxString url; @@ -2273,7 +2330,10 @@ void Sidebar::update_all_preset_comboboxes() //w34 y58 if (cfg.opt_bool("support_multi_bed_types")) { p->combo_printer_bed->Enable(); - p->combo_printer_bed->SelectAndNotify(btPEI); + //y64 + DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config; + auto curr_bed_type = proj_cfg.opt_enum(std::string("curr_bed_type")); + set_bed_type_accord_combox(curr_bed_type); p->combo_printer_bed->SetAble(true); } else { @@ -2386,7 +2446,11 @@ void Sidebar::update_presets(Preset::Type preset_type) auto extruder_variants = printer_preset.config.option("extruder_variant_list"); bool is_dual_extruder = extruder_variants->size() == 2; - p->layout_printer(true, is_dual_extruder); + + //y65 + bool is_support_multi_box = wxGetApp().preset_bundle->printers.get_edited_preset().config.opt_bool("is_support_multi_box"); + p->layout_printer(is_support_multi_box, is_dual_extruder); + auto extruders_def = printer_preset.config.def()->get("extruder_type"); auto extruders = printer_preset.config.option("extruder_type"); auto nozzle_volumes_def = wxGetApp().preset_bundle->project_config.def()->get("nozzle_volume_type"); @@ -2438,7 +2502,7 @@ void Sidebar::update_presets(Preset::Type preset_type) update_extruder_variant(*p->single_extruder, 0); //if (!p->is_switching_diameter) update_extruder_diameter(*p->single_extruder); - p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, 32)); + p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, 48)); } if (GUI::wxGetApp().plater()) @@ -2555,20 +2619,13 @@ void Sidebar::set_bed_type_accord_combox(BedType bed_type) { save_bed_type_to_config(bed_type_name); } -bool Sidebar::reset_bed_type_combox_choices() { +bool Sidebar::reset_bed_type_combox_choices(bool is_sidebar_init) +{ if (!p->combo_printer_bed) { return false; } - auto bundle = wxGetApp().preset_bundle; - const Preset * curr = &bundle->printers.get_selected_preset(); - const VendorProfile::PrinterModel *pm = PresetUtils::system_printer_model(*curr); - if (!pm) { - auto curr_parent = bundle->printers.get_selected_preset_parent(); - //y62 - if(curr_parent) - pm = PresetUtils::system_printer_model(*curr_parent); - } + auto pm = p->plater->get_curr_printer_model(); //y58 //if (m_last_combo_bedtype_count != 0 && pm) { // auto cur_count = (int) BedType::btCount - 1 - pm->not_support_bed_types.size(); @@ -2608,6 +2665,9 @@ bool Sidebar::reset_bed_type_combox_choices() { } } m_last_combo_bedtype_count = p->combo_printer_bed->GetCount(); + if (!is_sidebar_init && &p->plater->get_partplate_list()) { + p->plater->get_partplate_list().check_all_plate_local_bed_type(m_cur_combox_bed_types); + } return true; } @@ -2619,8 +2679,12 @@ bool Sidebar::use_default_bed_type(bool is_qdt_preset) if (is_qdt_preset && pm && pm->default_bed_type.size() > 0) { return set_bed_type(pm->default_bed_type); } - auto select_bed_type = get_cur_select_bed_type(); - std::string bed_type_name = print_config_def.get("curr_bed_type")->enum_values[int(select_bed_type) - 1]; + + //y65 + //auto select_bed_type = get_cur_select_bed_type(); + auto select_bed_type = std::stoi(wxGetApp().app_config->get("curr_bed_type")); + + std::string bed_type_name = print_config_def.get("curr_bed_type")->enum_values[int(select_bed_type) - 1]; save_bed_type_to_config(bed_type_name); return false; } @@ -2648,7 +2712,7 @@ void Sidebar::msw_rescale() p->image_printer->SetSize(PRINTER_THUMBNAIL_SIZE); bool isDual = static_cast(p->panel_printer_preset->GetSizer())->GetOrientation() == wxVERTICAL; auto image_path = get_cur_select_bed_image(); - p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, isDual ? 48 : 32)); + p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, 48)); p->m_filament_icon->msw_rescale(); p->m_bpButton_add_filament->msw_rescale(); @@ -2666,7 +2730,7 @@ void Sidebar::msw_rescale() p->btn_sync_printer->SetPaddingSize({FromDIP(6), FromDIP(12)}); p->btn_sync_printer->SetMinSize(PRINTER_PANEL_SIZE); p->btn_sync_printer->SetMaxSize(PRINTER_PANEL_SIZE); - p->panel_printer_bed->SetMinSize(isDual ? PRINTER_PANEL_SIZE : PRINTER_PANEL_SIZE_WIDEN); + p->panel_printer_bed->SetMinSize(PRINTER_PANEL_SIZE); p->btn_sync_printer->Rescale(); #if 0 if (p->mode_sizer) @@ -2836,6 +2900,11 @@ void Sidebar::on_filament_count_change(size_t num_filaments) sizer->Hide(p->m_flushing_volume_btn); } + auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize(min_size); + Layout(); p->m_panel_filament_title->Refresh(); update_ui_from_settings(); @@ -2891,6 +2960,11 @@ void Sidebar::on_filaments_delete(size_t filament_id) p->combos_filament[idx]->update(); } + auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize(min_size); + Layout(); p->m_panel_filament_title->Refresh(); update_ui_from_settings(); @@ -3250,7 +3324,11 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn) for (auto& c : p->combos_filament) c->update(); // Expand filament list - p->m_panel_filament_content->SetMaxSize({-1, -1}); + p->m_panel_filament_content->SetMaxSize({-1, FromDIP(174)}); + auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize({-1, min_size.y}); // QDS:Synchronized consumables information // auto calculation of flushing volumes for (int i = 0; i < p->combos_filament.size(); ++i) { @@ -3491,11 +3569,12 @@ void Sidebar::sync_box_list() BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish on_filament_count_change"; for (auto& c : p->combos_filament) c->update(); - /*wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); - wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); - dynamic_filament_list.update();*/ // Expand filament list - p->m_panel_filament_content->SetMaxSize({-1, -1}); + p->m_panel_filament_content->SetMaxSize({-1, FromDIP(174)}); + auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize(); + if (min_size.y > p->m_panel_filament_content->GetMaxHeight()) + min_size.y = p->m_panel_filament_content->GetMaxHeight(); + p->m_panel_filament_content->SetMinSize({-1, min_size.y}); // QDS:Synchronized consumables information // auto calculation of flushing volumes for (int i = 0; i < p->combos_filament.size(); ++i) { @@ -3575,7 +3654,6 @@ void Sidebar::sync_box_list() } } } - //wxGetApp().plater()->sidebar().udpate_combos_filament_badge(); wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); @@ -3587,15 +3665,6 @@ void Sidebar::sync_box_list() } } -void Sidebar::updata_filament_list() { - wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]); - wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); - dynamic_filament_list.update(); - // Expand filament list - p->m_panel_filament_content->SetMaxSize({ -1, -1 }); - Layout(); -} - void Sidebar::load_box_list() { box_filament_id = wxGetApp().plater()->box_msg.filament_id; @@ -3692,6 +3761,7 @@ bool Sidebar::is_multifilament() } void Sidebar::deal_btn_sync() { +#if 0 m_begin_sync_printer_status = true; bool only_external_material; auto ok = p->sync_extruder_list(only_external_material); @@ -3702,6 +3772,10 @@ void Sidebar::deal_btn_sync() { } m_begin_sync_printer_status = false; wxGetApp().plater()->update_machine_sync_status(); +#endif + + //y65 + sync_box_list(); } void Sidebar::pop_sync_nozzle_and_ams_dialog() { @@ -3721,13 +3795,12 @@ void Sidebar::pop_sync_nozzle_and_ams_dialog() { wxSize small_btn_size; get_small_btn_sync_pos_size(small_btn_pt, small_btn_size); temp_na_info.ams_btn_pos = small_btn_pt + wxPoint(small_btn_size.x / 2, small_btn_size.y / 2); - + if (m_fna_dialog) { m_fna_dialog->on_hide(); } if (m_sna_dialog) { - if (m_fna_dialog) { m_fna_dialog->on_hide(); } - m_sna_dialog->update_info(temp_na_info); - } else { - m_sna_dialog = new SyncNozzleAndAmsDialog(temp_na_info); + m_sna_dialog->Destroy(); + m_sna_dialog = nullptr; } + m_sna_dialog = new SyncNozzleAndAmsDialog(temp_na_info); m_sna_dialog->on_show(); }); } @@ -3739,17 +3812,17 @@ void Sidebar::pop_finsish_sync_ams_dialog() wxSize small_btn_size; get_small_btn_sync_pos_size(small_btn_pt, small_btn_size); - FinishSyncBoxDialog::InputInfo temp_fsa_info; + FinishSyncAmsDialog::InputInfo temp_fsa_info; auto same_dialog_pos_x = get_sidebar_pos_right_x() + FromDIP(5); temp_fsa_info.dialog_pos.x = same_dialog_pos_x; temp_fsa_info.dialog_pos.y = small_btn_pt.y; temp_fsa_info.ams_btn_pos = small_btn_pt + wxPoint(small_btn_size.x / 2, small_btn_size.y / 2); + if (m_sna_dialog) { m_sna_dialog->on_hide(); } if (m_fna_dialog) { - if (m_sna_dialog) { m_sna_dialog->on_hide(); } - m_fna_dialog->update_info(temp_fsa_info); - } else { - m_fna_dialog = new FinishSyncBoxDialog(temp_fsa_info); + m_fna_dialog->Destroy(); + m_fna_dialog = nullptr; } + m_fna_dialog = new FinishSyncAmsDialog(temp_fsa_info); m_fna_dialog->on_show(); }); @@ -3792,18 +3865,12 @@ void Sidebar::update_mode() Layout(); } -bool Sidebar::is_collapsed() { return p->is_collapsed; } +bool Sidebar::is_collapsed() { + return p->plater->is_sidebar_collapsed(); +} -void Sidebar::collapse(bool collapse) -{ - p->is_collapsed = collapse; - - this->Show(!collapse); - p->plater->Layout(); - - // save collapsing state to the AppConfig - //if (wxGetApp().is_editor()) - // wxGetApp().app_config->set_bool("collapsed_sidebar", collapse); +void Sidebar::collapse(bool collapse){ + p->plater->collapse_sidebar(collapse); } #ifdef _MSW_DARK_MODE @@ -4090,12 +4157,40 @@ enum ExportingStatus{ EXPORTING_TO_LOCAL }; +class FloatFrame : public wxAuiFloatingFrame +{ +public: + FloatFrame(wxWindow *parent, wxAuiManager *ownerMgr, const wxAuiPaneInfo &pane) : wxAuiFloatingFrame(parent, ownerMgr, pane) { wxGetApp().UpdateFrameDarkUI(this); } +}; + +class AuiMgr : public wxAuiManager +{ +public: + AuiMgr() : wxAuiManager() { + } + + virtual wxAuiFloatingFrame *CreateFloatingFrame(wxWindow *parent, const wxAuiPaneInfo &p) override { + return new FloatFrame(parent, this, p); + } +}; + // Plater / private struct Plater::priv { +private: + Camera camera; +public: // PIMPL back pointer ("Q-Pointer") Plater *q; Sidebar * sidebar; + AuiMgr m_aui_mgr; + wxString m_default_window_layout; + struct SidebarLayout + { + bool is_enabled{false}; + bool is_collapsed{false}; + bool show{false}; + } sidebar_layout; MainFrame *main_frame; MenuFactory menus; @@ -4119,7 +4214,6 @@ struct Plater::priv std::vector panels; Bed3D bed; - Camera camera; Camera picking_camera; //QDS: partplate related structure PartPlateList partplate_list; @@ -4150,7 +4244,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; @@ -4317,8 +4410,11 @@ struct Plater::priv if (current_panel == view3D) view3D->get_canvas3d()->show_overhang(show); } - bool is_sidebar_collapsed() const { return sidebar->is_collapsed(); } + void enable_sidebar(bool enabled); void collapse_sidebar(bool collapse); + void update_sidebar(bool force_update = false); + void reset_window_layout(int width); + Sidebar::DockingState get_sidebar_docking_state(); bool is_view3D_layers_editing_enabled() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_layers_editing_enabled(); } @@ -4328,6 +4424,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(); // QDS bool init_collapse_toolbar(); @@ -4543,6 +4640,7 @@ struct Plater::priv //QDS: change dark/light mode void on_change_color_mode(SimpleEvent& evt); void on_apple_change_color_mode(wxSysColourChangedEvent& evt); + void apply_color_mode(); void on_update_geometry(Vec3dsEvent<2>&); void on_3dcanvas_mouse_dragging_started(SimpleEvent&); void on_3dcanvas_mouse_dragging_finished(SimpleEvent&); @@ -4552,6 +4650,7 @@ struct Plater::priv void update_publish_dialog_status(wxString &msg, int percent = -1); void on_action_print_plate_from_sdcard(SimpleEvent&); + void on_tab_selection_changing(wxBookCtrlEvent &); // Set the bed shape to a single closed 2D polygon(array of two element arrays), // triangulate the bed and store the triangles into m_bed.m_triangles, // fills the m_bed.m_grid_lines and sets m_bed.m_origin. @@ -4718,6 +4817,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //QDS :partplatelist construction , partplate_list(this->q, &model) { + m_is_dark = wxGetApp().app_config->get_bool("dark_color_mode"); + m_aui_mgr.SetManagedWindow(q); + m_aui_mgr.SetDockSizeConstraint(1, 1); + // m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, 0); + // m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_SASH_SIZE, 2); + m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, 0); + m_aui_mgr.GetArtProvider()->SetMetric(wxAUI_DOCKART_GRADIENT_TYPE, wxAUI_GRADIENT_NONE); + this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); //QDS: use the first partplate's print for background process @@ -4763,12 +4870,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_ADD_FILAMENT, &priv::on_add_filament, this); this->q->Bind(EVT_DEL_FILAMENT, &priv::on_delete_filament, this); this->q->Bind(EVT_ADD_CUSTOM_FILAMENT, &priv::on_add_custom_filament, this); - view3D = new View3D(q, bed, &model, config, &background_process); + main_frame->m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this); + + auto *panel_3d = new wxPanel(q); + view3D = new View3D(panel_3d, bed, &model, config, &background_process); partplate_list.set_bed3d(&bed); //QDS: use partplater's gcode - preview = new Preview(q, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); }); + preview = new Preview(panel_3d, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); }); - assemble_view = new AssembleView(q, bed, &model, config, &background_process); + assemble_view = new AssembleView(panel_3d, bed, &model, config, &background_process); #ifdef __APPLE__ // QDS @@ -4789,23 +4899,49 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) update(); - auto* hsizer = new wxBoxSizer(wxHORIZONTAL); - auto* vsizer = new wxBoxSizer(wxVERTICAL); + // Orca: Make sidebar dockable + auto look = wxGetApp().app_config->get_bool("enable_sidebar_resizable"); + m_aui_mgr.AddPane(sidebar, wxAuiPaneInfo() + .Name("sidebar") + .Left() + .CloseButton(false) + .TopDockable(false) + .BottomDockable(false) + //.Floatable(true) + .Resizable(wxGetApp().app_config->get_bool("enable_sidebar_resizable")) + .MinSize(wxSize(41 * wxGetApp().em_unit(), -1)) + .BestSize(wxSize(42 * wxGetApp().em_unit(), 90 * wxGetApp().em_unit()))); - // QDS: move sidebar to left side - hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); - auto spliter_1 = new ::StaticLine(q, true); - spliter_1->SetLineColour("#A6A9AA"); - hsizer->Add(spliter_1, 0, wxEXPAND); - - panel_sizer = new wxBoxSizer(wxHORIZONTAL); + auto *panel_sizer = new wxBoxSizer(wxHORIZONTAL); panel_sizer->Add(view3D, 1, wxEXPAND | wxALL, 0); panel_sizer->Add(preview, 1, wxEXPAND | wxALL, 0); panel_sizer->Add(assemble_view, 1, wxEXPAND | wxALL, 0); - vsizer->Add(panel_sizer, 1, wxEXPAND | wxALL, 0); - hsizer->Add(vsizer, 1, wxEXPAND | wxALL, 0); + panel_3d->SetSizer(panel_sizer); + m_aui_mgr.AddPane(panel_3d, wxAuiPaneInfo().Name("main").CenterPane().PaneBorder(false)); - q->SetSizer(hsizer); + m_default_window_layout = m_aui_mgr.SavePerspective(); + { + auto &sidebar = m_aui_mgr.GetPane(this->sidebar); + + // Load previous window layout + const auto cfg = wxGetApp().app_config; + wxString layout = wxString::FromUTF8(cfg->get("window_layout")); + if (!layout.empty()) { + m_aui_mgr.LoadPerspective(layout, false); + sidebar_layout.is_collapsed = !sidebar.IsShown(); + } + + // Keep tracking the current sidebar size, by storing it using `best_size`, which will be stored + // in the config and re-applied when the app is opened again. + this->sidebar->Bind(wxEVT_IDLE, [&sidebar, this](wxIdleEvent &e) { + if (sidebar.IsShown() && sidebar.IsDocked() && sidebar.rect.GetWidth() > 0) { sidebar.BestSize(sidebar.rect.GetWidth(), sidebar.best_size.GetHeight()); } + e.Skip(); + }); + + // Hide sidebar initially, will re-show it after initialization when we got proper window size + //sidebar.Hide(); + m_aui_mgr.Update(); + } menus.init(main_frame); @@ -5035,6 +5171,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership q->Layout(); + apply_color_mode(); + set_current_panel(wxGetApp().is_editor() ? static_cast(view3D) : static_cast(preview)); // updates camera type from .ini file @@ -5160,6 +5298,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1"; // sidebar->collapse(is_collapsed); //} + update_sidebar(true); } Plater::priv::~priv() @@ -5168,6 +5307,7 @@ Plater::priv::~priv() delete config; // Saves the database of visited (already shown) hints into hints.ini. notification_manager->deactivate_loaded_hints(); + main_frame->m_tabpanel->Unbind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this); } void Plater::priv::update(unsigned int flags) @@ -5206,6 +5346,7 @@ void Plater::priv::update(unsigned int flags) if (get_config("autocenter") == "true" && this->sidebar->obj_manipul()->IsShown()) this->sidebar->obj_manipul()->UpdateAndShow(true); #endif + update_sidebar(); } void Plater::priv::select_view(const std::string& direction) @@ -5226,6 +5367,25 @@ void Plater::priv::select_view(const std::string& direction) } } +const VendorProfile::PrinterModel *Plater::get_curr_printer_model() +{ + auto bundle = wxGetApp().preset_bundle; + if (bundle) { + const Preset *curr = &bundle->printers.get_selected_preset(); + if (curr) { + const VendorProfile::PrinterModel *pm = PresetUtils::system_printer_model(*curr); + if (!pm) { + auto curr_parent = bundle->printers.get_selected_preset_parent(); + if (curr_parent) { + pm = PresetUtils::system_printer_model(*curr_parent); + } + } + return pm; + } + } + return nullptr; +} + wxColour Plater::get_next_color_for_filament() { static int curr_color_filamenet = 0; @@ -5331,12 +5491,85 @@ void Plater::priv::select_next_view_3D() // set_current_panel(view3D); } +void Plater::priv::enable_sidebar(bool enabled) +{ + if (q->m_only_gcode) + enabled = false; + + sidebar_layout.is_enabled = enabled; + update_sidebar(); +} + void Plater::priv::collapse_sidebar(bool collapse) { - if (q->m_only_gcode && !collapse) - return; - sidebar->collapse(collapse); - notification_manager->set_sidebar_collapsed(collapse); + if (q->m_only_gcode) return; + + sidebar_layout.is_collapsed = collapse; + + // Now update the tooltip in the toolbar. + std::string new_tooltip = collapse ? _u8L("Expand sidebar") : _u8L("Collapse sidebar"); + new_tooltip += " [Shift+Tab]"; + int id = collapse_toolbar.get_item_id("collapse_sidebar"); + collapse_toolbar.set_tooltip(id, new_tooltip); + + update_sidebar(); +} + +void Plater::priv::update_sidebar(bool force_update) +{ + auto &sidebar = m_aui_mgr.GetPane(this->sidebar); + if (!sidebar.IsOk() || this->current_panel == nullptr) { return; } + bool needs_update = force_update; + + if (!sidebar_layout.is_enabled) { + if (sidebar.IsShown()) { + sidebar.Hide(); + needs_update = true; + } + } else { + // Only hide if collapsed or is floating and is not 3d view + const bool should_hide = sidebar_layout.is_collapsed || (sidebar.IsFloating() && !sidebar_layout.show); + const bool should_show = !should_hide; + if (should_show != sidebar.IsShown()) { + sidebar.Show(should_show); + needs_update = true; + } + } + + if (needs_update) { + notification_manager->set_sidebar_collapsed(sidebar.IsShown()); + m_aui_mgr.Update(); + } +} + +void Plater::priv::reset_window_layout(int width) +{ + if (width < 0) { + m_aui_mgr.LoadPerspective(m_default_window_layout, false); + } else { + auto copy = m_default_window_layout; + wxString old_num = wxString::Format("%d", 42 * wxGetApp().em_unit()); + wxString new_num = wxString::Format("%d", width); + wxString str0("bestw="), str1("bestw="); + str0 += old_num; + str1 += new_num; + copy.Replace(str0, str1, false); + m_aui_mgr.LoadPerspective(copy, false); + } + sidebar_layout.is_collapsed = false; + update_sidebar(true); +} + +Sidebar::DockingState Plater::priv::get_sidebar_docking_state() +{ + if (!sidebar_layout.is_enabled) { return Sidebar::None; } + + const auto &sidebar = m_aui_mgr.GetPane(this->sidebar); + if (sidebar.IsFloating()) { + return Sidebar::None; + } + + return sidebar.dock_direction == wxAUI_DOCK_RIGHT ? Sidebar::Right : Sidebar::Left; } @@ -5477,7 +5710,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ bool translate_old = false; int current_width, current_depth, current_height, project_filament_count = 1; - if (input_files.empty()) { return std::vector(); } + if (input_files.empty()) + return std::vector(); + + if (!input_files.empty()) + q->m_3mf_path = input_files[0].string(); // QDS int filaments_cnt = config->opt("filament_colour")->values.size(); @@ -5647,7 +5884,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ Semver app_version = *(Semver::parse(SLIC3R_VERSION)); if (en_3mf_file_type == En3mfType::From_Prusa) { // do not reset the model config - load_config = false; + //load_config = false; if(load_type != LoadType::LoadGeometry) show_info(q, _L("The 3mf is not from QIDI Tech, load geometry data only."), _L("Load 3mf")); } @@ -6275,7 +6512,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ int model_idx = 0; for (ModelObject *model_object : model.objects) { - if (!type_3mf && !type_any_amf) model_object->center_around_origin(false); + if (!type_3mf && !type_any_amf) + model_object->center_around_origin(false); // QDS BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n"); @@ -6962,6 +7200,13 @@ void Plater::priv::delete_all_objects_from_model() 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(); // Stop and reset the Print content. @@ -7036,6 +7281,15 @@ void Plater::priv::reset(bool apply_presets_change) // QDS m_saved_timestamp = m_backup_timestamp = size_t(-1); + + // Save window layout + if (sidebar_layout.is_enabled) { + // Reset show state + auto &sidebar = m_aui_mgr.GetPane(this->sidebar); + if (!sidebar_layout.is_collapsed && !sidebar.IsShown()) { sidebar.Show(); } + auto layout = m_aui_mgr.SavePerspective(); + wxGetApp().app_config->set("window_layout", layout.utf8_string()); + } } void Plater::priv::center_selection() @@ -8349,10 +8603,12 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) preview->set_as_dirty(); }; - //QDS: add the collapse logic + // Add sidebar and toolbar collapse logic + if (panel == view3D || panel == preview) { + this->enable_sidebar(!q->only_gcode_mode()); + } if (panel == preview) { if (q->only_gcode_mode()) { - this->sidebar->collapse(true); preview->get_canvas3d()->enable_select_plate_toolbar(false); } else if (q->using_exported_file() && (q->m_valid_plates_count <= 1)) { preview->get_canvas3d()->enable_select_plate_toolbar(false); @@ -8411,22 +8667,7 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) p->Hide(); } - panel_sizer->Layout(); - - 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()); - } - } + update_sidebar(true); if (current_panel == view3D) { if (old_panel == preview) @@ -8449,6 +8690,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) { @@ -8465,8 +8709,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) view3D->get_canvas3d()->reset_old_size(); // QDS //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(); @@ -8513,9 +8755,11 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) // QDS //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(); } @@ -8539,12 +8783,6 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) } } - // QDS 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(); // QDS //view_toolbar.select_item("Assemble"); @@ -8662,7 +8900,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) Preset::remove_suffix_modified(wx_name.ToUTF8().data())); if (preset_type == Preset::TYPE_FILAMENT) { + std::string old_name = wxGetApp().preset_bundle->filaments.get_edited_preset().name; wxGetApp().preset_bundle->set_filament_preset(idx, preset_name); + if (!q->on_filament_change(idx)) + wxGetApp().preset_bundle->set_filament_preset(idx, old_name); wxGetApp().plater()->update_project_dirty_from_presets(); wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); dynamic_filament_list.update(); @@ -8672,7 +8913,6 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) } auto select_flag = combo->GetFlag(selection); combo->ShowBadge(select_flag == (int)PresetComboBox::FilamentAMSType::FROM_AMS); - q->on_filament_change(idx); } bool select_preset = !combo->selection_is_changed_according_to_physical_printers(); // TODO: ? @@ -9315,8 +9555,6 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) if (filament_info.filament_index != cur_box_info.filament_index || filament_info.filament_vendor != cur_box_info.filament_vendor || filament_info.filament_color_index != cur_box_info.filament_color_index - || filament_info.slot_state != cur_box_info.slot_state - || filament_info.slot_id != cur_box_info.slot_id || filament_info.box_count != cur_box_info.box_count || filament_info.auto_reload_detect != cur_box_info.auto_reload_detect) { has_diff = true; @@ -9324,7 +9562,10 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) #endif } - if(extruders_size > 1 && box_ip.empty()){ +//y65 + bool is_can_change_color = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->get_is_can_change_color(); + + if(extruders_size > 1 && box_ip.empty() && !is_can_change_color){ wxGetApp().plater()->sidebar().sync_box_list(); } //y61 @@ -9485,6 +9726,14 @@ void Plater::priv::on_action_print_plate_from_sdcard(SimpleEvent&) m_select_machine_dlg->ShowModal(); } +void Plater::priv::on_tab_selection_changing(wxBookCtrlEvent &e) +{ + const int new_sel = e.GetSelection(); + sidebar_layout.show = new_sel == MainFrame::tp3DEditor || new_sel == MainFrame::tpPreview; + update_sidebar(); + e.Skip(); +} + int Plater::priv::update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path) { //y30 @@ -9713,6 +9962,8 @@ void Plater::priv::on_apple_change_color_mode(wxSysColourChangedEvent& evt) { preview->get_canvas3d()->on_change_color_mode(m_is_dark); assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark); } + + apply_color_mode(); } void Plater::priv::on_change_color_mode(SimpleEvent& evt) { @@ -9722,6 +9973,19 @@ void Plater::priv::on_change_color_mode(SimpleEvent& evt) { preview->get_canvas3d()->on_change_color_mode(m_is_dark); assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark); if (m_send_to_sdcard_dlg) m_send_to_sdcard_dlg->on_change_color_mode(); + apply_color_mode(); +} + +void Plater::priv::apply_color_mode() +{ + const bool is_dark = wxGetApp().dark_mode(); + wxColour orca_color = wxColour(59, 68, 70); // wxColour(ColorRGBA::ORCA().r_uchar(), ColorRGBA::ORCA().g_uchar(), ColorRGBA::ORCA().b_uchar()); + orca_color = is_dark ? StateColor::darkModeColorFor(orca_color) : StateColor::lightModeColorFor(orca_color); + wxColour sash_color = is_dark ? wxColour(38, 46, 48) : wxColour(206, 206, 206); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, sash_color); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, *wxWHITE); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_SASH_COLOUR, sash_color); + m_aui_mgr.GetArtProvider()->SetColour(wxAUI_DOCKART_BORDER_COLOUR, is_dark ? *wxBLACK : wxColour(165, 165, 165)); } static void get_position(wxWindowBase *child, wxWindowBase *until_parent, int &x, int &y) @@ -10148,8 +10412,14 @@ void Plater::priv::update_objects_position_when_select_preset(const std::functio wxGetApp().obj_list()->update_object_list_by_printer_technology(); - // QDS:Model reset by plate center + // set default wipe tower pos PartPlateList &cur_plate_list = this->partplate_list; + for (size_t plate_id = 0; plate_id < cur_plate_list.get_plate_list().size(); ++plate_id) { + cur_plate_list.set_default_wipe_tower_pos_for_plate(plate_id); + } + update(); + + // QDS:Model reset by plate center PartPlate *cur_plate = cur_plate_list.get_curr_plate(); Vec3d cur_plate_pos = cur_plate->get_center_origin(); Vec3d cur_plate_size = cur_plate->get_bounding_box().size(); @@ -10251,6 +10521,16 @@ void Plater::get_print_job_data(PrintPrepareData* data) } } +void Plater::set_print_job_plate_idx(int plate_idx) +{ + if (plate_idx == PLATE_CURRENT_IDX) { + p->m_print_job_data.plate_idx = get_partplate_list().get_curr_plate_index(); + } + else { + p->m_print_job_data.plate_idx = plate_idx; + } +} + int Plater::get_send_calibration_finished_event() { return EVT_SEND_CALIBRATION_FINISHED; @@ -10422,6 +10702,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()) @@ -10433,10 +10727,10 @@ bool Plater::priv::init_collapse_toolbar() BackgroundTexture::Metadata background_data; background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png"; - background_data.left = 16; - background_data.top = 16; - background_data.right = 16; - background_data.bottom = 16; + background_data.left = 4; + background_data.top = 4; + background_data.right = 4; + background_data.bottom = 4; if (!collapse_toolbar.init(background_data)) return false; @@ -10444,17 +10738,16 @@ bool Plater::priv::init_collapse_toolbar() collapse_toolbar.set_layout_type(GLToolbar::Layout::Vertical); collapse_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right); collapse_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); - collapse_toolbar.set_border(5.0f); + collapse_toolbar.set_border(0.0f); collapse_toolbar.set_separator_size(5); collapse_toolbar.set_gap_size(2); - collapse_toolbar.del_all_item(); GLToolbarItem::Data item; item.name = "collapse_sidebar"; // set collapse svg name - item.icon_filename = "*.svg"; + item.icon_filename = "collapse.svg"; item.sprite_id = 0; item.left.action_callback = []() { wxGetApp().plater()->collapse_sidebar(!wxGetApp().plater()->is_sidebar_collapsed()); @@ -10466,6 +10759,7 @@ bool Plater::priv::init_collapse_toolbar() // Now "collapse" sidebar to current state. This is done so the tooltip // is updated before the toolbar is first used. wxGetApp().plater()->collapse_sidebar(wxGetApp().plater()->is_sidebar_collapsed()); + collapse_toolbar.set_icons_size(q->get_collapse_toolbar_size()); return true; } @@ -11432,6 +11726,8 @@ void Plater::render_project_state_debug_window() const { p->render_project_state Sidebar& Plater::sidebar() { return *p->sidebar; } const Model& Plater::model() const { return p->model; } Model& Plater::model() { return p->model; } +Bed3D & Plater::bed() { return p->bed; } +BackgroundSlicingProcess &Plater::background_process() { return p->background_process; } const Print& Plater::fff_print() const { return p->fff_print; } Print& Plater::fff_print() { return p->fff_print; } const SLAPrint& Plater::sla_print() const { return p->sla_print; } @@ -11465,9 +11761,6 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString &project_ if (!skip_confirm && (result = close_with_confirm(check)) == wxID_CANCEL) return wxID_CANCEL; - //QDS: add only gcode mode - bool previous_gcode = m_only_gcode; - reset_flags_when_new_or_close_project(); get_notification_manager()->clear_all(); @@ -11507,9 +11800,8 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString &project_ // QDS set default view and zoom p->select_view_3D("3D"); p->select_view("topfront"); - p->camera.requires_zoom_to_bed = true; - if (previous_gcode) - collapse_sidebar(false); + p->get_current_camera().requires_zoom_to_bed = true; + enable_sidebar(!m_only_gcode); up_to_date(true, false); up_to_date(true, true); @@ -11561,9 +11853,9 @@ bool Plater::try_sync_preset_with_connected_printer(int& nozzle_diameter) if (printer_preset.get_current_printer_type(preset_bundle) != printer_type || !is_approx((float)(preset_nozzle_diameter), machine_nozzle_diameter)) { wxString tips; if (printer_preset.get_current_printer_type(preset_bundle) != printer_type) - tips = from_u8((boost::format(_u8L("The currently connected printer, %s, is a %s model.\nTo use this printer for printing, please switch the printer model of project file to %s.")) % obj->dev_name % printer_model % printer_model).str()); + tips = from_u8((boost::format(_u8L("The currently connected printer '%s', is a %s model.\nTo use this printer for printing, please switch the printer model of project file to %s.")) % obj->dev_name % printer_model % printer_model).str()); else if (!is_approx((float) (preset_nozzle_diameter), machine_nozzle_diameter)) - tips = from_u8((boost::format(_u8L("The currently connected printer, %s, is a %s model but not consistent with preset in project file.\n" + tips = from_u8((boost::format(_u8L("The currently connected printer '%s', is a %s model but not consistent with preset in project file.\n" "To use this printer for printing, please switch the preset first.")) % obj->dev_name % printer_model).str()); std::mapoption_map = { @@ -11691,7 +11983,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 { @@ -13192,6 +13484,7 @@ void Plater::load_gcode(const wxString& filename) // process gcode GCodeProcessor processor; + processor.init_filament_maps_and_nozzle_type_when_import_only_gcode(); try { processor.process_file(filename.ToUTF8().data()); @@ -13242,8 +13535,7 @@ void Plater::load_gcode(const wxString& filename) } else { set_project_filename(filename); } - - p->main_frame->update_slice_print_status(MainFrame::eEventPlateUpdate, false, true);//STUDIO-11512 + p->main_frame->update_slice_print_status(MainFrame::eEventPlateUpdate, false, false); //20250416 ban gcode to send print } void Plater::reload_gcode_from_disk() @@ -13494,7 +13786,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) m_confirm = new Button(this, _L("OK")); // y96 - StateColor btn_bg_blue(std::pair(wxColour(95, 82, 253), StateColor::Pressed), std::pair(wxColour(129, 150, 255), StateColor::Hovered), + StateColor btn_bg_blue(std::pair(wxColour(40, 90, 220), StateColor::Pressed), std::pair(wxColour(100, 150, 255), StateColor::Hovered), std::pair(wxColour(68, 121, 251), StateColor::Normal)); m_confirm->SetBackgroundColor(btn_bg_blue); @@ -14136,9 +14428,12 @@ void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); } bool Plater::is_view3D_overhang_shown() const { return p->is_view3D_overhang_shown(); } void Plater::show_view3D_overhang(bool show) { p->show_view3D_overhang(show); } -bool Plater::is_sidebar_collapsed() const { return p->is_sidebar_collapsed(); } +bool Plater::is_sidebar_enabled() const { return p->sidebar_layout.is_enabled; } +void Plater::enable_sidebar(bool enabled) { p->enable_sidebar(enabled); } +bool Plater::is_sidebar_collapsed() const { return p->sidebar_layout.is_collapsed; } void Plater::collapse_sidebar(bool show) { p->collapse_sidebar(show); } - +Sidebar::DockingState Plater::get_sidebar_docking_state() const { return p->get_sidebar_docking_state(); } +void Plater::reset_window_layout(int width) { p->reset_window_layout(width); } //QDS void Plater::select_curr_plate_all() { p->select_curr_plate_all(); } void Plater::remove_curr_plate_all() { p->remove_curr_plate_all(); } @@ -14653,6 +14948,7 @@ void Plater::export_gcode_3mf(bool export_all) default_output_file = into_path(get_export_gcode_filename(".gcode.3mf", false, export_all)); if (default_output_file.empty()) { try { + start_dir = appconfig.get_last_output_dir("", false); wxString filename = get_export_gcode_filename(".gcode.3mf", true, export_all); std::string full_filename = start_dir + "/" + filename.utf8_string(); @@ -14942,7 +15238,7 @@ Preset *get_printer_preset(MachineObject *obj) return printer_preset; } -bool Plater::check_printer_initialized(MachineObject *obj, bool only_warning) +bool Plater::check_printer_initialized(MachineObject *obj, bool only_warning, bool popup_warning) { if (!obj) return false; @@ -14962,22 +15258,23 @@ bool Plater::check_printer_initialized(MachineObject *obj, bool only_warning) } if (!has_been_initialized) { - if (!only_warning) { + if (popup_warning) { + if (!only_warning) { + if (DeviceManager::get_printer_can_set_nozzle(obj->printer_type)) { + MessageDialog dlg(wxGetApp().plater(), _L("The nozzle type is not set. Please set the nozzle and try again."), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); + } else { + MessageDialog dlg(wxGetApp().plater(), _L("The nozzle type is not set. Please check."), _L("Warning"), wxOK | wxICON_WARNING); + dlg.ShowModal(); + } - if (DeviceManager::get_printer_can_set_nozzle(obj->printer_type)) { - MessageDialog dlg(wxGetApp().plater(), _L("The nozzle type is not set. Please set the nozzle and try again."), _L("Warning"), wxOK | wxICON_WARNING); - dlg.ShowModal(); + PrinterPartsDialog *print_parts_dlg = new PrinterPartsDialog(nullptr); + print_parts_dlg->update_machine_obj(obj); + print_parts_dlg->ShowModal(); } else { - MessageDialog dlg(wxGetApp().plater(), _L("The nozzle type is not set. Please check."), _L("Warning"), wxOK | wxICON_WARNING); - dlg.ShowModal(); + auto printer_name = get_selected_printer_name_in_combox(); // wxString(obj->get_preset_printer_model_name(machine_print_name)) + pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::NOT_CONNECTED, _L("Sync printer information")); } - - PrinterPartsDialog *print_parts_dlg = new PrinterPartsDialog(nullptr); - print_parts_dlg->update_machine_obj(obj); - print_parts_dlg->ShowModal(); - } else { - auto printer_name = get_selected_printer_name_in_combox(); // wxString(obj->get_preset_printer_model_name(machine_print_name)) - pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::NOT_CONNECTED, _L("Sync printer information")); } return false; } @@ -15371,19 +15668,6 @@ void publish(Model &model, SaveStrategy strategy) } } - // Orca: don't show this in silence mode - if (exist_new && !(strategy & SaveStrategy::Silence)) { - MessageDialog dialog(nullptr, - _L("Are you sure you want to store original SVGs with their local paths into the 3MF file?\n" - "If you hit 'NO', all SVGs in the project will not be editable any more."), - _L("Private protection"), wxYES_NO | wxICON_QUESTION); - if (dialog.ShowModal() == wxID_NO) { - for (ModelObject *object : model.objects) - for (ModelVolume *volume : object->volumes) - if (volume->emboss_shape.has_value()) volume->emboss_shape.reset(); - } - } - for (SvgFile *svgfile : svgfiles) { if (!svgfile->path_in_3mf.empty()) continue; // already suggested path (previous save) @@ -16056,12 +16340,7 @@ int Plater::send_gcode(int plate_idx, Export3mfProgressFn proFn) { int result = 0; /* generate 3mf */ - if (plate_idx == PLATE_CURRENT_IDX) { - p->m_print_job_data.plate_idx = get_partplate_list().get_curr_plate_index(); - } - else { - p->m_print_job_data.plate_idx = plate_idx; - } + set_print_job_plate_idx(plate_idx); PartPlate* plate = get_partplate_list().get_curr_plate(); try { @@ -16090,12 +16369,7 @@ int Plater::export_config_3mf(int plate_idx, Export3mfProgressFn proFn) { int result = 0; /* generate 3mf */ - if (plate_idx == PLATE_CURRENT_IDX) { - p->m_print_job_data.plate_idx = get_partplate_list().get_curr_plate_index(); - } - else { - p->m_print_job_data.plate_idx = plate_idx; - } + set_print_job_plate_idx(plate_idx); PartPlate* plate = get_partplate_list().get_curr_plate(); try { @@ -16234,34 +16508,27 @@ bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** o return false; } -void Plater::on_filament_change(size_t filament_idx) +bool Plater::on_filament_change(size_t filament_idx) { auto& filament_presets = wxGetApp().preset_bundle->filament_presets; if (filament_idx >= filament_presets.size()) - return; + return false; Slic3r::Preset* filament = wxGetApp().preset_bundle->filaments.find_preset(filament_presets[filament_idx]); if (filament == nullptr) - return; + return false; std::string filament_type = filament->config.option("filament_type")->values[0]; if (filament_type == "PVA") { - auto& process_preset = wxGetApp().preset_bundle->prints.get_edited_preset(); - auto support_type = process_preset.config.opt_enum("support_type"); - if (support_type == stNormalAuto || support_type == stNormal) - return; - - wxString msg_text = _(L("For PVA filaments, it is strongly recommended to use normal support to avoid print failures.")); - msg_text += "\n" + _(L("Change these settings automatically? \n")); - MessageDialog dialog(this, msg_text, "", - wxICON_WARNING | wxYES | wxNO); - if (dialog.ShowModal() == wxID_YES) { - SupportType target_type = support_type == SupportType::stTree ? SupportType::stNormal : SupportType::stNormalAuto; - process_preset.config.option("support_type")->set(new ConfigOptionEnum(target_type)); - auto print_tab = wxGetApp().get_tab(Preset::Type::TYPE_PRINT); - print_tab->on_value_change("support_type", target_type); - print_tab->reload_config(); - print_tab->update_dirty(); + auto nozzle_diameters = p->config->option("nozzle_diameter")->values; + if (std::find(nozzle_diameters.begin(), nozzle_diameters.end(), 0.2) != nozzle_diameters.end()) { + wxString msg_text = _(L("It is not recommended to use PVA filaments with 0.2mm nozzles.")); + msg_text += "\n" + _(L("Are you sure to use them? \n")); + MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO); + if (dialog.ShowModal() == wxID_NO) { + return false; + } } } + return true; } int Plater::update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path) @@ -17049,21 +17316,23 @@ void Plater::pop_warning_and_go_to_device_page(wxString printer_name, PrinterWar } } -bool Plater::is_same_printer_for_connected_and_selected() +bool Plater::is_same_printer_for_connected_and_selected(bool popup_warning) { MachineObject *obj = wxGetApp().getDeviceManager()->get_selected_machine(); if (obj == nullptr) { return false; } - if (!check_printer_initialized(obj,true)) + if (!check_printer_initialized(obj, true, popup_warning)) return false; Preset * machine_preset = get_printer_preset(obj); if (!machine_preset) return false; if (wxGetApp().is_blocking_printing()) { - auto printer_name = get_selected_printer_name_in_combox(); // wxString(obj->get_preset_printer_model_name(machine_print_name)) - pop_warning_and_go_to_device_page(printer_name, PrinterWarningType::INCONSISTENT, _L("Synchronize BOX Filament Information")); + if (popup_warning) { + auto printer_name = get_selected_printer_name_in_combox(); // wxString(obj->get_preset_printer_model_name(machine_print_name)) + pop_warning_and_go_to_device_page(printer_name, PrinterWarningType::INCONSISTENT, _L("Synchronize BOX Filament Information")); + } return false; } return true; @@ -17239,19 +17508,14 @@ bool Plater::init_collapse_toolbar() return p->init_collapse_toolbar(); } -void Plater::enable_collapse_toolbar(bool enable) -{ - p->collapse_toolbar.set_enabled(enable); -} - 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 @@ -17599,7 +17863,7 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) { dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index, &dlg](wxCommandEvent& e) { PartPlate* curr_plate = p->partplate_list.get_curr_plate(); BedType old_bed_type = curr_plate->get_bed_type(); - auto bt_sel = BedType(dlg.get_bed_type_choice()); + auto bt_sel = dlg.get_bed_type_choice(); if (old_bed_type != bt_sel) { curr_plate->set_bed_type(bt_sel); update_project_dirty_from_presets(); @@ -18091,6 +18355,54 @@ void Plater::show_object_info() notify_manager->qdt_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); @@ -18212,6 +18524,10 @@ GLToolbar& Plater::get_collapse_toolbar() return p->collapse_toolbar; } +int Plater::get_collapse_toolbar_size() { + return 20; +} + void Plater::update_preview_bottom_toolbar() { p->update_preview_bottom_toolbar(); @@ -18459,6 +18775,10 @@ wxMenu *Plater::assemble_multi_selection_menu() { return p->menus.assemble_multi wxMenu *Plater::filament_action_menu(int active_filament_menu_id) { return p->menus.filament_action_menu(active_filament_menu_id); } int Plater::GetPlateIndexByRightMenuInLeftUI() { return p->m_is_RightClickInLeftUI; } void Plater::SetPlateIndexByRightMenuInLeftUI(int index) { p->m_is_RightClickInLeftUI = index; } + +//y65 +bool Plater::is_can_change_color() { return p->preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->get_is_can_change_color();} + SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() : m_was_scheduled(wxGetApp().plater()->is_background_process_update_scheduled()) { @@ -18471,14 +18791,14 @@ SuppressBackgroundProcessingUpdate::~SuppressBackgroundProcessingUpdate() } wxString get_view_type_string(Camera::ViewAngleType type) { switch (type) { - case Slic3r::GUI::Camera::ViewAngleType::Iso: return _L("isometric"); - case Slic3r::GUI::Camera::ViewAngleType::Top_Front: return _L("top_front"); - case Slic3r::GUI::Camera::ViewAngleType::Left: return _L("left"); - case Slic3r::GUI::Camera::ViewAngleType::Right: return _L("right"); - case Slic3r::GUI::Camera::ViewAngleType::Top: return _L("top"); - case Slic3r::GUI::Camera::ViewAngleType::Bottom: return _L("bottom"); - case Slic3r::GUI::Camera::ViewAngleType::Front: return _L("front"); - case Slic3r::GUI::Camera::ViewAngleType::Rear: return _L("rear"); + case Slic3r::GUI::Camera::ViewAngleType::Iso: return _CTX(L_CONTEXT("Isometric", "Camera"), "Camera"); + case Slic3r::GUI::Camera::ViewAngleType::Top_Front: return _L("Top front"); + case Slic3r::GUI::Camera::ViewAngleType::Left: return _CTX(L_CONTEXT("Left", "Camera"), "Camera"); + case Slic3r::GUI::Camera::ViewAngleType::Right: return _CTX(L_CONTEXT("Right", "Camera"), "Camera"); + case Slic3r::GUI::Camera::ViewAngleType::Top: return _L("Top"); + case Slic3r::GUI::Camera::ViewAngleType::Bottom: return _L("Bottom"); + case Slic3r::GUI::Camera::ViewAngleType::Front: return _L("Front"); + case Slic3r::GUI::Camera::ViewAngleType::Rear: return _L("Rear"); default: return ""; } } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 22d42b1..ae792af 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -46,7 +46,7 @@ class ComboBox; class Button; namespace Slic3r { - +class BackgroundSlicingProcess; class BuildVolume; class Model; class ModelObject; @@ -91,6 +91,7 @@ class PlaterPresetComboBox; class PartPlateList; class SyncNozzleAndAmsDialog; class FinishSyncAmsDialog; +class Bed3D; class FinishSyncBoxDialog; using t_optgroups = std::vector >; @@ -146,7 +147,7 @@ class Sidebar : public wxPanel ScalableButton * ams_btn{nullptr}; bool m_last_slice_state = false; SyncNozzleAndAmsDialog* m_sna_dialog{nullptr}; - FinishSyncBoxDialog* m_fna_dialog{nullptr}; + FinishSyncAmsDialog* m_fna_dialog{nullptr}; std::vector m_cur_combox_bed_types; std::string m_cur_image_bed_type; int m_last_combo_bedtype_count{0}; @@ -158,6 +159,7 @@ class Sidebar : public wxPanel void update_sync_ams_btn_enable(wxUpdateUIEvent &e); public: + enum DockingState { None, Left, Right }; Sidebar(Plater *parent); Sidebar(Sidebar &&) = delete; Sidebar(const Sidebar &) = delete; @@ -182,7 +184,7 @@ public: BedType get_cur_select_bed_type(); std::string get_cur_select_bed_image(); void set_bed_type_accord_combox(BedType bed_type); - bool reset_bed_type_combox_choices(); + bool reset_bed_type_combox_choices(bool is_sidebar_init = false); bool use_default_bed_type(bool is_qdt_preset = true); void change_top_border_for_mode_sizer(bool increase_border); void msw_rescale(); @@ -226,7 +228,6 @@ public: void sync_box_list(); void load_box_list(); std::map build_filament_box_list(std::vector id, std::vector color, std::vector slot_state, std::vector slot_id, std::vector type); - void updata_filament_list(); PlaterPresetComboBox * printer_combox(); ObjectList* obj_list(); @@ -334,10 +335,12 @@ public: Sidebar& sidebar(); const Model& model() const; Model& model(); + Bed3D& bed(); const Print& fff_print() const; Print& fff_print(); const SLAPrint& sla_print() const; SLAPrint& sla_print(); + BackgroundSlicingProcess &background_process(); void reset_flags_when_new_or_close_project(); //w29 @@ -401,6 +404,8 @@ public: void invalid_all_plate_thumbnails(); void force_update_all_plate_thumbnails(); + const VendorProfile::PrinterModel *get_curr_printer_model(); + static wxColour get_next_color_for_filament(); static wxString get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning); @@ -437,9 +442,12 @@ public: bool is_view3D_overhang_shown() const; void show_view3D_overhang(bool show); + bool is_sidebar_enabled() const; + void enable_sidebar(bool enabled); bool is_sidebar_collapsed() const; void collapse_sidebar(bool show); - + Sidebar::DockingState get_sidebar_docking_state() const; + void reset_window_layout(int width = -1); // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. void update_ui_from_settings(); @@ -564,7 +572,7 @@ public: // QDS: return false if not changed bool leave_gizmos_stack(); - void on_filament_change(size_t filament_idx); + bool on_filament_change(size_t filament_idx); void on_filament_count_change(size_t extruders_count); void on_filaments_delete(size_t extruders_count, size_t filament_id, int replace_filament_id = -1); std::vector> get_extruders_colors(); @@ -595,8 +603,8 @@ public: EMPTY_FILAMENT }; void pop_warning_and_go_to_device_page(wxString printer_name, PrinterWarningType type, const wxString &title); - bool check_printer_initialized(MachineObject *obj, bool only_warning = false); - bool is_same_printer_for_connected_and_selected(); + bool check_printer_initialized(MachineObject *obj, bool only_warning = false,bool popup_warning = true); + bool is_same_printer_for_connected_and_selected(bool popup_warning = true); bool is_printer_configed_by_QDT(); // QDS //void show_action_buttons(const bool is_ready_to_slice) const; @@ -630,6 +638,8 @@ public: int get_prepare_state(); //QDS: add print job releated functions void get_print_job_data(PrintPrepareData* data); + void set_print_job_plate_idx(int plate_idx); + int get_send_calibration_finished_event(); int get_print_finished_event(); int get_send_finished_event(); @@ -665,7 +675,7 @@ public: //QDS: void edit_text(); bool can_edit_text() const; - + std::string get_3mf_filename() { return m_3mf_path; }; bool can_delete() const; bool can_delete_all() const; bool can_add_model() const; @@ -708,7 +718,6 @@ public: #endif bool init_collapse_toolbar(); - void enable_collapse_toolbar(bool enable); const Camera& get_camera() const; Camera& get_camera(); @@ -736,6 +745,7 @@ public: void update_slicing_context_to_current_partplate(); //QDS: show object info void show_object_info(); + void show_assembly_info(); //QDS bool show_publish_dialog(bool show = true); //QDS: post process string object exception strings by warning types @@ -761,7 +771,7 @@ public: const GLToolbar& get_collapse_toolbar() const; GLToolbar& get_collapse_toolbar(); - + int get_collapse_toolbar_size(); void update_preview_bottom_toolbar(); void update_preview_moves_slider(); void enable_preview_moves_slider(bool enable); @@ -927,6 +937,9 @@ public: void setUploadCount(int uploadcount); int getInterval(); void setInterval(int interval); + //y65 + bool is_can_change_color(); + //y59 Box_msg box_msg; @@ -939,7 +952,7 @@ public: private: struct priv; std::unique_ptr p; - + std::string m_3mf_path; // Set true during PopupMenu() tracking to suppress immediate error message boxes. // The error messages are collected to m_tracking_popup_menu_error_message instead and these error messages // are shown after the pop-up dialog closes. diff --git a/src/slic3r/GUI/PrePrintChecker.cpp b/src/slic3r/GUI/PrePrintChecker.cpp new file mode 100644 index 0000000..315db1f --- /dev/null +++ b/src/slic3r/GUI/PrePrintChecker.cpp @@ -0,0 +1,239 @@ +#include "PrePrintChecker.hpp" +#include "GUI_Utils.hpp" +#include "I18N.hpp" + + + +namespace Slic3r { namespace GUI { + +std::string PrePrintChecker::get_print_status_info(PrintDialogStatus status) +{ + switch (status) { + case PrintStatusInit: return "PrintStatusInit"; + case PrintStatusNoUserLogin: return "PrintStatusNoUserLogin"; + case PrintStatusInvalidPrinter: return "PrintStatusInvalidPrinter"; + case PrintStatusConnectingServer: return "PrintStatusConnectingServer"; + case PrintStatusReadingTimeout: return "PrintStatusReadingTimeout"; + case PrintStatusReading: return "PrintStatusReading"; + case PrintStatusInUpgrading: return "PrintStatusInUpgrading"; + case PrintStatusModeNotFDM: return "PrintStatusModeNotFDM"; + case PrintStatusInSystemPrinting: return "PrintStatusInSystemPrinting"; + case PrintStatusInPrinting: return "PrintStatusInPrinting"; + case PrintStatusNozzleMatchInvalid: return "PrintStatusNozzleMatchInvalid"; + case PrintStatusNozzleDataInvalid: return "PrintStatusNozzleDataInvalid"; + case PrintStatusNozzleDiameterMismatch: return "PrintStatusNozzleDiameterMismatch"; + case PrintStatusNozzleTypeMismatch: return "PrintStatusNozzleTypeMismatch"; + case PrintStatusRefreshingMachineList: return "PrintStatusRefreshingMachineList"; + case PrintStatusSending: return "PrintStatusSending"; + case PrintStatusLanModeNoSdcard: return "PrintStatusLanModeNoSdcard"; + case PrintStatusNoSdcard: return "PrintStatusNoSdcard"; + case PrintStatusLanModeSDcardNotAvailable: return "PrintStatusLanModeSDcardNotAvailable"; + case PrintStatusNeedForceUpgrading: return "PrintStatusNeedForceUpgrading"; + case PrintStatusNeedConsistencyUpgrading: return "PrintStatusNeedConsistencyUpgrading"; + case PrintStatusNotSupportedPrintAll: return "PrintStatusNotSupportedPrintAll"; + case PrintStatusBlankPlate: return "PrintStatusBlankPlate"; + case PrintStatusUnsupportedPrinter: return "PrintStatusUnsupportedPrinter"; + case PrintStatusInvalidMapping: return "PrintStatusInvalidMapping"; + // Handle filament errors + case PrintStatusAmsOnSettingup: return "PrintStatusAmsOnSettingup"; + case PrintStatusAmsMappingInvalid: return "PrintStatusAmsMappingInvalid"; + case PrintStatusAmsMappingU0Invalid: return "PrintStatusAmsMappingU0Invalid"; + case PrintStatusAmsMappingMixInvalid: return "PrintStatusAmsMappingMixInvalid"; + case PrintStatusTPUUnsupportAutoCali: return "PrintStatusTPUUnsupportAutoCali"; + // Handle warnings + case PrintStatusTimelapseNoSdcard: return "PrintStatusTimelapseNoSdcard"; + case PrintStatusTimelapseWarning: return "PrintStatusTimelapseWarning"; + case PrintStatusMixAmsAndVtSlotWarning: return "PrintStatusMixAmsAndVtSlotWarning"; + // Handle success statuses + case PrintStatusReadingFinished: return "PrintStatusReadingFinished"; + case PrintStatusSendingCanceled: return "PrintStatusSendingCanceled"; + case PrintStatusAmsMappingSuccess: return "PrintStatusAmsMappingSuccess"; + case PrintStatusNotOnTheSameLAN: return "PrintStatusNotOnTheSameLAN"; + case PrintStatusNotSupportedSendToSDCard: return "PrintStatusNotSupportedSendToSDCard"; + case PrintStatusPublicInitFailed: return "PrintStatusPublicInitFailed"; + case PrintStatusPublicUploadFiled: return "PrintStatusPublicUploadFiled"; + case PrintStatusReadyToGo: return "PrintStatusReadyToGo"; + default: return "Unknown status"; + } +} + +wxString PrePrintChecker::get_pre_state_msg(PrintDialogStatus status) +{ + switch (status) { + case PrintStatusNoUserLogin: return _L("No login account, only printers in LAN mode are displayed"); + case PrintStatusConnectingServer: return _L("Connecting to server"); + case PrintStatusReading: return _L("Synchronizing device information"); + case PrintStatusReadingTimeout: return _L("Synchronizing device information time out"); + case PrintStatusModeNotFDM: return _L("Cannot send the print job when the printer is not at FDM mode"); + case PrintStatusInUpgrading: return _L("Cannot send the print job when the printer is updating firmware"); + case PrintStatusInSystemPrinting: return _L("The printer is executing instructions. Please restart printing after it ends"); + case PrintStatusInPrinting: return _L("The printer is busy on other print job"); + case PrintStatusAmsOnSettingup: return _L("Box is setting up. Please try again later."); + case PrintStatusAmsMappingMixInvalid: return _L("Please do not mix-use the Ext with BOX"); + case PrintStatusNozzleDataInvalid: return _L("Invalid nozzle information, please refresh or manually set nozzle information."); + case PrintStatusLanModeNoSdcard: return _L("Storage needs to be inserted before printing via LAN."); + case PrintStatusLanModeSDcardNotAvailable: return _L("Storage is not available or is in read-only mode."); + case PrintStatusNoSdcard: return _L("Storage needs to be inserted before printing."); + case PrintStatusNeedForceUpgrading: return _L("Cannot send the print job to a printer whose firmware is required to get updated."); + case PrintStatusNeedConsistencyUpgrading: return _L("Cannot send the print job to a printer whose firmware is required to get updated."); + case PrintStatusBlankPlate: return _L("Cannot send the print job for empty plate"); + case PrintStatusTimelapseNoSdcard: return _L("Storage needs to be inserted to record timelapse."); + case PrintStatusMixAmsAndVtSlotWarning: return _L("You have selected both external and Box filaments for an extruder. You will need to manually switch the external filament during printing."); + case PrintStatusTPUUnsupportAutoCali: return _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration."); + case PrintStatusWarningKvalueNotUsed: return _L("Set dynamic flow calibration to 'OFF' to enable custom dynamic flow value."); + case PrintStatusNotSupportedPrintAll: return _L("This printer does not support printing all plates"); + case PrintStatusWarningTpuRightColdPulling: return _L("Please cold pull before printing TPU to avoid clogging. You may use cold pull maintenance on the printer."); + case PrintStatusFilamentWarningHighChamberTempCloseDoor: return _L("High chamber temperature is required. Please close the door."); + } + return wxEmptyString; +} + +void PrePrintChecker::clear() +{ + printerList.clear(); + filamentList.clear(); +} + +void PrePrintChecker::add(PrintDialogStatus state, wxString msg, wxString tip) +{ + prePrintInfo info; + + if (is_error(state)) { + info.level = prePrintInfoLevel::Error; + } else if (is_warning(state)) { + info.level = prePrintInfoLevel::Warning; + } else { + info.level = prePrintInfoLevel::Normal; + } + + if (is_error_printer(state)) { + info.type = prePrintInfoType::Printer; + } else if (is_error_filament(state)) { + info.type = prePrintInfoType::Filament; + } else if (is_warning_printer(state)) { + info.type = prePrintInfoType::Printer; + } else if (is_warning_filament(state)) { + info.type = prePrintInfoType::Filament; + } + + if (!msg.IsEmpty()) { + info.msg = msg; + info.tips = tip; + } else { + info.msg = get_pre_state_msg(state); + info.tips = wxEmptyString; + } + + switch (info.type) { + case prePrintInfoType::Filament: + filamentList.push_back(info); + break; + case prePrintInfoType::Printer: + printerList.push_back(info); + break; + default: break; + } +} + + +//void PrePrintMsgBoard::add(const wxString &msg, const wxString &tips, bool is_error) +//{ +// if (msg.IsEmpty()) { return; } +// +// /*message*/ +// // create label +// if (!m_sizer->IsEmpty()) { m_sizer->AddSpacer(FromDIP(10)); } +// Label *msg_label = new Label(this, wxEmptyString); +// m_sizer->Add(msg_label, 0, wxLEFT, 0); +// +// // set message +// msg_label->SetLabel(msg); +// msg_label->SetMinSize(wxSize(FromDIP(420), -1)); +// msg_label->SetMaxSize(wxSize(FromDIP(420), -1)); +// msg_label->Wrap(FromDIP(420)); +// +// // font color +// auto colour = is_error ? wxColour("#D01B1B") : wxColour(0xFF, 0x6F, 0x00); +// msg_label->SetForegroundColour(colour); +// +// /*tips*/ +// if (!tips.IsEmpty()) { /*Not supported yet*/ +// } +// +// Layout(); +// Fit(); +//} + +PrinterMsgPanel::PrinterMsgPanel(wxWindow *parent) + : wxPanel(parent) +{ + m_sizer = new wxBoxSizer(wxVERTICAL); + this->SetSizer(m_sizer); +} + +void PrinterMsgPanel::SetLabelList(const std::vector &texts, const wxColour &colour) +{ + if (texts == m_last_texts) + return; + + m_last_texts = texts; + m_labels.clear(); + m_sizer->Clear(true); + std::set unique_texts; + + for (const wxString &text : texts) { + if (text.empty()) { + continue; + } + if (!unique_texts.insert(text).second) { + continue; + } + Label *label = new Label(this); + label->SetFont(::Label::Body_13); + label->SetForegroundColour(colour); + label->SetLabel(text); + label->Wrap(this->GetMinSize().GetWidth()); + label->Show(); + m_sizer->Add(label, 0, wxBOTTOM, FromDIP(4)); + m_labels.push_back(label); + } + this->Show(); + this->Layout(); + Fit(); +} + +//void PrinterMsgPanel::SetLabelSingle(const wxString &texts, const wxColour &colour) +//{ +// Label *label = new Label(this); +// label->SetMinSize(wxSize(FromDIP(420), -1)); +// label->SetMaxSize(wxSize(FromDIP(420), -1)); +// label->SetFont(::Label::Body_13); +// label->SetForegroundColour(colour); +// label->SetLabel(texts); +// label->Wrap(FromDIP(-1)); +// label->Show(); +// m_sizer->Add(label, 0, wxBOTTOM, FromDIP(4)); +// m_labels.push_back(label); +// this->Layout(); +// Fit(); +//} + +wxString PrinterMsgPanel::GetLabel() { + if (!m_labels.empty() && m_labels[0] != nullptr) + return m_labels[0]->GetLabel(); + return wxEmptyString; +} + + +std::vector PrinterMsgPanel::GetLabelList() { + if (m_last_texts.empty()) + wxLogDebug(_L("No labels are currently stored.")); + return m_last_texts; +} + + + +} +}; + + diff --git a/src/slic3r/GUI/PrePrintChecker.hpp b/src/slic3r/GUI/PrePrintChecker.hpp new file mode 100644 index 0000000..96398cc --- /dev/null +++ b/src/slic3r/GUI/PrePrintChecker.hpp @@ -0,0 +1,191 @@ +#ifndef slic3r_GUI_PRE_PRINT_CHECK_hpp_ +#define slic3r_GUI_PRE_PRINT_CHECK_hpp_ + +#include +#include "Widgets/Label.hpp" +namespace Slic3r { namespace GUI { + +enum prePrintInfoLevel { + Normal, + Warning, + Error +}; + +enum prePrintInfoType { + Printer, + Filament +}; + +struct prePrintInfo +{ + prePrintInfoLevel level; + prePrintInfoType type; + wxString msg; + wxString tips; + int index; +}; + +enum PrintDialogStatus : unsigned int { + + PrintStatusErrorBegin,//->start error<- + + // Errors for printer, Block Print + PrintStatusPrinterErrorBegin, + PrintStatusInit, + PrintStatusNoUserLogin, + PrintStatusInvalidPrinter, + PrintStatusConnectingServer, + PrintStatusReadingTimeout, + PrintStatusReading, + PrintStatusConnecting, + PrintStatusReconnecting, + PrintStatusInUpgrading, + PrintStatusModeNotFDM, + PrintStatusInSystemPrinting, + PrintStatusInPrinting, + PrintStatusNozzleMatchInvalid, + PrintStatusNozzleDataInvalid, + PrintStatusNozzleDiameterMismatch, + PrintStatusNozzleTypeMismatch, + PrintStatusRefreshingMachineList, + PrintStatusSending, + PrintStatusLanModeNoSdcard, + PrintStatusNoSdcard, + PrintStatusLanModeSDcardNotAvailable, + PrintStatusNeedForceUpgrading, + PrintStatusNeedConsistencyUpgrading, + PrintStatusNotSupportedPrintAll, + PrintStatusBlankPlate, + PrintStatusUnsupportedPrinter, + PrintStatusInvalidMapping, + PrintStatusPrinterErrorEnd, + + // Errors for filament, Block Print + PrintStatusFilamentErrorBegin, + PrintStatusAmsOnSettingup, + PrintStatusAmsMappingInvalid, + PrintStatusAmsMappingU0Invalid, + PrintStatusAmsMappingMixInvalid, + PrintStatusTPUUnsupportAutoCali, + PrintStatusHasFilamentInBlackListError, + PrintStatusFilamentErrorEnd, + + PrintStatusErrorEnd,//->end error<- + + + PrintStatusWarningBegin,//->start warning<- + + // Warnings for printer + PrintStatusPrinterWarningBegin, + PrintStatusTimelapseNoSdcard, + PrintStatusTimelapseWarning, + PrintStatusMixAmsAndVtSlotWarning, + PrintStatusPrinterWarningEnd, + + // Warnings for filament + PrintStatusFilamentWarningBegin, + PrintStatusWarningKvalueNotUsed, + PrintStatusWarningTpuRightColdPulling, + PrintStatusHasFilamentInBlackListWarning, + PrintStatusFilamentWarningHighChamberTempCloseDoor, + PrintStatusFilamentWarningHighChamberTempSoft, + PrintStatusFilamentWarningUnknownHighChamberTempSoft, + PrintStatusFilamentWarningEnd, + + PrintStatusWarningEnd,//->end error<- + + /*success*/ + // printer + PrintStatusReadingFinished, + PrintStatusSendingCanceled, + PrintStatusReadyToGo, + + // filament + PrintStatusAmsMappingSuccess, + + /*Other, SendToPrinterDialog*/ + PrintStatusNotOnTheSameLAN, + PrintStatusNotSupportedSendToSDCard, + PrintStatusPublicInitFailed, + PrintStatusPublicUploadFiled, + + //y65 + PrintStatusPrinterOffline, + PrintStatusPrinterNotStandby, + PrintStatusPinrterPrinting, + PrinterNotConnectBox, + PrintStatusNeedUpgradingBox, + BoxhasSomeProblem, +}; + +class PrePrintChecker +{ +public: + std::vector printerList; + std::vector filamentList; + +public: + void clear(); + /*auto merge*/ + void add(PrintDialogStatus state, wxString msg, wxString tip); + static ::std::string get_print_status_info(PrintDialogStatus status); + + wxString get_pre_state_msg(PrintDialogStatus status); + static bool is_error(PrintDialogStatus status) { return (PrintStatusErrorBegin < status) && (PrintStatusErrorEnd > status); }; + static bool is_error_printer(PrintDialogStatus status) { return (PrintStatusPrinterErrorBegin < status) && (PrintStatusPrinterErrorEnd > status); }; + static bool is_error_filament(PrintDialogStatus status) { return (PrintStatusFilamentErrorBegin < status) && (PrintStatusFilamentErrorEnd > status); }; + static bool is_warning(PrintDialogStatus status) { return (PrintStatusWarningBegin < status) && (PrintStatusWarningEnd > status); }; + static bool is_warning_printer(PrintDialogStatus status) { return (PrintStatusPrinterWarningBegin < status) && (PrintStatusPrinterWarningEnd > status); }; + static bool is_warning_filament(PrintDialogStatus status) { return (PrintStatusFilamentWarningBegin < status) && (PrintStatusFilamentWarningEnd > status); }; +}; +//class PrePrintMsgBoard : public wxWindow +//{ +//public: +// PrePrintMsgBoard(wxWindow * parent, +// wxWindowID winid = wxID_ANY, +// const wxPoint & pos = wxDefaultPosition, +// const wxSize & size = wxDefaultSize, +// long style = wxTAB_TRAVERSAL | wxNO_BORDER, +// const wxString &name = wxASCII_STR(wxPanelNameStr) +// ); +// +//public: +// // Operations +// void addError(const wxString &msg, const wxString &tips = wxEmptyString) { Add(msg, tips, true); }; +// void addWarning(const wxString &msg, const wxString &tips = wxEmptyString) { Add(msg, tips, false); }; +// void clear() { m_sizer->Clear(); }; +// +// // Const Access +// bool isEmpty() const { return m_sizer->IsEmpty(); } +// +//private: +// void add(const wxString &msg, const wxString &tips, bool is_error); +// +//private: +// wxBoxSizer *m_sizer{nullptr}; +//}; + + + +class PrinterMsgPanel : public wxPanel +{ +public: + PrinterMsgPanel(wxWindow *parent); + + void SetLabelList(const std::vector &texts, const wxColour &colour); + + // void SetLabelSingle(const wxString &texts,const wxColour& colour); + + wxString GetLabel(); + std::vector GetLabelList(); + + private: + wxBoxSizer * m_sizer = nullptr; + std::vector