mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'SoftFever' into feature/calib
This commit is contained in:
		
						commit
						f5b28201fe
					
				
					 54 changed files with 500 additions and 1230 deletions
				
			
		|  | @ -3,6 +3,7 @@ | |||
| #include <string> | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| #include <mutex> | ||||
| #include <boost/filesystem/path.hpp> | ||||
| #include <boost/filesystem/operations.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 
 | ||||
| bool write_to_pot(boost::filesystem::path path, const std::vector<std::pair<std::string, std::string>>& data) | ||||
| { | ||||
| 	boost::filesystem::ofstream file(std::move(path), std::ios_base::app); | ||||
| 	boost::nowide::ofstream file(path.string(), std::ios_base::app); | ||||
| 	for (const auto& element : data) | ||||
| 	{ | ||||
| 		//Example of .pot element 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| #ifndef slic3r_Format_3mf_hpp_ | ||||
| #define slic3r_Format_3mf_hpp_ | ||||
| #include "../expat.h" | ||||
| #include <expat.h> | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| // PrusaFileParser is used to check 3mf file is from Prusa
 | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include <boost/algorithm/string/replace.hpp> | ||||
| #include <boost/filesystem/operations.hpp> | ||||
| #include <boost/filesystem/string_file.hpp> | ||||
| #include <boost/nowide/fstream.hpp> | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
| #include <boost/spirit/include/karma.hpp> | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <cstdint> | ||||
| #include <array> | ||||
| #include <vector> | ||||
| #include <mutex> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <optional> | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include <boost/algorithm/string/replace.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/filesystem/string_file.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| #include <boost/nowide/iostream.hpp> | ||||
| 
 | ||||
|  |  | |||
|  | @ -2889,7 +2889,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int | |||
|     // Generate intermediate layers.
 | ||||
|     // The first intermediate layer is the same as the 1st layer if there is no raft,
 | ||||
|     // or the bottom of the first intermediate layer is aligned with the bottom of the raft contact layer.
 | ||||
|     // Intermediate layers are always printed with a normal etrusion flow (non-bridging).
 | ||||
|     // Intermediate layers are always printed with a normal extrusion flow (non-bridging).
 | ||||
|     size_t idx_layer_object = 0; | ||||
|     size_t idx_extreme_first = 0; | ||||
|     if (! extremes.empty() && std::abs(extremes.front()->extreme_z() - m_slicing_params.raft_interface_top_z) < EPSILON) { | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ | |||
| #define TAU (2.0 * M_PI) | ||||
| #define NO_INDEX (std::numeric_limits<unsigned int>::max()) | ||||
| 
 | ||||
| //#define SUPPORT_TREE_DEBUG_TO_SVG
 | ||||
| // #define SUPPORT_TREE_DEBUG_TO_SVG
 | ||||
| 
 | ||||
| namespace Slic3r | ||||
| { | ||||
|  | @ -1399,7 +1399,6 @@ void TreeSupport::generate_toolpaths() | |||
| 
 | ||||
|     const size_t wall_count = object_config.tree_support_wall_count.value; | ||||
|     const bool with_infill = object_config.support_base_pattern != smpNone && object_config.support_base_pattern != smpDefault; | ||||
|     auto m_support_material_flow = support_material_flow(m_object, float(m_slicing_params.layer_height)); | ||||
| 
 | ||||
|     // coconut: use same intensity settings as SupportMaterial.cpp
 | ||||
|     auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height)); | ||||
|  | @ -1407,8 +1406,6 @@ void TreeSupport::generate_toolpaths() | |||
|     coordf_t bottom_interface_spacing = object_config.support_bottom_interface_spacing.value + m_support_material_interface_flow.spacing(); | ||||
|     coordf_t interface_density = std::min(1., m_support_material_interface_flow.spacing() / interface_spacing); | ||||
|     coordf_t bottom_interface_density = std::min(1., m_support_material_interface_flow.spacing() / bottom_interface_spacing); | ||||
|     coordf_t support_spacing = object_config.support_base_pattern_spacing.value + m_support_material_flow.spacing(); | ||||
|     coordf_t support_density = std::min(1., m_support_material_flow.spacing() / support_spacing); | ||||
| 
 | ||||
|     const coordf_t branch_radius = object_config.tree_support_branch_diameter.value / 2; | ||||
|     const coordf_t branch_radius_scaled = scale_(branch_radius); | ||||
|  | @ -1518,6 +1515,9 @@ void TreeSupport::generate_toolpaths() | |||
| 
 | ||||
|                 TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_id); | ||||
|                 Flow support_flow(support_extrusion_width, ts_layer->height, nozzle_diameter); | ||||
|                 coordf_t support_spacing         = object_config.support_base_pattern_spacing.value + support_flow.spacing(); | ||||
|                 coordf_t support_density         = std::min(1., support_flow.spacing() / support_spacing); | ||||
| 
 | ||||
|                 ts_layer->support_fills.no_sort = false; | ||||
| 
 | ||||
|                 for (auto& area_group : ts_layer->area_groups) { | ||||
|  | @ -1569,12 +1569,11 @@ void TreeSupport::generate_toolpaths() | |||
|                     } | ||||
|                     else { | ||||
|                         // base_areas
 | ||||
|                         filler_support->spacing = m_support_material_flow.spacing(); | ||||
|                         Flow flow = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() : | ||||
|                             (m_support_params.base_fill_pattern == ipRectilinear && (layer_id % num_layers_to_change_infill_direction == 0) ? support_transition_flow(m_object) : support_flow); | ||||
|                         if (area_group.dist_to_top < 10 / layer_height) { | ||||
|                             // extra 2 walls for the top tips
 | ||||
|                             make_perimeter_and_inner_brim(ts_layer->support_fills.entities, *m_object->print(), poly, wall_count + 2, flow, false); | ||||
|                         filler_support->spacing = support_flow.spacing(); | ||||
|                         Flow flow               = (layer_id == 0 && m_raft_layers == 0) ? m_object->print()->brim_flow() : support_flow; | ||||
|                         if (area_group.dist_to_top < 10 / layer_height && !with_infill) { | ||||
|                             // at least 2 walls for the top tips
 | ||||
|                             make_perimeter_and_inner_brim(ts_layer->support_fills.entities, *m_object->print(), poly, std::max(wall_count, size_t(2)), flow, false); | ||||
|                         } else { | ||||
|                             if (with_infill && layer_id > 0 && m_support_params.base_fill_pattern != ipLightning) { | ||||
|                                 filler_support->angle = Geometry::deg2rad(object_config.support_angle.value); | ||||
|  | @ -1893,7 +1892,7 @@ void TreeSupport::generate_support_areas() | |||
|     profiler.stage_finish(STAGE_DROP_DOWN_NODES); | ||||
| 
 | ||||
|     // Adjust support layer heights
 | ||||
|     adjust_layer_heights(contact_nodes); | ||||
|     // adjust_layer_heights(contact_nodes);
 | ||||
| 
 | ||||
|     //Generate support areas.
 | ||||
|     profiler.stage_start(STAGE_DRAW_CIRCLES); | ||||
|  | @ -2023,20 +2022,24 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no | |||
|             { | ||||
|                 if (print->canceled()) | ||||
|                     break; | ||||
| 
 | ||||
|                 const std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr]; | ||||
|                 TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers); | ||||
|                 assert(ts_layer != nullptr); | ||||
| 
 | ||||
|                 // skip if current layer has no points. This fixes potential crash in get_collision (see jira BBL001-355)
 | ||||
|                 if (curr_layer_nodes.empty()) | ||||
|                 if (curr_layer_nodes.empty()) { | ||||
|                     ts_layer->print_z = 0.0; | ||||
|                     ts_layer->height = 0.0; | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 Node* first_node = curr_layer_nodes.front(); | ||||
|                 ts_layer->print_z = first_node->print_z; | ||||
|                 ts_layer->height = first_node->height; | ||||
| 
 | ||||
|                 if (ts_layer->height < EPSILON) | ||||
|                 if (ts_layer->height < EPSILON) { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 ExPolygons& base_areas = ts_layer->base_areas; | ||||
|                 ExPolygons& roof_areas = ts_layer->roof_areas; | ||||
|  | @ -2057,16 +2060,16 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no | |||
| 
 | ||||
|                     const Node& node = *p_node; | ||||
|                     ExPolygon area; | ||||
|                     // 直接从overhang多边形生成,如果<EFBFBD>?
 | ||||
|                     // 1) 是混合支撑里的普通部分,
 | ||||
|                     // 2) 启用了顶部接触层<EFBFBD>?
 | ||||
|                     // 3) 是顶部空<EFBFBD>?
 | ||||
|                     // Generate directly from overhang polygon if one of the following is true:
 | ||||
|                     // 1) node is a normal part of hybrid support
 | ||||
|                     // 2) top interface layers are enabled
 | ||||
|                     // 3) node is virtual
 | ||||
|                     if (node.type == ePolygon || (top_interface_layers>0 &&node.support_roof_layers_below > 0) || node.distance_to_top<0) { | ||||
|                         if (node.overhang->contour.size() > 100 || node.overhang->holes.size()>1) | ||||
|                             area = *node.overhang; | ||||
|                         else { | ||||
|                              auto tmp = offset_ex({ *node.overhang }, scale_(m_ts_data->m_xy_distance)); | ||||
|                              if(!tmp.empty()) // 对于有缺陷的模型,overhang膨胀以后可能是空的!
 | ||||
|                              if(!tmp.empty()) // can be empty for non-manifold models
 | ||||
|                                 area = tmp[0]; | ||||
|                         } | ||||
|                     } | ||||
|  | @ -2396,7 +2399,22 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no | |||
|         char fname[10]; sprintf(fname, "%d_%.2f", layer_nr, ts_layer->print_z); | ||||
|         draw_contours_and_nodes_to_svg(-1, base_areas, roof_areas, roof_1st_layer, {}, {}, get_svg_filename(fname, "circles"), { "base", "roof", "roof1st" }); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     // export layer & print_z log
 | ||||
|     std::ofstream draw_circles_layer_out; | ||||
|     draw_circles_layer_out.open("./SVG/layer_heights_draw_circles.txt"); | ||||
|     if (draw_circles_layer_out.is_open()) { | ||||
|         for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) { | ||||
|             TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers); | ||||
|             ExPolygons& base_areas = ts_layer->base_areas; | ||||
|             ExPolygons& roof_areas = ts_layer->roof_areas; | ||||
|             ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer; | ||||
|             ExPolygons& floor_areas = ts_layer->floor_areas; | ||||
|             if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue; | ||||
|             draw_circles_layer_out << layer_nr << "     " << ts_layer->print_z << "     " << ts_layer->height << std::endl; | ||||
|         } | ||||
|     } | ||||
| #endif  // SUPPORT_TREE_DEBUG_TO_SVG
 | ||||
| 
 | ||||
|     TreeSupportLayerPtrs& ts_layers = m_object->tree_support_layers(); | ||||
|     auto iter = std::remove_if(ts_layers.begin(), ts_layers.end(), [](TreeSupportLayer* ts_layer) { return ts_layer->height < EPSILON; }); | ||||
|  | @ -2410,7 +2428,7 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no | |||
| void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | ||||
| { | ||||
|     const PrintObjectConfig &config = m_object->config(); | ||||
|     //Use Minimum Spanning Tree to connect the points on each layer and move them while dropping them down.
 | ||||
|     // Use Minimum Spanning Tree to connect the points on each layer and move them while dropping them down.
 | ||||
|     const coordf_t layer_height = config.layer_height.value; | ||||
|     const double angle = config.tree_support_branch_angle.value * M_PI / 180.; | ||||
|     const int wall_count = std::max(1, config.tree_support_wall_count.value); | ||||
|  | @ -2424,6 +2442,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|     const bool support_on_buildplate_only = config.support_on_build_plate_only.value; | ||||
|     const size_t bottom_interface_layers = config.support_interface_bottom_layers.value; | ||||
|     const size_t top_interface_layers = config.support_interface_top_layers.value; | ||||
|     std::vector<std::pair<coordf_t, coordf_t>> layer_heights = plan_layer_heights(contact_nodes); | ||||
| 
 | ||||
|     std::unordered_set<Node*> to_free_node_set; | ||||
|     m_spanning_trees.resize(contact_nodes.size()); | ||||
|  | @ -2467,16 +2486,22 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|         BOOST_LOG_TRIVIAL(debug) << "before m_avoidance_cache.size()=" << m_ts_data->m_avoidance_cache.size(); | ||||
|     } | ||||
| 
 | ||||
|     for (size_t layer_nr = contact_nodes.size() - 1; layer_nr > 0; layer_nr--) //Skip layer 0, since we can't drop down the vertices there.
 | ||||
|     for (size_t layer_nr = contact_nodes.size() - 1; layer_nr > 0; layer_nr--) // Skip layer 0, since we can't drop down the vertices there.
 | ||||
|     { | ||||
|         if (m_object->print()->canceled()) | ||||
|             break; | ||||
| 
 | ||||
|         auto& layer_contact_nodes = contact_nodes[layer_nr]; | ||||
|         std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
 | ||||
|         const Layer* ts_layer = m_object->get_tree_support_layer(layer_nr); | ||||
|         if (layer_contact_nodes.empty()) | ||||
|             continue; | ||||
| 
 | ||||
|         int jump_nr = 1; | ||||
|         while (layer_heights[layer_nr - jump_nr].second < EPSILON) | ||||
|             jump_nr++; | ||||
| 
 | ||||
|         std::deque<std::pair<size_t, Node*>> unsupported_branch_leaves; // All nodes that are leaves on this layer that would result in unsupported ('mid-air') branches.
 | ||||
|         const Layer* ts_layer = m_object->get_tree_support_layer(layer_nr); | ||||
| 
 | ||||
|         m_object->print()->set_status(60, (boost::format(_L("Support: propagate branches at layer %d")) % layer_nr).str()); | ||||
| 
 | ||||
|         Polygons layer_contours = std::move(m_ts_data->get_contours_with_holes(layer_nr)); | ||||
|  | @ -2512,8 +2537,8 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|             if (node.distance_to_top < 0) { | ||||
|                 // virtual node do not merge or move
 | ||||
|                 Node* next_node = new Node(p_node->position, p_node->distance_to_top + 1, p_node->skin_direction, p_node->support_roof_layers_below - 1, p_node->to_buildplate, p_node, | ||||
|                     m_object->get_layer(layer_nr - 1)->print_z, m_object->get_layer(layer_nr - 1)->height); | ||||
|                 contact_nodes[layer_nr - 1].emplace_back(next_node); | ||||
|                     layer_heights[layer_nr - jump_nr].first, layer_heights[layer_nr - jump_nr].second); | ||||
|                 contact_nodes[layer_nr - jump_nr].emplace_back(next_node); | ||||
|                 continue; | ||||
|             } | ||||
|             if (support_on_buildplate_only && !node.to_buildplate) //Can't rest on model and unable to reach the build plate. Then we must drop the node and leave parts unsupported.
 | ||||
|  | @ -2530,8 +2555,8 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|                 // polygon node do not merge or move
 | ||||
|                 const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[layer_nr], p_node->position); | ||||
|                 Node *next_node = new Node(p_node->position, p_node->distance_to_top + 1, p_node->skin_direction, p_node->support_roof_layers_below - 1, to_buildplate, p_node, | ||||
|                                            m_object->get_layer(layer_nr - 1)->print_z, m_object->get_layer(layer_nr - 1)->height); | ||||
|                 contact_nodes[layer_nr - 1].emplace_back(next_node); | ||||
|                     layer_heights[layer_nr - jump_nr].first, layer_heights[layer_nr - jump_nr].second); | ||||
|                 contact_nodes[layer_nr - jump_nr].emplace_back(next_node); | ||||
|                 continue; | ||||
|             } | ||||
|             /* Find which part this node is located in and group the nodes in
 | ||||
|  | @ -2608,7 +2633,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
| 
 | ||||
|                     const coordf_t branch_radius_node = calc_branch_radius(branch_radius, node.distance_to_top, tip_layers, diameter_angle_scale_factor); | ||||
| 
 | ||||
|                     auto avoid_layer = m_ts_data->get_avoidance(branch_radius_node, layer_nr - 1); | ||||
|                     auto avoid_layer = m_ts_data->get_avoidance(branch_radius_node, layer_nr - jump_nr); | ||||
|                     if (group_index == 0) | ||||
|                     { | ||||
|                         //Avoid collisions.
 | ||||
|  | @ -2620,11 +2645,11 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|                     size_t new_distance_to_top = std::max(node.distance_to_top, neighbour->distance_to_top) + 1; | ||||
|                     size_t new_support_roof_layers_below = std::max(node.support_roof_layers_below, neighbour->support_roof_layers_below) - 1; | ||||
| 
 | ||||
|                     const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr - 1), next_position); | ||||
|                     const bool to_buildplate = !is_inside_ex(m_ts_data->get_avoidance(0, layer_nr - jump_nr), next_position); | ||||
|                     Node *     next_node     = new Node(next_position, new_distance_to_top, node.skin_direction, new_support_roof_layers_below, to_buildplate, p_node, | ||||
|                                                m_object->get_layer(layer_nr - 1)->print_z, p_node->height); | ||||
|                         layer_heights[layer_nr - jump_nr].first, layer_heights[layer_nr - jump_nr].second); | ||||
|                     next_node->movement = next_position - node.position; | ||||
|                     contact_nodes[layer_nr - 1].push_back(next_node); | ||||
|                     contact_nodes[layer_nr - jump_nr].push_back(next_node); | ||||
| 
 | ||||
|                     // Make sure the next pass doesn't drop down either of these (since that already happened).
 | ||||
|                     node.merged_neighbours.push_front(neighbour); | ||||
|  | @ -2708,8 +2733,8 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
| 
 | ||||
|                         Point direction = neighbour - node.position; | ||||
|                         Node *neighbour_node = nodes_per_part[group_index][neighbour]; | ||||
|                         coordf_t branch_bottom_radius = calc_branch_radius(branch_radius, node.distance_to_top + layer_nr, tip_layers, diameter_angle_scale_factor); | ||||
|                         coordf_t neighbour_bottom_radius = calc_branch_radius(branch_radius, neighbour_node->distance_to_top + layer_nr, tip_layers, diameter_angle_scale_factor); | ||||
|                         coordf_t branch_bottom_radius = calc_branch_radius(branch_radius, node.distance_to_top + 1, tip_layers, diameter_angle_scale_factor); | ||||
|                         coordf_t neighbour_bottom_radius = calc_branch_radius(branch_radius, neighbour_node->distance_to_top + 1, tip_layers, diameter_angle_scale_factor); | ||||
|                         const coordf_t min_overlap = branch_radius; | ||||
|                         double max_converge_distance = tan_angle * (ts_layer->print_z - DO_NOT_MOVER_UNDER_MM) + branch_bottom_radius + neighbour_bottom_radius - min_overlap; | ||||
|                         if (vsize2_with_unscale(direction) > max_converge_distance * max_converge_distance) | ||||
|  | @ -2740,7 +2765,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|                     branch_radius_temp = branch_radius_node; | ||||
|                 } | ||||
| #endif | ||||
|                 auto avoid_layer = m_ts_data->get_avoidance(branch_radius_node, layer_nr - 1); | ||||
|                 auto avoid_layer = m_ts_data->get_avoidance(branch_radius_node, layer_nr - jump_nr); | ||||
| 
 | ||||
|                 Point to_outside = projection_onto_ex(avoid_layer, node.position); | ||||
|                 Point movement = to_outside - node.position; | ||||
|  | @ -2785,15 +2810,15 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
| 
 | ||||
|                 const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[layer_nr], next_layer_vertex);// !is_inside_ex(m_ts_data->get_avoidance(m_ts_data->m_xy_distance, layer_nr - 1), next_layer_vertex);
 | ||||
|                 Node *     next_node     = new Node(next_layer_vertex, node.distance_to_top + 1, node.skin_direction, node.support_roof_layers_below - 1, to_buildplate, p_node, | ||||
|                                            m_object->get_layer(layer_nr - 1)->print_z, m_object->get_layer(layer_nr-1)->height); | ||||
|                     layer_heights[layer_nr - jump_nr].first, layer_heights[layer_nr - jump_nr].second); | ||||
|                 next_node->movement  = movement; | ||||
|                 contact_nodes[layer_nr - 1].push_back(next_node); | ||||
|                 contact_nodes[layer_nr - jump_nr].push_back(next_node); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| #ifdef SUPPORT_TREE_DEBUG_TO_SVG | ||||
|         draw_contours_and_nodes_to_svg(layer_nr, m_ts_data->get_avoidance(0, layer_nr), m_ts_data->get_avoidance(branch_radius_temp, layer_nr), m_ts_data->m_layer_outlines_below[layer_nr], | ||||
|             contact_nodes[layer_nr], contact_nodes[layer_nr - 1], "contact_points", { "overhang","avoid","outline" }, { "blue","red","yellow" }); | ||||
|             contact_nodes[layer_nr], contact_nodes[layer_nr - jump_nr], "contact_points", { "overhang","avoid","outline" }, { "blue","red","yellow" }); | ||||
| #endif | ||||
| 
 | ||||
|         // Prune all branches that couldn't find support on either the model or the buildplate (resulting in 'mid-air' branches).
 | ||||
|  | @ -2840,6 +2865,27 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes) | |||
|         delete node; | ||||
|     } | ||||
|     to_free_node_set.clear(); | ||||
| 
 | ||||
|     // Merge empty contact_nodes layers
 | ||||
| 
 | ||||
| 
 | ||||
| #ifdef SUPPORT_TREE_DEBUG_TO_SVG | ||||
|     // export all print_z and layer height into .txt
 | ||||
|     std::ofstream layer_heights_out; | ||||
|     layer_heights_out.open("./SVG/layer_heights_drop_nodes.txt"); | ||||
|     //layer_heights_out.open("layer_heights_out.txt");
 | ||||
|     if (layer_heights_out.is_open()) { | ||||
|         for (int i = 0; i < layer_heights.size(); i++) { | ||||
|             if (contact_nodes[i].empty()) { | ||||
|                 layer_heights_out << 0 << "    " << 0 << std::endl; | ||||
|             } | ||||
|             else { | ||||
|                 layer_heights_out << contact_nodes[i][0]->print_z << "    " << contact_nodes[i][0]->height << std::endl; | ||||
|             } | ||||
|         } | ||||
|         layer_heights_out.close(); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void TreeSupport::adjust_layer_heights(std::vector<std::vector<Node*>>& contact_nodes) | ||||
|  | @ -2849,6 +2895,7 @@ void TreeSupport::adjust_layer_heights(std::vector<std::vector<Node*>>& contact_ | |||
| 
 | ||||
|     const PrintConfig& print_config = m_object->print()->config(); | ||||
|     const PrintObjectConfig& config = m_object->config(); | ||||
| 
 | ||||
|     if (!print_config.independent_support_layer_height) { | ||||
|         for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) { | ||||
|             std::vector<Node*>& curr_layer_nodes = contact_nodes[layer_nr]; | ||||
|  | @ -2932,6 +2979,108 @@ void TreeSupport::adjust_layer_heights(std::vector<std::vector<Node*>>& contact_ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<std::pair<coordf_t, coordf_t>> TreeSupport::plan_layer_heights(std::vector<std::vector<Node*>>& contact_nodes) | ||||
| { | ||||
|     const PrintObjectConfig& config = m_object->config(); | ||||
|     const coordf_t max_layer_height = m_slicing_params.max_layer_height; | ||||
|     const coordf_t layer_height = config.layer_height.value; | ||||
|     coordf_t z_distance_top = m_slicing_params.gap_support_object; | ||||
|     // BBS: add extra distance if thick bridge is enabled
 | ||||
|     // Note: normal support uses print_z, but tree support uses integer layers, so we need to subtract layer_height
 | ||||
|     if (!m_slicing_params.soluble_interface && m_object_config->thick_bridges) { | ||||
|         z_distance_top += m_object->layers()[0]->regions()[0]->region().bridging_height_avg(m_object->print()->config()) - layer_height; | ||||
|     } | ||||
|     const size_t support_roof_layers = config.support_interface_top_layers.value; | ||||
|     const int z_distance_top_layers = round_up_divide(scale_(z_distance_top), scale_(layer_height)) + 1; | ||||
|     std::vector<std::pair<coordf_t, coordf_t>> layer_heights(contact_nodes.size(), std::pair<coordf_t, coordf_t>(0.0, 0.0)); | ||||
|     std::vector<int> bounds; | ||||
| 
 | ||||
|     if (layer_height == max_layer_height) | ||||
|         return std::vector<std::pair<coordf_t, coordf_t>>(); | ||||
| 
 | ||||
|     bounds.push_back(0); | ||||
|     // Keep first layer still
 | ||||
|     layer_heights[0].first = m_object->get_layer(0)->print_z; | ||||
|     layer_heights[0].second = m_object->get_layer(0)->height; | ||||
|     // Collect top contact layers
 | ||||
|     for (int layer_nr = 1; layer_nr < contact_nodes.size(); layer_nr++) | ||||
|     { | ||||
|         if (!contact_nodes[layer_nr].empty()) | ||||
|             for (int i = 0; i < support_roof_layers + z_distance_top_layers + 1; i++) { | ||||
|                 if (layer_nr - i > 0) { | ||||
|                     bounds.push_back(layer_nr - i); | ||||
|                     layer_heights[layer_nr - i].first = m_object->get_layer(layer_nr - i)->print_z; | ||||
|                     layer_heights[layer_nr - i].second = m_object->get_layer(layer_nr - i)->height; | ||||
|                 }  | ||||
|                 else { | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|     } | ||||
|     std::set<int> s(bounds.begin(), bounds.end()); | ||||
|     bounds.assign(s.begin(), s.end()); | ||||
| 
 | ||||
|     for (size_t idx_extreme = 0; idx_extreme < bounds.size(); idx_extreme++) { | ||||
|         int extr2_layer_nr = bounds[idx_extreme]; | ||||
|         coordf_t extr2z = m_object->get_layer(extr2_layer_nr)->bottom_z(); | ||||
|         int extr1_layer_nr = idx_extreme == 0 ? -1 : bounds[idx_extreme - 1]; | ||||
|         coordf_t extr1z = idx_extreme == 0 ? 0.f : m_object->get_layer(extr1_layer_nr)->print_z; | ||||
|         coordf_t dist = extr2z - extr1z; | ||||
| 
 | ||||
|         // Insert intermediate layers.
 | ||||
|         size_t n_layers_extra = size_t(ceil(dist / (m_slicing_params.max_suport_layer_height + EPSILON))); | ||||
|         int actual_internel_layers = extr2_layer_nr - extr1_layer_nr - 1; | ||||
|         int extr_layers_left = extr2_layer_nr - extr1_layer_nr - n_layers_extra - 1; | ||||
|         if (n_layers_extra < 1) | ||||
|             continue; | ||||
| 
 | ||||
|         coordf_t step = dist / coordf_t(n_layers_extra); | ||||
|         coordf_t print_z = extr1z + step; | ||||
|         assert(step >= layer_height - EPSILON); | ||||
|         for (int layer_nr = extr1_layer_nr + 1; layer_nr < extr2_layer_nr; layer_nr++) { | ||||
|             // if (curr_layer_nodes.empty()) continue;
 | ||||
|             if (std::abs(print_z - m_object->get_layer(layer_nr)->print_z) < step / 2 + EPSILON || extr_layers_left < 1) { | ||||
|                 layer_heights[layer_nr].first = print_z; | ||||
|                 layer_heights[layer_nr].second = step; | ||||
|                 print_z += step; | ||||
|             } | ||||
|             else { | ||||
|                 // can't clear curr_layer_nodes, or the model will have empty layers
 | ||||
|                 layer_heights[layer_nr].first = 0.0; | ||||
|                 layer_heights[layer_nr].second = 0.0; | ||||
|                 extr_layers_left--; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| #ifdef SUPPORT_TREE_DEBUG_TO_SVG | ||||
|     // export all print_z and layer height into .txt
 | ||||
|     std::ofstream layer_heights_out; | ||||
|     layer_heights_out.open("./SVG/layer_heights_out.txt"); | ||||
|     //layer_heights_out.open("layer_heights_out.txt");
 | ||||
|     if (layer_heights_out.is_open()) { | ||||
|         for (int i = 0; i < layer_heights.size(); i++) { | ||||
|             layer_heights_out << layer_heights[i].first << "    " << layer_heights[i].second << std::endl; | ||||
|         } | ||||
|         layer_heights_out.close(); | ||||
|     } | ||||
|     // check bounds
 | ||||
|     if (1) | ||||
|     { | ||||
|         std::ofstream bounds_out; | ||||
|         bounds_out.open("bounds.txt"); | ||||
|         if (bounds_out.is_open()) { | ||||
|             for (int i = 0; i < bounds.size(); i++) { | ||||
|                 bounds_out << bounds[i] << std::endl; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     return layer_heights; | ||||
| } | ||||
| 
 | ||||
| void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::Node*>>& contact_nodes) | ||||
| { | ||||
|     const PrintObjectConfig &config = m_object->config(); | ||||
|  | @ -3118,6 +3267,16 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N | |||
|          | ||||
|         BOOST_LOG_TRIVIAL(info) << "avg_node_per_layer=" << avg_node_per_layer << ", nodes_angle=" << nodes_angle; | ||||
|     } | ||||
| #ifdef SUPPORT_TREE_DEBUG_TO_SVG | ||||
|     std::ofstream contact_nodes_out; | ||||
|     contact_nodes_out.open("./SVG/contact_nodes.txt"); | ||||
|     if (contact_nodes_out.is_open()) { | ||||
|         for (int i = 0; i < contact_nodes.size(); i++) { | ||||
|             if (!contact_nodes[i].empty()) | ||||
|                 contact_nodes_out << i << std::endl; | ||||
|         } | ||||
|     } | ||||
| #endif // SUPPORT_TREE_DEBUG_TO_SVG
 | ||||
| } | ||||
| 
 | ||||
| void TreeSupport::insert_dropped_node(std::vector<Node*>& nodes_layer, Node* p_node) | ||||
|  |  | |||
|  | @ -170,7 +170,7 @@ public: | |||
| struct LineHash { | ||||
|     size_t operator()(const Line& line) const { | ||||
|         return (std::hash<coord_t>()(line.a(0)) ^ std::hash<coord_t>()(line.b(1))) * 102 + | ||||
|             (std::hash<coord_t>()(line.a(0)) ^ std::hash<coord_t>()(line.b(1))) * 10222; | ||||
|             (std::hash<coord_t>()(line.a(1)) ^ std::hash<coord_t>()(line.b(0))) * 10222; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -401,6 +401,12 @@ private: | |||
| 
 | ||||
|     void adjust_layer_heights(std::vector<std::vector<Node*>>& contact_nodes); | ||||
| 
 | ||||
|     /*! BBS: MusangKing: maximum layer height
 | ||||
|      * \brief Optimize the generation of tree support by pre-planning the layer_heights | ||||
|      *  | ||||
|     */ | ||||
| 
 | ||||
|     std::vector<std::pair<coordf_t, coordf_t>> plan_layer_heights(std::vector<std::vector<Node*>>& contact_nodes); | ||||
|     /*!
 | ||||
|      * \brief Creates points where support contacts the model. | ||||
|      * | ||||
|  |  | |||
|  | @ -1405,7 +1405,7 @@ bool bbl_calc_md5(std::string &filename, std::string &md5_out) | |||
|     unsigned char digest[16]; | ||||
|     MD5_CTX       ctx; | ||||
|     MD5_Init(&ctx); | ||||
|     boost::filesystem::ifstream ifs(filename, std::ios::binary); | ||||
|     boost::nowide::ifstream ifs(filename, std::ios::binary); | ||||
|     std::string                 buf(64 * 1024, 0); | ||||
|     const std::size_t &         size      = boost::filesystem::file_size(filename); | ||||
|     std::size_t                 left_size = size; | ||||
|  |  | |||
|  | @ -41,11 +41,7 @@ export LD_LIBRARY_PATH="\$DIR/bin" | |||
| 
 | ||||
| # FIXME: BambuStudio segfault workarounds | ||||
| # 1) BambuStudio will segfault on systems where locale info is not as expected (i.e. Holo-ISO arch-based distro) | ||||
| # 2) BambuStudio will segfault with a boost logging error if ~/.config/BambuStudio doesn't exist on first run | ||||
| export LC_ALL=C | ||||
| # FIXME: BambuStudio doesn't respect dark mode; use GTK_THEME workaround from sigxcpu76                                      │ | ||||
| export GTK_THEME=Adwaita:light | ||||
| mkdir -p \${HOME}/.config/BambuStudio/ 2> /dev/null | ||||
| 
 | ||||
| exec "\$DIR/bin/@SLIC3R_APP_CMD@" "\$@" | ||||
| EOF | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ void AMSMaterialsSetting::create() | |||
|     m_clrData->SetChooseFull(true); | ||||
|     m_clrData->SetChooseAlpha(false); | ||||
| 
 | ||||
|     m_clr_picker        = new Button(this, "", ""); | ||||
|     m_clr_picker  = new Button(this, wxEmptyString, wxEmptyString, wxBU_AUTODRAW); | ||||
|     m_clr_picker->SetCanFocus(false); | ||||
|     m_clr_picker->SetSize(FromDIP(50), FromDIP(25)); | ||||
|     m_clr_picker->SetMinSize(wxSize(FromDIP(50), FromDIP(25))); | ||||
|  | @ -364,7 +364,12 @@ void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event) | |||
|     show_flag = true; | ||||
|     if (clr_dialog->ShowModal() == wxID_OK) { | ||||
|         m_clrData = &(clr_dialog->GetColourData()); | ||||
|         m_clr_picker->SetBackgroundColor(m_clrData->GetColour()); | ||||
|         m_clr_picker->SetBackgroundColor(wxColour( | ||||
|             m_clrData->GetColour().Red(), | ||||
|             m_clrData->GetColour().Green(), | ||||
|             m_clrData->GetColour().Blue(), | ||||
|             254 | ||||
|         )); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -374,13 +379,19 @@ bool AMSMaterialsSetting::Show(bool show) | |||
|         m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE); | ||||
|         m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); | ||||
|         m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20))); | ||||
|         m_clr_picker->SetBackgroundColour(m_clr_picker->GetParent()->GetBackgroundColour()); | ||||
|     } | ||||
|     return DPIDialog::Show(show);  | ||||
| } | ||||
| 
 | ||||
| void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max) | ||||
| { | ||||
|     m_clr_picker->SetBackgroundColor(m_clrData->GetColour()); | ||||
|     m_clr_picker->SetBackgroundColor(wxColour( | ||||
|         m_clrData->GetColour().Red(), | ||||
|         m_clrData->GetColour().Green(), | ||||
|         m_clrData->GetColour().Blue(), | ||||
|         254 | ||||
|     )); | ||||
| 
 | ||||
|     if (!m_is_third) { | ||||
|         m_button_confirm->Hide(); | ||||
|  |  | |||
|  | @ -83,7 +83,7 @@ protected: | |||
|     Button *            m_button_confirm; | ||||
|     wxStaticText*       m_tip_readonly; | ||||
|     Button *            m_button_close; | ||||
|     Button *          m_clr_picker; | ||||
|     Button *            m_clr_picker; | ||||
|     wxColourData *      m_clrData; | ||||
| #ifdef __APPLE__ | ||||
|     wxComboBox *m_comboBox_filament_mac; | ||||
|  |  | |||
|  | @ -200,6 +200,11 @@ void AMSSetting::create() | |||
|     m_panel_img->Layout(); | ||||
|     m_sizer_img->Fit(m_panel_img); | ||||
| 
 | ||||
|     m_sizer_remain_block = new wxBoxSizer(wxVERTICAL);  | ||||
|     m_sizer_remain_block->Add(m_sizer_remain, 0, wxEXPAND | wxTOP, FromDIP(8)); | ||||
|     m_sizer_remain_block->Add(0, 0, 0, wxTOP, 8); | ||||
|     m_sizer_remain_block->Add(m_sizer_remain_tip, 0, wxLEFT, 18); | ||||
|     m_sizer_remain_block->Add(0, 0, 0, wxTOP, 15); | ||||
| 
 | ||||
|     m_sizerl_body->Add(m_sizer_Insert_material, 0, wxEXPAND, 0); | ||||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 8); | ||||
|  | @ -209,10 +214,7 @@ void AMSSetting::create() | |||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 8); | ||||
|     m_sizerl_body->Add(m_sizer_starting_tip, 0, wxLEFT, 18); | ||||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 15); | ||||
|     m_sizerl_body->Add(m_sizer_remain, 0, wxEXPAND | wxTOP, FromDIP(8)); | ||||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 8); | ||||
|     m_sizerl_body->Add(m_sizer_remain_tip, 0, wxLEFT, 18); | ||||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 15); | ||||
|     m_sizerl_body->Add(m_sizer_remain_block, 0, wxEXPAND, 0); | ||||
|     m_sizerl_body->Add(m_sizer_switch_filament, 0, wxEXPAND | wxTOP, FromDIP(8)); | ||||
|     m_sizerl_body->Add(0, 0, 0, wxTOP, 8); | ||||
|     m_sizerl_body->Add(m_sizer_switch_filament_tip, 0, wxLEFT, 18); | ||||
|  | @ -231,6 +233,17 @@ void AMSSetting::create() | |||
| 
 | ||||
|     this->Centre(wxBOTH); | ||||
|     wxGetApp().UpdateDlgDarkUI(this); | ||||
| 
 | ||||
|     Bind(wxEVT_SHOW, [this](auto& e) { | ||||
|         if (this->IsShown()) { | ||||
|             if (ams_support_remain) { | ||||
|                 m_sizer_remain_block->Show(true); | ||||
|             } | ||||
|             else { | ||||
|                 m_sizer_remain_block->Show(false); | ||||
|             } | ||||
|         }    | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void AMSSetting::update_insert_material_read_mode(bool selected) | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ public: | |||
|     wxString      append_title(wxString text); | ||||
|     wxStaticText *append_text(wxString text); | ||||
|     MachineObject *obj{nullptr}; | ||||
|     bool           ams_support_remain{false}; | ||||
|     int            ams_id { 0 }; | ||||
| 
 | ||||
| protected: | ||||
|  | @ -72,6 +73,7 @@ protected: | |||
|     wxBoxSizer *m_sizer_starting_tip_inline; | ||||
|     wxBoxSizer *m_sizer_remain_inline; | ||||
|     wxBoxSizer *m_sizer_switch_filament_inline; | ||||
|     wxBoxSizer *m_sizer_remain_block; | ||||
| }; | ||||
| 
 | ||||
| }} // namespace Slic3r::GUI
 | ||||
|  |  | |||
|  | @ -456,7 +456,9 @@ void AuFile::on_set_cover() | |||
| { | ||||
|     if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>(); } | ||||
| 
 | ||||
|     wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString(); | ||||
|     fs::path path(into_path(m_file_name)); | ||||
|     wxGetApp().plater()->model().model_info->cover_file = path.string(); | ||||
|     //wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString();
 | ||||
| 
 | ||||
|     auto full_path          = m_file_path.branch_path(); | ||||
|     auto full_root_path         = full_path.branch_path(); | ||||
|  | @ -696,7 +698,8 @@ void AuFolderPanel::update_cover() | |||
|     if (wxGetApp().plater()->model().model_info != nullptr) { | ||||
|         for (auto i = 0; i < m_aufiles_list.GetCount(); i++) { | ||||
|             AuFiles *aufile = m_aufiles_list[i]; | ||||
|             if (wxGetApp().plater()->model().model_info->cover_file == aufile->file->m_file_name) { | ||||
| 
 | ||||
|             if (wxString::FromUTF8(wxGetApp().plater()->model().model_info->cover_file) == aufile->file->m_file_name) { | ||||
|                 aufile->file->set_cover(true); | ||||
|             } else { | ||||
|                 aufile->file->set_cover(false); | ||||
|  |  | |||
|  | @ -271,6 +271,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con | |||
|     } | ||||
| 
 | ||||
|     double sparse_infill_density = config->option<ConfigOptionPercent>("sparse_infill_density")->value; | ||||
|     auto timelapse_type = config->opt_enum<TimelapseType>("timelapse_type"); | ||||
| 
 | ||||
|     if (config->opt_bool("spiral_mode") && | ||||
|         ! (config->opt_int("wall_loops") == 1 && | ||||
|  | @ -279,12 +280,12 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con | |||
|            ! config->opt_bool("enable_support") && | ||||
|            config->opt_int("enforce_support_layers") == 0 && | ||||
|            config->opt_bool("ensure_vertical_shell_thickness") && | ||||
|            ! config->opt_bool("detect_thin_wall"))) | ||||
|            ! config->opt_bool("detect_thin_wall") && | ||||
|             config->opt_enum<TimelapseType>("timelapse_type") == TimelapseType::tlTraditional)) | ||||
|     { | ||||
|         wxString msg_text = _(L("Spiral mode only works when wall loops is 1, \n" | ||||
|                                 "support is disabled, top shell layers is 0 and sparse infill density is 0\n")); | ||||
|         wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional")); | ||||
|         if (is_global_config) | ||||
|             msg_text += "\n" + _(L("Change these settings automatically? \n" | ||||
|             msg_text += "\n\n" + _(L("Change these settings automatically? \n" | ||||
|                                      "Yes - Change these settings and enable spiral mode automatically\n" | ||||
|                                      "No  - Give up using spiral mode this time")); | ||||
|         MessageDialog dialog(m_msg_dlg_parent, msg_text, "", | ||||
|  | @ -301,7 +302,9 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con | |||
|             new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0)); | ||||
|             new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(true)); | ||||
|             new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); | ||||
|             new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional)); | ||||
|             sparse_infill_density = 0; | ||||
|             timelapse_type = TimelapseType::tlTraditional; | ||||
|             support = false; | ||||
|         } | ||||
|         else { | ||||
|  | @ -310,6 +313,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con | |||
|         apply(config, &new_conf); | ||||
|         if (cb_value_change) { | ||||
|             cb_value_change("sparse_infill_density", sparse_infill_density); | ||||
|             cb_value_change("timelapse_type", timelapse_type); | ||||
|             if (!support) | ||||
|                 cb_value_change("enable_support", false); | ||||
|         } | ||||
|  |  | |||
|  | @ -1259,6 +1259,29 @@ bool MachineObject::is_recording() | |||
|     return camera_recording; | ||||
| } | ||||
| 
 | ||||
| void MachineObject::parse_version_func() | ||||
| { | ||||
|     auto ota_version = module_vers.find("ota"); | ||||
|     if (printer_type == "BL-P001" || | ||||
|         printer_type == "BL-P002") { | ||||
|         if (ota_version != module_vers.end()) { | ||||
|             if (ota_version->second.sw_ver.compare("01.01.01.00") <= 0) { | ||||
|                 ams_support_remain                      = false; | ||||
|                 ams_support_auto_switch_filament_flag   = false; | ||||
|                 is_xcam_buildplate_supported            = false; | ||||
|                 xcam_support_recovery_step_loss         = false; | ||||
|                 is_support_send_to_sdcard               = false; | ||||
|             } else { | ||||
|                 ams_support_remain                      = true; | ||||
|                 ams_support_auto_switch_filament_flag   = true; | ||||
|                 is_xcam_buildplate_supported            = true; | ||||
|                 xcam_support_recovery_step_loss         = true; | ||||
|                 is_support_send_to_sdcard               = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int MachineObject::command_get_version(bool with_retry) | ||||
| { | ||||
|     BOOST_LOG_TRIVIAL(info) << "command_get_version"; | ||||
|  | @ -1990,9 +2013,15 @@ bool MachineObject::is_function_supported(PrinterFunction func) | |||
|         func_name = "FUNC_AI_MONITORING"; | ||||
|         break; | ||||
|     case FUNC_BUILDPLATE_MARKER_DETECT: | ||||
|         parse_version_func(); | ||||
|         if (!is_xcam_buildplate_supported) | ||||
|             return false; | ||||
|         func_name = "FUNC_BUILDPLATE_MARKER_DETECT"; | ||||
|         break; | ||||
|     case FUNC_AUTO_RECOVERY_STEP_LOSS: | ||||
|         parse_version_func(); | ||||
|         if (!xcam_support_recovery_step_loss) | ||||
|             return false; | ||||
|         func_name = "FUNC_AUTO_RECOVERY_STEP_LOSS"; | ||||
|         break; | ||||
|     case FUNC_FLOW_CALIBRATION: | ||||
|  | @ -2026,9 +2055,15 @@ bool MachineObject::is_function_supported(PrinterFunction func) | |||
|         func_name = "FUNC_ALTER_RESOLUTION"; | ||||
|         break; | ||||
|     case FUNC_SEND_TO_SDCARD: | ||||
|         parse_version_func(); | ||||
|         if (!is_support_send_to_sdcard) | ||||
|             return false; | ||||
|         func_name = "FUNC_SEND_TO_SDCARD"; | ||||
|         break; | ||||
|     case FUNC_AUTO_SWITCH_FILAMENT: | ||||
|         parse_version_func(); | ||||
|         if (!ams_support_auto_switch_filament_flag) | ||||
|             return false; | ||||
|         func_name = "FUNC_AUTO_SWITCH_FILAMENT"; | ||||
|         break; | ||||
|     case FUNC_VIRTUAL_CAMERA: | ||||
|  | @ -2615,6 +2650,9 @@ int MachineObject::parse_json(std::string payload) | |||
|                             else { | ||||
|                                 if (jj["xcam"].contains("buildplate_marker_detector")) { | ||||
|                                     xcam_buildplate_marker_detector = jj["xcam"]["buildplate_marker_detector"].get<bool>(); | ||||
|                                     is_xcam_buildplate_supported = true; | ||||
|                                 } else { | ||||
|                                     is_xcam_buildplate_supported = false; | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|  | @ -2874,6 +2912,8 @@ int MachineObject::parse_json(std::string payload) | |||
|                                         } | ||||
|                                         if (tray_it->contains("remain")) { | ||||
|                                             curr_tray->remain = (*tray_it)["remain"].get<int>(); | ||||
|                                         } else { | ||||
|                                             curr_tray->remain = -1; | ||||
|                                         } | ||||
|                                         try { | ||||
|                                             if (!ams_id.empty() && !curr_tray->id.empty()) { | ||||
|  | @ -3021,6 +3061,7 @@ int MachineObject::parse_json(std::string payload) | |||
|                             ver_info.hw_ver = (*it)["hw_ver"].get<std::string>(); | ||||
|                         module_vers.emplace(ver_info.name, ver_info); | ||||
|                     } | ||||
|                     parse_version_func(); | ||||
|                     bool get_version_result = true; | ||||
|                     if (j["info"].contains("result")) | ||||
|                         if (j["info"]["result"].get<std::string>() == "fail") | ||||
|  |  | |||
|  | @ -423,8 +423,10 @@ public: | |||
|     bool  ams_insert_flag { false }; | ||||
|     bool  ams_power_on_flag { false }; | ||||
|     bool  ams_calibrate_remain_flag { false }; | ||||
|     bool  ams_support_auto_switch_filament_flag { true }; | ||||
|     bool  ams_auto_switch_filament_flag  { false }; | ||||
|     bool  ams_support_use_ams { false }; | ||||
|     bool  ams_support_remain { true }; | ||||
|     int   ams_humidity; | ||||
|     int   ams_user_setting_hold_count = 0; | ||||
|     AmsStatusMain ams_status_main; | ||||
|  | @ -579,8 +581,10 @@ public: | |||
|     bool xcam_ai_monitoring{ false }; | ||||
|     int  xcam_ai_monitoring_hold_count = 0; | ||||
|     std::string xcam_ai_monitoring_sensitivity; | ||||
|     bool is_xcam_buildplate_supported { true }; | ||||
|     bool xcam_buildplate_marker_detector{ false }; | ||||
|     int  xcam_buildplate_marker_hold_count = 0; | ||||
|     bool xcam_support_recovery_step_loss { true }; | ||||
|     bool xcam_auto_recovery_step_loss{ false }; | ||||
|     int  xcam_auto_recovery_hold_count = 0; | ||||
|     int  ams_print_option_count = 0; | ||||
|  | @ -588,6 +592,7 @@ public: | |||
|     /* sdcard */ | ||||
|     MachineObject::SdcardState sdcard_state { NO_SDCARD }; | ||||
|     MachineObject::SdcardState get_sdcard_state(); | ||||
|     bool is_support_send_to_sdcard { true }; | ||||
| 
 | ||||
|     /* HMS */ | ||||
|     std::vector<HMSItem>    hms_list; | ||||
|  | @ -622,6 +627,8 @@ public: | |||
| 
 | ||||
|     MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip); | ||||
|     ~MachineObject(); | ||||
| 
 | ||||
|     void parse_version_func(); | ||||
|     /* command commands */ | ||||
|     int command_get_version(bool with_retry = true); | ||||
|     int command_request_push_all(); | ||||
|  |  | |||
|  | @ -1699,7 +1699,7 @@ void GUI_App::init_networking_callbacks() | |||
|                     wxCommandEvent event(EVT_CONNECT_LAN_MODE_PRINT); | ||||
| 
 | ||||
|                     if (obj) { | ||||
|                          | ||||
| 
 | ||||
|                         if (obj->is_lan_mode_printer()) { | ||||
|                             if (state == ConnectStatus::ConnectStatusOk) { | ||||
|                                 obj->command_request_push_all(); | ||||
|  | @ -1892,6 +1892,9 @@ void GUI_App::init_app_config() | |||
|             if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() ) | ||||
|                 dir = wxFileName::GetHomeDir() + wxS("/.config"); | ||||
|             set_data_dir((dir + "/" + GetAppName()).ToUTF8().data()); | ||||
|             boost::filesystem::path data_dir_path(data_dir()); | ||||
|             if (!boost::filesystem::exists(data_dir_path)) | ||||
|                 boost::filesystem::create_directory(data_dir_path); | ||||
|         #endif | ||||
|     } else { | ||||
|         m_datadir_redefined = true; | ||||
|  | @ -2729,7 +2732,7 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju | |||
| 
 | ||||
|     /*if (m_is_dark_mode != dark_mode() )
 | ||||
|         m_is_dark_mode = dark_mode();*/ | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
|     if (m_is_dark_mode) { | ||||
|         auto original_col = window->GetBackgroundColour(); | ||||
|  |  | |||
|  | @ -201,7 +201,7 @@ void GridCellFilamentsEditor::BeginEdit(int row, int col, wxGrid* grid) | |||
|     { | ||||
|         // This event handler is needed to properly dismiss the editor when the popup is closed
 | ||||
|         m_control->Bind(wxEVT_COMBOBOX_CLOSEUP, &GridCellFilamentsEditor::OnComboCloseUp, this); | ||||
|         evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler); | ||||
|         evtHandler = static_cast<wxGridCellEditorEvtHandler*>(m_control->GetEventHandler()); | ||||
|     } | ||||
| 
 | ||||
|     // Don't immediately end if we get a kill focus event within BeginEdit
 | ||||
|  | @ -403,7 +403,7 @@ void GridCellChoiceEditor::BeginEdit(int row, int col, wxGrid *grid) | |||
|     if (m_control) { | ||||
|         // This event handler is needed to properly dismiss the editor when the popup is closed
 | ||||
|         m_control->Bind(wxEVT_COMBOBOX_CLOSEUP, &GridCellChoiceEditor::OnComboCloseUp, this); | ||||
|         evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler); | ||||
|         evtHandler = static_cast<wxGridCellEditorEvtHandler*>(m_control->GetEventHandler()); | ||||
|     } | ||||
| 
 | ||||
|     // Don't immediately end if we get a kill focus event within BeginEdit
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include "MsgDialog.hpp" | ||||
| #include "DownloadProgressDialog.hpp" | ||||
| 
 | ||||
| #include <boost/filesystem/string_file.hpp> | ||||
| #undef pid_t | ||||
| #include <boost/process.hpp> | ||||
| #ifdef __WIN32__ | ||||
|  |  | |||
|  | @ -1198,6 +1198,28 @@ std::vector<int> PartPlate::get_extruders() const | |||
| 	return plate_extruders; | ||||
| } | ||||
| 
 | ||||
| std::vector<int> PartPlate::get_used_extruders() | ||||
| { | ||||
| 	std::vector<int> used_extruders; | ||||
| 	// if gcode.3mf file
 | ||||
| 	if (m_model->objects.empty()) { | ||||
| 		for (int i = 0; i < slice_filaments_info.size(); i++) { | ||||
| 			used_extruders.push_back(slice_filaments_info[i].id + 1); | ||||
| 		} | ||||
| 		return used_extruders; | ||||
| 	} | ||||
| 
 | ||||
| 	GCodeProcessorResult* result = get_slice_result(); | ||||
| 	if (!result) | ||||
| 		return used_extruders; | ||||
| 
 | ||||
| 	PrintEstimatedStatistics& ps = result->print_statistics; | ||||
| 	for (auto it = ps.volumes_per_extruder.begin(); it != ps.volumes_per_extruder.end(); it++) { | ||||
| 		used_extruders.push_back(it->first + 1); | ||||
| 	} | ||||
| 	return used_extruders; | ||||
| } | ||||
| 
 | ||||
| Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volume) const | ||||
| { | ||||
| 	Vec3d wipe_tower_size; | ||||
|  |  | |||
|  | @ -259,6 +259,7 @@ public: | |||
|     Vec3d get_origin() { return m_origin; } | ||||
|     Vec3d estimate_wipe_tower_size(const double w, const double wipe_volume) const; | ||||
|     std::vector<int> get_extruders() const; | ||||
|     std::vector<int> get_used_extruders(); | ||||
| 
 | ||||
|     /* instance related operations*/ | ||||
|     //judge whether instance is bound in plate or not
 | ||||
|  |  | |||
|  | @ -2930,7 +2930,7 @@ void SelectMachineDialog::set_default() | |||
|     } | ||||
| 
 | ||||
|     // material info
 | ||||
|     auto        extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders(); | ||||
|     auto        extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_extruders(); | ||||
|     BitmapCache bmcache; | ||||
| 
 | ||||
|     MaterialHash::iterator iter = m_materialList.begin(); | ||||
|  |  | |||
|  | @ -2707,7 +2707,7 @@ void Selection::paste_objects_from_clipboard() | |||
|             auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center(); | ||||
|             auto point_offset = start_offset - start_point; | ||||
|             auto empty_cell   = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1}); | ||||
|             displacement    = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_point(2)}; | ||||
|             displacement      = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)}; | ||||
|         } | ||||
| 
 | ||||
|         for (ModelInstance* inst : dst_object->instances) | ||||
|  |  | |||
|  | @ -1807,6 +1807,7 @@ void StatusPanel::update_ams(MachineObject *obj) | |||
|     // update obj in sub dlg
 | ||||
|     if (m_ams_setting_dlg) { | ||||
|         m_ams_setting_dlg->obj = obj; | ||||
| 
 | ||||
|         if (obj && m_ams_setting_dlg->IsShown()) { | ||||
|             m_ams_setting_dlg->update_insert_material_read_mode(obj->ams_insert_flag); | ||||
|             m_ams_setting_dlg->update_starting_read_mode(obj->ams_power_on_flag); | ||||
|  | @ -2445,6 +2446,7 @@ void StatusPanel::on_ams_setting_click(SimpleEvent &event) | |||
|         try { | ||||
|             int ams_id_int            = atoi(ams_id.c_str()); | ||||
|             m_ams_setting_dlg->ams_id = ams_id_int; | ||||
|             m_ams_setting_dlg->ams_support_remain = obj->ams_support_remain; | ||||
|             m_ams_setting_dlg->Show(); | ||||
|         } catch (...) { | ||||
|             ; | ||||
|  |  | |||
|  | @ -4,9 +4,13 @@ | |||
| 
 | ||||
| #include <wx/webviewarchivehandler.h> | ||||
| #include <wx/webviewfshandler.h> | ||||
| #if wxUSE_WEBVIEW_EDGE | ||||
| #include <wx/msw/webview_edge.h> | ||||
| #endif | ||||
| #include <wx/uri.h> | ||||
| #if defined(__WIN32__) || defined(__WXMAC__) | ||||
| #include "wx/private/jsscriptwrapper.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __WIN32__ | ||||
| #include "../WebView2.h" | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ | |||
| 
 | ||||
| #include <cstdint> // uint8_t | ||||
| #include <ctype.h> // ::tolower, ::toupper | ||||
| #include <cwctype> // ::towlower | ||||
| #include <cstring> // memcpy | ||||
| 
 | ||||
| #include <cstdio> | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <boost/format.hpp> | ||||
| #include <boost/algorithm/string.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/filesystem/string_file.hpp> | ||||
| #include <boost/filesystem/fstream.hpp> | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 SoftFever
						SoftFever