mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into ys_manipulation_panel_rw
This commit is contained in:
		
						commit
						efb9ef37f6
					
				
					 36 changed files with 170 additions and 174 deletions
				
			
		|  | @ -89,33 +89,34 @@ struct stl_neighbors { | |||
| }; | ||||
| 
 | ||||
| struct stl_stats { | ||||
| 	stl_stats() { this->reset(); } | ||||
| 	void reset() { memset(this, 0, sizeof(stl_stats)); this->volume = -1.0; } | ||||
| 	char          header[81]; | ||||
| 	stl_type      type; | ||||
| 	uint32_t      number_of_facets; | ||||
| 	stl_vertex    max; | ||||
| 	stl_vertex    min; | ||||
| 	stl_vertex    size; | ||||
| 	float         bounding_diameter; | ||||
| 	float         shortest_edge; | ||||
| 	float         volume; | ||||
| 	int           connected_edges; | ||||
| 	int           connected_facets_1_edge; | ||||
| 	int           connected_facets_2_edge; | ||||
| 	int           connected_facets_3_edge; | ||||
| 	int           facets_w_1_bad_edge; | ||||
| 	int           facets_w_2_bad_edge; | ||||
| 	int           facets_w_3_bad_edge; | ||||
| 	int           original_num_facets; | ||||
| 	int           edges_fixed; | ||||
| 	int           degenerate_facets; | ||||
| 	int           facets_removed; | ||||
| 	int           facets_added; | ||||
| 	int           facets_reversed; | ||||
| 	int           backwards_edges; | ||||
| 	int           normals_fixed; | ||||
| 	int           number_of_parts; | ||||
|     stl_stats() { memset(&header, 0, 81); } | ||||
|     char          header[81]                = ""; | ||||
|     stl_type      type                      = (stl_type)0; | ||||
|     uint32_t      number_of_facets          = 0; | ||||
|     stl_vertex    max                       = stl_vertex::Zero(); | ||||
|     stl_vertex    min                       = stl_vertex::Zero(); | ||||
|     stl_vertex    size                      = stl_vertex::Zero(); | ||||
|     float         bounding_diameter         = 0.f; | ||||
|     float         shortest_edge             = 0.f; | ||||
|     float         volume                    = -1.f; | ||||
|     int           connected_edges           = 0; | ||||
|     int           connected_facets_1_edge   = 0; | ||||
|     int           connected_facets_2_edge   = 0; | ||||
|     int           connected_facets_3_edge   = 0; | ||||
|     int           facets_w_1_bad_edge       = 0; | ||||
|     int           facets_w_2_bad_edge       = 0; | ||||
|     int           facets_w_3_bad_edge       = 0; | ||||
|     int           original_num_facets       = 0; | ||||
|     int           edges_fixed               = 0; | ||||
|     int           degenerate_facets         = 0; | ||||
|     int           facets_removed            = 0; | ||||
|     int           facets_added              = 0; | ||||
|     int           facets_reversed           = 0; | ||||
|     int           backwards_edges           = 0; | ||||
|     int           normals_fixed             = 0; | ||||
|     int           number_of_parts           = 0; | ||||
| 
 | ||||
|     void clear() { *this = stl_stats(); } | ||||
| }; | ||||
| 
 | ||||
| struct stl_file { | ||||
|  | @ -124,7 +125,7 @@ struct stl_file { | |||
| 	void clear() { | ||||
| 		this->facet_start.clear(); | ||||
| 		this->neighbors_start.clear(); | ||||
| 		this->stats.reset(); | ||||
|         this->stats.clear(); | ||||
| 	} | ||||
| 
 | ||||
| 	size_t memsize() const { | ||||
|  |  | |||
|  | @ -36,6 +36,10 @@ | |||
| #error "SEEK_SET not defined" | ||||
| #endif | ||||
| 
 | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
| extern void stl_internal_reverse_quads(char *buf, size_t cnt); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
| 
 | ||||
| static FILE* stl_open_count_facets(stl_file *stl, const char *file)  | ||||
| { | ||||
|   	// Open the file in binary mode first.
 | ||||
|  | @ -238,10 +242,6 @@ bool stl_open(stl_file *stl, const char *file) | |||
|   	return result; | ||||
| } | ||||
| 
 | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
| extern void stl_internal_reverse_quads(char *buf, size_t cnt); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
| 
 | ||||
| void stl_allocate(stl_file *stl)  | ||||
| { | ||||
|   	//  Allocate memory for the entire .STL file.
 | ||||
|  |  | |||
|  | @ -15,4 +15,4 @@ | |||
| #undef clipper_hpp | ||||
| #undef use_xyz | ||||
| 
 | ||||
| #endif clipper_z_hpp | ||||
| #endif // clipper_z_hpp
 | ||||
|  |  | |||
|  | @ -249,7 +249,7 @@ ConfigOption* ConfigOptionDef::create_default_option() const | |||
|             // Special case: For a DynamicConfig, convert a templated enum to a generic enum.
 | ||||
|             new ConfigOptionEnumGeneric(this->enum_keys_map, this->default_value->getInt()) : | ||||
|             this->default_value->clone(); | ||||
| 	return this->create_empty_option(); | ||||
|     return this->create_empty_option(); | ||||
| } | ||||
| 
 | ||||
| // Assignment of the serialization IDs is not thread safe. The Defs shall be initialized from the main thread!
 | ||||
|  |  | |||
|  | @ -353,7 +353,7 @@ public: | |||
|     bool apply_override(const ConfigOption *rhs) override { | ||||
|         if (this->nullable()) | ||||
|         	throw std::runtime_error("Cannot override a nullable ConfigOption."); | ||||
| 		if (rhs->type() != this->type()) | ||||
|         if (rhs->type() != this->type()) | ||||
| 			throw std::runtime_error("ConfigOptionVector.apply_override() applied to different types."); | ||||
| 		auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs); | ||||
| 		if (! rhs->nullable()) { | ||||
|  | @ -461,7 +461,7 @@ public: | |||
|         for (const double &v : this->values) { | ||||
|             if (&v != &this->values.front()) | ||||
|             	ss << ","; | ||||
|         	serialize_single_value(ss, v); | ||||
|             serialize_single_value(ss, v); | ||||
|         } | ||||
|         return ss.str(); | ||||
|     } | ||||
|  | @ -607,7 +607,7 @@ public: | |||
|         for (const int &v : this->values) { | ||||
|             if (&v != &this->values.front()) | ||||
|             	ss << ","; | ||||
|         	serialize_single_value(ss, v); | ||||
|             serialize_single_value(ss, v); | ||||
|         } | ||||
|         return ss.str(); | ||||
|     } | ||||
|  |  | |||
|  | @ -15,40 +15,39 @@ namespace Slic3r { | |||
| 
 | ||||
| struct SurfaceFillParams | ||||
| { | ||||
| 	SurfaceFillParams() : flow(0.f, 0.f, 0.f, false) { memset(this, 0, sizeof(*this)); } | ||||
| 	// Zero based extruder ID.
 | ||||
| 	unsigned int 	extruder; | ||||
|     unsigned int 	extruder = 0; | ||||
| 	// Infill pattern, adjusted for the density etc.
 | ||||
| 	InfillPattern  	pattern; | ||||
|     InfillPattern  	pattern = InfillPattern(0); | ||||
| 
 | ||||
|     // FillBase
 | ||||
|     // in unscaled coordinates
 | ||||
|     coordf_t    	spacing; | ||||
|     coordf_t    	spacing = 0.; | ||||
|     // infill / perimeter overlap, in unscaled coordinates
 | ||||
|     coordf_t    	overlap; | ||||
|     coordf_t    	overlap = 0.; | ||||
|     // Angle as provided by the region config, in radians.
 | ||||
|     float       	angle; | ||||
|     float       	angle = 0.f; | ||||
|     // Non-negative for a bridge.
 | ||||
|     float 			bridge_angle; | ||||
|     float 			bridge_angle = 0.f; | ||||
| 
 | ||||
|     // FillParams
 | ||||
|     float       	density; | ||||
|     float       	density = 0.f; | ||||
|     // Don't connect the fill lines around the inner perimeter.
 | ||||
|     bool        	dont_connect; | ||||
|     bool        	dont_connect = false; | ||||
|     // Don't adjust spacing to fill the space evenly.
 | ||||
|     bool        	dont_adjust; | ||||
|     bool        	dont_adjust = false; | ||||
| 
 | ||||
|     // width, height of extrusion, nozzle diameter, is bridge
 | ||||
|     // For the output, for fill generator.
 | ||||
| 	Flow 			flow; | ||||
|     Flow 			flow = Flow(0.f, 0.f, 0.f, false); | ||||
| 
 | ||||
| 	// For the output
 | ||||
| 	ExtrusionRole	extrusion_role; | ||||
|     ExtrusionRole	extrusion_role = ExtrusionRole(0); | ||||
| 
 | ||||
| 	// Various print settings?
 | ||||
| 
 | ||||
| 	// Index of this entry in a linear vector.
 | ||||
| 	size_t 			idx; | ||||
|     size_t 			idx = 0; | ||||
| 
 | ||||
| 
 | ||||
| 	bool operator<(const SurfaceFillParams &rhs) const { | ||||
|  |  | |||
|  | @ -979,7 +979,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) | |||
|             stream << layer_height_profile.front(); | ||||
|             for (size_t i = 1; i < layer_height_profile.size(); ++i) | ||||
|                 stream << ";" << layer_height_profile[i]; | ||||
|                 stream << "\n    </metadata>\n"; | ||||
|             stream << "\n    </metadata>\n"; | ||||
|         } | ||||
| 
 | ||||
|         // Export layer height ranges including the layer range specific config overrides.
 | ||||
|  |  | |||
|  | @ -246,7 +246,7 @@ static void extract_model_from_archive( | |||
|                 sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { | ||||
|                 // Normal was mangled. Maybe denormals or "not a number" were stored?
 | ||||
|                 // Just reset the normal and silently ignore it.
 | ||||
|                 memset(&facet.normal, 0, sizeof(facet.normal)); | ||||
|                 facet.normal = stl_normal::Zero(); | ||||
|             } | ||||
|             facets.emplace_back(facet); | ||||
|         } | ||||
|  | @ -278,7 +278,7 @@ static void extract_model_from_archive( | |||
|         instance->set_rotation(instance_rotation); | ||||
|         instance->set_scaling_factor(instance_scaling_factor); | ||||
|         instance->set_offset(instance_offset); | ||||
|         if (group_id != (size_t)-1) | ||||
|         if (group_id != (unsigned int)(-1)) | ||||
|             group_to_model_object[group_id] = model_object; | ||||
|     } else { | ||||
|         // This is not the 1st mesh of a group. Add it to the ModelObject.
 | ||||
|  |  | |||
|  | @ -659,7 +659,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ | |||
|     if (print->is_step_done(psGCodeExport) && boost::filesystem::exists(boost::filesystem::path(path))) | ||||
|         return; | ||||
| 
 | ||||
| 	print->set_started(psGCodeExport); | ||||
|     print->set_started(psGCodeExport); | ||||
| 
 | ||||
|     BOOST_LOG_TRIVIAL(info) << "Exporting G-code..." << log_memory_info(); | ||||
| 
 | ||||
|  | @ -1415,7 +1415,7 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc | |||
|         // Skip the rest of the line.
 | ||||
|         for (; *ptr != 0 && *ptr != '\r' && *ptr != '\n'; ++ ptr); | ||||
| 		// Skip the end of line indicators.
 | ||||
| 		for (; *ptr == '\r' || *ptr == '\n'; ++ ptr); | ||||
|         for (; *ptr == '\r' || *ptr == '\n'; ++ ptr); | ||||
| 	} | ||||
|     return temp_set_by_gcode; | ||||
| } | ||||
|  |  | |||
|  | @ -308,7 +308,7 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ | |||
|                     LayerTools lt_new(0.5f * (lt.print_z + lt_object.print_z)); | ||||
|                     // Find the 1st layer above lt_new.
 | ||||
|                     for (j = i + 1; j < m_layer_tools.size() && m_layer_tools[j].print_z < lt_new.print_z - EPSILON; ++ j); | ||||
| 					if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) { | ||||
|                     if (std::abs(m_layer_tools[j].print_z - lt_new.print_z) < EPSILON) { | ||||
| 						m_layer_tools[j].has_wipe_tower = true; | ||||
| 					} else { | ||||
| 						LayerTools <_extra = *m_layer_tools.insert(m_layer_tools.begin() + j, lt_new); | ||||
|  |  | |||
|  | @ -698,7 +698,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool last_in_lay | |||
|         writer.append(std::string("; material : " + (m_current_tool < m_filpar.size() ? m_filpar[m_current_tool].material : "(NONE)") + " -> " + m_filpar[tool].material + "\n").c_str()) | ||||
|               .append(";--------------------\n"); | ||||
| 
 | ||||
| 	writer.speed_override_backup(); | ||||
|     writer.speed_override_backup(); | ||||
| 	writer.speed_override(100); | ||||
| 
 | ||||
| 	Vec2f initial_position = cleaning_box.ld + Vec2f(0.f, m_depth_traversed); | ||||
|  | @ -748,7 +748,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool last_in_lay | |||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|         m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	ToolChangeResult result; | ||||
|     ToolChangeResult result; | ||||
|     result.priming      = false; | ||||
|     result.initial_tool = int(old_tool); | ||||
|     result.new_tool     = int(m_current_tool); | ||||
|  | @ -806,7 +806,7 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of | |||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|     	m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	ToolChangeResult result; | ||||
|     ToolChangeResult result; | ||||
|     result.priming      = false; | ||||
|     result.initial_tool = int(old_tool); | ||||
|     result.new_tool     = int(m_current_tool); | ||||
|  | @ -1163,7 +1163,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer() | |||
|                 writer.extrude(box.rd.x() - m_perimeter_width / 2.f, writer.y() + 0.5f * step); | ||||
|                 writer.extrude(box.ld.x() + m_perimeter_width / 2.f, writer.y()); | ||||
|             } | ||||
|             writer.travel(box.rd.x()-m_perimeter_width/2.f,writer.y()); // wipe the nozzle
 | ||||
|         writer.travel(box.rd.x()-m_perimeter_width/2.f,writer.y()); // wipe the nozzle
 | ||||
|     } | ||||
|     else {  // Extrude a sparse infill to support the material to be printed above.
 | ||||
|         const float dy = (fill_box.lu.y() - fill_box.ld.y() - m_perimeter_width); | ||||
|  | @ -1196,7 +1196,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer() | |||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|         m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	ToolChangeResult result; | ||||
|     ToolChangeResult result; | ||||
|     result.priming      = false; | ||||
|     result.initial_tool = int(old_tool); | ||||
|     result.new_tool     = int(m_current_tool); | ||||
|  |  | |||
|  | @ -144,7 +144,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly | |||
|             } | ||||
|             if (! lower_layer_covered->empty()) | ||||
|             	voids = diff(voids, *lower_layer_covered); | ||||
|         	fill_boundaries = diff(fill_boundaries, voids); | ||||
|             fill_boundaries = diff(fill_boundaries, voids); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -473,4 +473,4 @@ void LayerRegion::export_region_fill_surfaces_to_svg_debug(const char *name) con | |||
| } | ||||
| 
 | ||||
| } | ||||
|   | ||||
|   | ||||
|  |  | |||
|  | @ -1462,7 +1462,7 @@ stl_stats ModelObject::get_object_stl_stats() const | |||
|         return this->volumes[0]->mesh().stl.stats; | ||||
| 
 | ||||
|     stl_stats full_stats; | ||||
|     memset(&full_stats, 0, sizeof(stl_stats)); | ||||
|     full_stats.volume = 0.f; | ||||
| 
 | ||||
|     // fill full_stats from all objet's meshes
 | ||||
|     for (ModelVolume* volume : this->volumes) | ||||
|  |  | |||
|  | @ -252,7 +252,7 @@ bool Print::is_step_done(PrintObjectStep step) const | |||
| { | ||||
|     if (m_objects.empty()) | ||||
|         return false; | ||||
| 	tbb::mutex::scoped_lock lock(this->state_mutex()); | ||||
|     tbb::mutex::scoped_lock lock(this->state_mutex()); | ||||
|     for (const PrintObject *object : m_objects) | ||||
|         if (! object->is_step_done_unguarded(step)) | ||||
|             return false; | ||||
|  |  | |||
|  | @ -1480,7 +1480,7 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full | |||
| 
 | ||||
|     if (object_max_z <= 0.f) | ||||
|         object_max_z = (float)model_object.raw_bounding_box().size().z(); | ||||
| 	return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); | ||||
|     return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); | ||||
| } | ||||
| 
 | ||||
| // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
 | ||||
|  |  | |||
|  | @ -783,7 +783,7 @@ namespace SupportMaterialInternal { | |||
|         for (const ExtrusionPath &ep : loop.paths) | ||||
|             if (ep.role() == erOverhangPerimeter && ! ep.polyline.empty()) | ||||
|                 return ep.size() >= (ep.is_closed() ? 3 : 2); | ||||
|             return false; | ||||
|         return false; | ||||
|     } | ||||
|     static bool has_bridging_perimeters(const ExtrusionEntityCollection &perimeters) | ||||
|     { | ||||
|  | @ -2125,7 +2125,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( | |||
|                 } | ||||
|                 // $layer->slices contains the full shape of layer, thus including
 | ||||
|                 // perimeter's width. $support contains the full shape of support
 | ||||
|                 // material, thus including the width of its foremost extrusion.
 | ||||
|                 // material, thus including the width of its foremost extrusion.
 | ||||
|                 // We leave a gap equal to a full extrusion width.
 | ||||
|                 support_layer.polygons = diff(support_layer.polygons, polygons_trimming); | ||||
|             } | ||||
|  | @ -2934,20 +2934,13 @@ void PrintObjectSupportMaterial::generate_toolpaths( | |||
|     // Prepare fillers.
 | ||||
|     SupportMaterialPattern  support_pattern = m_object_config->support_material_pattern; | ||||
|     bool                    with_sheath     = m_object_config->support_material_with_sheath; | ||||
|     InfillPattern           infill_pattern; | ||||
|     InfillPattern           infill_pattern = (support_pattern == smpHoneycomb ? ipHoneycomb : ipRectilinear); | ||||
|     std::vector<float>      angles; | ||||
|     angles.push_back(base_angle); | ||||
|     switch (support_pattern) { | ||||
|     case smpRectilinearGrid: | ||||
| 
 | ||||
|     if (support_pattern == smpRectilinearGrid) | ||||
|         angles.push_back(interface_angle); | ||||
|         // fall through
 | ||||
|     case smpRectilinear: | ||||
|         infill_pattern = ipRectilinear; | ||||
|         break; | ||||
|     case smpHoneycomb: | ||||
|         infill_pattern = ipHoneycomb; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     BoundingBox bbox_object(Point(-scale_(1.), -scale_(1.0)), Point(scale_(1.), scale_(1.))); | ||||
| 
 | ||||
| //    const coordf_t link_max_length_factor = 3.;
 | ||||
|  | @ -3217,7 +3210,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( | |||
|                     density = 0.5f; | ||||
|                     flow = m_first_layer_flow; | ||||
|                     // use the proper spacing for first layer as we don't need to align
 | ||||
|                     // its pattern to the other layers
 | ||||
|                     // its pattern to the other layers
 | ||||
|                     //FIXME When paralellizing, each thread shall have its own copy of the fillers.
 | ||||
|                     filler->spacing = flow.spacing(); | ||||
|                     filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density)); | ||||
|  |  | |||
|  | @ -342,7 +342,7 @@ static void copy_config_dir_single_level(const boost::filesystem::path &path_src | |||
|         ! boost::filesystem::create_directory(path_dst)) | ||||
|         throw std::runtime_error(std::string("Slic3r was unable to create a directory at ") + path_dst.string()); | ||||
| 
 | ||||
| 	for (auto &dir_entry : boost::filesystem::directory_iterator(path_src)) | ||||
|     for (auto &dir_entry : boost::filesystem::directory_iterator(path_src)) | ||||
|         if (Slic3r::is_ini_file(dir_entry)) | ||||
| 		    boost::filesystem::copy_file(dir_entry.path(), path_dst / dir_entry.path().filename(), boost::filesystem::copy_option::overwrite_if_exists); | ||||
| } | ||||
|  | @ -351,7 +351,7 @@ static void delete_existing_ini_files(const boost::filesystem::path &path) | |||
| { | ||||
|     if (! boost::filesystem::is_directory(path)) | ||||
|     	return; | ||||
| 	for (auto &dir_entry : boost::filesystem::directory_iterator(path)) | ||||
|     for (auto &dir_entry : boost::filesystem::directory_iterator(path)) | ||||
|         if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) | ||||
| 		    boost::filesystem::remove(dir_entry.path()); | ||||
| } | ||||
|  | @ -378,7 +378,7 @@ const Snapshot&	SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot: | |||
|         sprintf(name, "filament_%u", i); | ||||
|         if (! app_config.has("presets", name)) | ||||
|             break; | ||||
| 	    snapshot.filaments.emplace_back(app_config.get("presets", name)); | ||||
|         snapshot.filaments.emplace_back(app_config.get("presets", name)); | ||||
|     } | ||||
|     // Vendor specific config bundles and installed printers.
 | ||||
|     for (const std::pair<std::string, std::map<std::string, std::set<std::string>>> &vendor : app_config.vendors()) { | ||||
|  | @ -417,7 +417,7 @@ const Snapshot&	SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot: | |||
|     // Backup the presets.
 | ||||
|     for (const char *subdir : { "print", "filament", "printer", "vendor" }) | ||||
|     	copy_config_dir_single_level(data_dir / subdir, snapshot_dir / subdir); | ||||
| 	snapshot.save_ini((snapshot_dir / "snapshot.ini").string()); | ||||
|     snapshot.save_ini((snapshot_dir / "snapshot.ini").string()); | ||||
|     assert(m_snapshots.empty() || m_snapshots.back().time_captured <= snapshot.time_captured); | ||||
|     m_snapshots.emplace_back(std::move(snapshot)); | ||||
|     return m_snapshots.back(); | ||||
|  |  | |||
|  | @ -227,9 +227,9 @@ size_t Index::load(const boost::filesystem::path &path) | |||
| 				// End of semver or keyword.
 | ||||
| 				break; | ||||
|     	} | ||||
|     	if (*key_end != 0 && *key_end != ' ' && *key_end != '\t' && *key_end != '=') | ||||
|         if (*key_end != 0 && *key_end != ' ' && *key_end != '\t' && *key_end != '=') | ||||
|     		throw file_parser_error("Invalid keyword or semantic version", path, idx_line); | ||||
| 		char *value = left_trim(key_end); | ||||
|         char *value = left_trim(key_end); | ||||
| 		bool  key_value_pair = *value == '='; | ||||
| 		if (key_value_pair) | ||||
| 			value = left_trim(value + 1); | ||||
|  | @ -245,11 +245,11 @@ size_t Index::load(const boost::filesystem::path &path) | |||
|     		if (strcmp(key, "min_slic3r_version") == 0 || strcmp(key, "max_slic3r_version") == 0) { | ||||
|     			if (! svalue.empty()) | ||||
| 					semver = Semver::parse(svalue); | ||||
| 		    	if (! semver) | ||||
|                 if (! semver) | ||||
| 		    		throw file_parser_error(std::string(key) + " must referece a valid semantic version", path, idx_line); | ||||
| 				if (strcmp(key, "min_slic3r_version") == 0) | ||||
|                 if (strcmp(key, "min_slic3r_version") == 0) | ||||
|     				ver.min_slic3r_version = *semver; | ||||
|     			else | ||||
|                 else | ||||
|     				ver.max_slic3r_version = *semver; | ||||
|     		} else { | ||||
|     			// Ignore unknown keys, as there may come new keys in the future.
 | ||||
|  |  | |||
|  | @ -455,7 +455,7 @@ void BedShapePanel::update_shape() | |||
|     else if (page_idx == SHAPE_CUSTOM)  | ||||
|         m_shape = m_loaded_shape; | ||||
| 
 | ||||
| 	update_preview(); | ||||
|     update_preview(); | ||||
| } | ||||
| 
 | ||||
| // Loads an stl file, projects it to the XY plane and calculates a polygon.
 | ||||
|  |  | |||
|  | @ -1225,13 +1225,16 @@ bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater | |||
| 
 | ||||
| const wxString& ConfigWizard::name(const bool from_menu/* = false*/) | ||||
| { | ||||
|     // A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
 | ||||
|     // A different naming convention is used for the Wizard on Windows & GTK vs. OSX.
 | ||||
|     // Note: Don't call _() macro here.
 | ||||
|     //       This function just return the current name according to the OS.
 | ||||
|     //       Translation is implemented inside GUI_App::add_config_menu()
 | ||||
| #if __APPLE__ | ||||
|     static const wxString config_wizard_name =  _(L("Configuration Assistant")); | ||||
|     static const wxString config_wizard_name_menu = _(L("Configuration &Assistant")); | ||||
|     static const wxString config_wizard_name =  L("Configuration Assistant"); | ||||
|     static const wxString config_wizard_name_menu = L("Configuration &Assistant"); | ||||
| #else | ||||
|     static const wxString config_wizard_name = _(L("Configuration Wizard")); | ||||
|     static const wxString config_wizard_name_menu = _(L("Configuration &Wizard")); | ||||
|     static const wxString config_wizard_name = L("Configuration Wizard"); | ||||
|     static const wxString config_wizard_name_menu = L("Configuration &Wizard"); | ||||
| #endif | ||||
|     return from_menu ? config_wizard_name_menu : config_wizard_name; | ||||
| } | ||||
|  |  | |||
|  | @ -928,8 +928,8 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c | |||
|     if (items_count > 1) | ||||
|         m_original_height += (items_count - 1) * scaled_square_contour; | ||||
| 
 | ||||
| 	m_width = (int)next_highest_power_of_2((uint32_t)m_original_width); | ||||
| 	m_height = (int)next_highest_power_of_2((uint32_t)m_original_height); | ||||
|     m_width = (int)next_highest_power_of_2((uint32_t)m_original_width); | ||||
|     m_height = (int)next_highest_power_of_2((uint32_t)m_original_height); | ||||
| 
 | ||||
|     // generates bitmap
 | ||||
|     wxBitmap bitmap(m_width, m_height); | ||||
|  | @ -1882,7 +1882,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|     if (m_reload_delayed) | ||||
|         return; | ||||
| 
 | ||||
| 	bool update_object_list = false; | ||||
|     bool update_object_list = false; | ||||
| 
 | ||||
|     if (m_volumes.volumes != glvolumes_new) | ||||
| 		update_object_list = true; | ||||
|  | @ -5070,14 +5070,14 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat | |||
| 		    for (const GCodePreviewData::Extrusion::Layer &layer : preview_data.extrusion.layers) | ||||
| 		        for (const ExtrusionPath &path : layer.paths) | ||||
| 		        	++ num_paths_per_role[size_t(path.role())]; | ||||
| 			std::vector<std::vector<float>> roles_values; | ||||
|             std::vector<std::vector<float>> roles_values; | ||||
| 			roles_values.assign(size_t(erCount), std::vector<float>()); | ||||
| 		    for (size_t i = 0; i < roles_values.size(); ++ i) | ||||
| 		    	roles_values[i].reserve(num_paths_per_role[i]); | ||||
| 		    for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers) | ||||
|             for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers) | ||||
| 		        for (const ExtrusionPath& path : layer.paths) | ||||
| 		        	roles_values[size_t(path.role())].emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path)); | ||||
| 			roles_filters.reserve(size_t(erCount)); | ||||
|             roles_filters.reserve(size_t(erCount)); | ||||
| 			size_t num_buffers = 0; | ||||
| 		    for (std::vector<float> &values : roles_values) { | ||||
| 		    	sort_remove_duplicates(values); | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ void config_wizard(int reason) | |||
|     if (! wxGetApp().check_unsaved_changes()) | ||||
|     	return; | ||||
| 
 | ||||
| 	try { | ||||
|     try { | ||||
| 		ConfigWizard wizard(nullptr, static_cast<ConfigWizard::RunReason>(reason)); | ||||
|         wizard.run(wxGetApp().preset_bundle, wxGetApp().preset_updater); | ||||
| 	} | ||||
|  |  | |||
|  | @ -725,7 +725,7 @@ bool GUI_App::load_language(wxString language, bool initial) | |||
| #endif | ||||
|         if (initial) | ||||
|         	message + "\n\nApplication will close."; | ||||
| 		wxMessageBox(message, "PrusaSlicer - Switching language failed", wxOK | wxICON_ERROR); | ||||
|         wxMessageBox(message, "PrusaSlicer - Switching language failed", wxOK | wxICON_ERROR); | ||||
|         if (initial) | ||||
| 			std::exit(EXIT_FAILURE); | ||||
| 		else | ||||
|  |  | |||
|  | @ -753,9 +753,9 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol | |||
|     } | ||||
| 
 | ||||
|     select_items(items); | ||||
| #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
| //#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
|     selection_changed(); | ||||
| #endif //no __WXOSX__ //__WXMSW__
 | ||||
| //#endif //no __WXOSX__ //__WXMSW__
 | ||||
| } | ||||
| 
 | ||||
| void ObjectList::paste_objects_into_list(const std::vector<size_t>& object_idxs) | ||||
|  | @ -773,9 +773,9 @@ void ObjectList::paste_objects_into_list(const std::vector<size_t>& object_idxs) | |||
|     wxGetApp().plater()->changed_objects(object_idxs); | ||||
| 
 | ||||
|     select_items(items); | ||||
| #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
| //#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
|     selection_changed(); | ||||
| #endif //no __WXOSX__ //__WXMSW__
 | ||||
| //#endif //no __WXOSX__ //__WXMSW__
 | ||||
| } | ||||
| 
 | ||||
| #ifdef __WXOSX__ | ||||
|  | @ -815,7 +815,9 @@ void ObjectList::list_manipulation(bool evt_context_menu/* = false*/) | |||
|         if (col == nullptr) { | ||||
|             if (wxOSX) | ||||
|                 UnselectAll(); | ||||
|             else | ||||
|             else if (!evt_context_menu)  | ||||
|                 // Case, when last item was deleted and under GTK was called wxEVT_DATAVIEW_SELECTION_CHANGED,
 | ||||
|                 // which invoked next list_manipulation(false)
 | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|  | @ -1720,9 +1722,9 @@ void ObjectList::load_subobject(ModelVolumeType type) | |||
|     if (sel_item) | ||||
|         select_item(sel_item); | ||||
| 
 | ||||
| #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
| //#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
|     selection_changed(); | ||||
| #endif //no __WXOSX__ //__WXMSW__
 | ||||
| //#endif //no __WXOSX__ //__WXMSW__
 | ||||
| } | ||||
| 
 | ||||
| void ObjectList::load_part( ModelObject* model_object, | ||||
|  | @ -1858,9 +1860,9 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode | |||
|     const auto object_item = m_objects_model->GetTopParent(GetSelection()); | ||||
|     select_item(m_objects_model->AddVolumeChild(object_item, name, type,  | ||||
|         new_volume->get_mesh_errors_count()>0)); | ||||
| #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
| //#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||
|     selection_changed(); | ||||
| #endif //no __WXOSX__ //__WXMSW__
 | ||||
| //#endif //no __WXOSX__ //__WXMSW__
 | ||||
| } | ||||
| 
 | ||||
| void ObjectList::load_shape_object(const std::string& type_name) | ||||
|  | @ -1899,6 +1901,9 @@ void ObjectList::load_shape_object(const std::string& type_name) | |||
|     new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); | ||||
|     new_object->invalidate_bounding_box(); | ||||
| 
 | ||||
|     new_object->center_around_origin(); | ||||
|     new_object->ensure_on_bed(); | ||||
| 
 | ||||
|     const BoundingBoxf bed_shape = wxGetApp().plater()->bed_shape_bb(); | ||||
|     new_object->instances[0]->set_offset(Slic3r::to_3d(bed_shape.center().cast<double>(), -new_object->origin_translation(2))); | ||||
| 
 | ||||
|  |  | |||
|  | @ -252,7 +252,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) | |||
|         const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; | ||||
|         const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false; | ||||
| 
 | ||||
|         if (is_point_clipped(support_point.pos.cast<double>())) | ||||
|         if (is_mesh_point_clipped(support_point.pos.cast<double>())) | ||||
|             continue; | ||||
| 
 | ||||
|         // First decide about the color of the point.
 | ||||
|  | @ -335,14 +335,14 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| bool GLGizmoSlaSupports::is_point_clipped(const Vec3d& point) const | ||||
| bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const | ||||
| { | ||||
|     if (m_clipping_plane_distance == 0.f) | ||||
|         return false; | ||||
| 
 | ||||
|     Vec3d transformed_point = m_model_object->instances.front()->get_transformation().get_matrix() * point; | ||||
|     transformed_point(2) += m_z_shift; | ||||
|     return m_clipping_plane->distance(transformed_point) < 0.; | ||||
|     return m_clipping_plane->is_point_clipped(transformed_point); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -391,27 +391,15 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec | |||
|     trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift)); | ||||
| 
 | ||||
|     // The raycaster query
 | ||||
|     std::vector<Vec3f> hits; | ||||
|     std::vector<Vec3f> normals; | ||||
|     m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, &hits, &normals); | ||||
| 
 | ||||
|     // We must also take care of the clipping plane (if active)
 | ||||
|     unsigned i = 0; | ||||
|     if (m_clipping_plane_distance != 0.f) { | ||||
|         for (i=0; i<hits.size(); ++i) | ||||
|             if (! is_point_clipped(hits[i].cast<double>())) | ||||
|                 break; | ||||
|     Vec3f hit; | ||||
|     Vec3f normal; | ||||
|     if (m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) { | ||||
|         // Return both the point and the facet normal.
 | ||||
|         pos_and_normal = std::make_pair(hit, normal); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     if (i==hits.size() || (hits.size()-i) % 2 != 0) { | ||||
|         // All hits are either clipped, or there is an odd number of unclipped
 | ||||
|         // hits - meaning the nearest must be from inside the mesh.
 | ||||
|     else | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // Calculate and return both the point and the facet normal.
 | ||||
|     pos_and_normal = std::make_pair(hits[i], normals[i]); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| // Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
 | ||||
|  | @ -481,19 +469,15 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous | |||
|             std::vector<Vec3f> points_inside; | ||||
|             std::vector<unsigned int> points_idxs = m_selection_rectangle.stop_dragging(m_parent, points); | ||||
|             for (size_t idx : points_idxs) | ||||
|                 points_inside.push_back((trafo.get_matrix() * points[idx]).cast<float>()); | ||||
|                 points_inside.push_back(points[idx].cast<float>()); | ||||
| 
 | ||||
|             // Only select/deselect points that are actually visible
 | ||||
|             for (size_t idx :  m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, | ||||
|                           [this](const Vec3f& pt) { return is_point_clipped(pt.cast<double>()); })) | ||||
|             for (size_t idx :  m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get())) | ||||
|             { | ||||
|                 const sla::SupportPoint &support_point = m_editing_cache[points_idxs[idx]].support_point; | ||||
|                 if (! is_point_clipped(support_point.pos.cast<double>())) { | ||||
|                     if (rectangle_status == GLSelectionRectangle::Deselect) | ||||
|                         unselect_point(points_idxs[idx]); | ||||
|                     else | ||||
|                         select_point(points_idxs[idx]); | ||||
|                 } | ||||
|                 if (rectangle_status == GLSelectionRectangle::Deselect) | ||||
|                     unselect_point(points_idxs[idx]); | ||||
|                 else | ||||
|                     select_point(points_idxs[idx]); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ private: | |||
|     mutable std::unique_ptr<MeshClipper> m_supports_clipper; | ||||
| 
 | ||||
|     std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const; | ||||
|     bool is_point_clipped(const Vec3d& point) const; | ||||
|     bool is_mesh_point_clipped(const Vec3d& point) const; | ||||
|     //void find_intersecting_facets(const igl::AABB<Eigen::MatrixXf, 3>* aabb, const Vec3f& normal, double offset, std::vector<unsigned int>& out) const;
 | ||||
| 
 | ||||
|     // Methods that do the model_object and editing cache synchronization,
 | ||||
|  |  | |||
|  | @ -192,7 +192,7 @@ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wx | |||
|     else | ||||
|         panel->SetSizer(optgroup->sizer); | ||||
| 
 | ||||
| 	return optgroup; | ||||
|     return optgroup; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -917,7 +917,7 @@ void MainFrame::load_config_file() | |||
| 	wxString file; | ||||
|     if (dlg.ShowModal() == wxID_OK) | ||||
|         file = dlg.GetPath(); | ||||
| 	if (! file.IsEmpty() && this->load_config_file(file.ToUTF8().data())) { | ||||
|     if (! file.IsEmpty() && this->load_config_file(file.ToUTF8().data())) { | ||||
|         wxGetApp().app_config->update_config_dir(get_dir_name(file)); | ||||
|         m_last_config = file; | ||||
|     } | ||||
|  |  | |||
|  | @ -152,8 +152,8 @@ Vec3f MeshRaycaster::AABBWrapper::get_hit_normal(const igl::Hit& hit) const | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, | ||||
|                                       const Camera& camera, std::vector<Vec3f>* positions, std::vector<Vec3f>* normals) const | ||||
| bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, | ||||
|                                       Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane) const | ||||
| { | ||||
|     const std::array<int, 4>& viewport = camera.get_viewport(); | ||||
|     const Transform3d& model_mat = camera.get_view_matrix(); | ||||
|  | @ -179,25 +179,30 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& | |||
| 
 | ||||
|     std::sort(hits.begin(), hits.end(), [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; }); | ||||
| 
 | ||||
|     // Now stuff the points in the provided vector and calculate normals if asked about them:
 | ||||
|     if (positions != nullptr) { | ||||
|         positions->clear(); | ||||
|         if (normals != nullptr) | ||||
|             normals->clear(); | ||||
|         for (const igl::Hit& hit : hits) { | ||||
|             positions->push_back(m_AABB_wrapper->get_hit_pos(hit)); | ||||
|     unsigned i = 0; | ||||
| 
 | ||||
|             if (normals != nullptr) | ||||
|                 normals->push_back(m_AABB_wrapper->get_hit_normal(hit)); | ||||
|     // Remove points that are obscured or cut by the clipping plane
 | ||||
|     if (clipping_plane) { | ||||
|         for (i=0; i<hits.size(); ++i) | ||||
|             if (! clipping_plane->is_point_clipped(trafo * m_AABB_wrapper->get_hit_pos(hits[i]).cast<double>())) | ||||
|                 break; | ||||
| 
 | ||||
|         if (i==hits.size() || (hits.size()-i) % 2 != 0) { | ||||
|             // All hits are either clipped, or there is an odd number of unclipped
 | ||||
|             // hits - meaning the nearest must be from inside the mesh.
 | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Now stuff the points in the provided vector and calculate normals if asked about them:
 | ||||
|     position = m_AABB_wrapper->get_hit_pos(hits[i]); | ||||
|     normal = m_AABB_wrapper->get_hit_normal(hits[i]); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transformation& trafo, const Camera& camera, const std::vector<Vec3f>& points, | ||||
|                                                        std::function<bool(const Vec3f&)> fn_ignore_hit) const | ||||
|                                                        const ClippingPlane* clipping_plane) const | ||||
| { | ||||
|     std::vector<unsigned> out; | ||||
| 
 | ||||
|  | @ -206,19 +211,24 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo | |||
|     Vec3f direction_to_camera_mesh = (instance_matrix_no_translation_no_scaling.inverse().cast<float>() * direction_to_camera).normalized().eval(); | ||||
|     Vec3f scaling = trafo.get_scaling_factor().cast<float>(); | ||||
|     direction_to_camera_mesh = Vec3f(direction_to_camera_mesh(0)*scaling(0), direction_to_camera_mesh(1)*scaling(1), direction_to_camera_mesh(2)*scaling(2)); | ||||
|     const Transform3f inverse_trafo = trafo.get_matrix().inverse().cast<float>(); | ||||
| 
 | ||||
|     for (size_t i=0; i<points.size(); ++i) { | ||||
|         const Vec3f& pt = points[i]; | ||||
|         if (clipping_plane && clipping_plane->is_point_clipped(pt.cast<double>())) | ||||
|             continue; | ||||
| 
 | ||||
|         bool is_obscured = false; | ||||
|         // Cast a ray in the direction of the camera and look for intersection with the mesh:
 | ||||
|         std::vector<igl::Hit> hits; | ||||
|         // Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies.
 | ||||
|         // Offset the start of the ray by EPSILON to account for numerical inaccuracies.
 | ||||
|         if (m_AABB_wrapper->m_AABB.intersect_ray( | ||||
|                 AABBWrapper::MapMatrixXfUnaligned(m_mesh->its.vertices.front().data(), m_mesh->its.vertices.size(), 3), | ||||
|                 AABBWrapper::MapMatrixXiUnaligned(m_mesh->its.indices.front().data(), m_mesh->its.indices.size(), 3), | ||||
|                 pt + direction_to_camera_mesh * EPSILON, direction_to_camera_mesh, hits)) { | ||||
|                 inverse_trafo * pt + direction_to_camera_mesh * EPSILON, direction_to_camera_mesh, hits)) { | ||||
| 
 | ||||
|             std::sort(hits.begin(), hits.end(), [](const igl::Hit& h1, const igl::Hit& h2) { return h1.t < h2.t; }); | ||||
| 
 | ||||
|             // If the closest hit facet normal points in the same direction as the ray,
 | ||||
|             // we are looking through the mesh and should therefore discard the point:
 | ||||
|             if (m_AABB_wrapper->get_hit_normal(hits.front()).dot(direction_to_camera_mesh) > 0.f) | ||||
|  | @ -227,11 +237,12 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo | |||
|             // Eradicate all hits that the caller wants to ignore
 | ||||
|             for (unsigned j=0; j<hits.size(); ++j) { | ||||
|                 const igl::Hit& hit = hits[j]; | ||||
|                 if (fn_ignore_hit(m_AABB_wrapper->get_hit_pos(hit))) { | ||||
|                 if (clipping_plane && clipping_plane->is_point_clipped(trafo.get_matrix() * m_AABB_wrapper->get_hit_pos(hit).cast<double>())) { | ||||
|                     hits.erase(hits.begin()+j); | ||||
|                     --j; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction.
 | ||||
|             // Also, the threshold is in mesh coordinates, not in actual dimensions.
 | ||||
|             if (! hits.empty()) | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ public: | |||
|         return (-get_normal().dot(pt) + m_data[3]); | ||||
|     } | ||||
| 
 | ||||
|     bool is_point_clipped(const Vec3d& point) const { return distance(point) < 0.; } | ||||
|     void set_normal(const Vec3d& normal) { for (size_t i=0; i<3; ++i) m_data[i] = normal(i); } | ||||
|     void set_offset(double offset) { m_data[3] = offset; } | ||||
|     Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); } | ||||
|  | @ -98,10 +99,10 @@ public: | |||
|     void set_camera(const Camera& camera); | ||||
| 
 | ||||
|     bool unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, | ||||
|                            std::vector<Vec3f>* positions = nullptr, std::vector<Vec3f>* normals = nullptr) const; | ||||
|                            Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane = nullptr) const; | ||||
| 
 | ||||
|     std::vector<unsigned> get_unobscured_idxs(const Geometry::Transformation& trafo, const Camera& camera, | ||||
|                                               const std::vector<Vec3f>& points, std::function<bool(const Vec3f&)> fn_ignore_hit) const; | ||||
|                                               const std::vector<Vec3f>& points, const ClippingPlane* clipping_plane = nullptr) const; | ||||
| 
 | ||||
|     Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText**	full_Label/* = n | |||
|         m_options_mode.push_back(option_set[0].opt.mode); | ||||
| 
 | ||||
| 	// if we have a single option with no label, no sidetext just add it directly to sizer
 | ||||
| 	if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && | ||||
|     if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && | ||||
|         option_set.front().opt.label.empty() && | ||||
| 		option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&  | ||||
| 		line.get_extra_widgets().size() == 0) { | ||||
|  |  | |||
|  | @ -4288,11 +4288,10 @@ void Plater::increase_instances(size_t num) | |||
| 
 | ||||
|     sidebar().obj_list()->increase_object_instances(obj_idx, was_one_instance ? num + 1 : num); | ||||
| 
 | ||||
|     if (p->get_config("autocenter") == "1") { | ||||
|     if (p->get_config("autocenter") == "1") | ||||
|         p->arrange(); | ||||
|     } else { | ||||
|         p->update(); | ||||
|     } | ||||
| 
 | ||||
|     p->update(); | ||||
| 
 | ||||
|     p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1); | ||||
| 
 | ||||
|  |  | |||
|  | @ -279,7 +279,7 @@ std::string PresetBundle::load_system_presets() | |||
|                 errors_cummulative += "\n"; | ||||
|             } | ||||
|         } | ||||
| 	if (first) { | ||||
|     if (first) { | ||||
| 		// No config bundle loaded, reset.
 | ||||
| 		this->reset(false); | ||||
| 	} | ||||
|  |  | |||
|  | @ -410,7 +410,7 @@ void Selection::set_deserialized(EMode mode, const std::vector<std::pair<size_t, | |||
|     if (! m_valid) | ||||
|         return; | ||||
| 
 | ||||
| 	m_mode = mode; | ||||
|     m_mode = mode; | ||||
|     for (unsigned int i : m_list) | ||||
|         (*m_volumes)[i]->selected = false; | ||||
|     m_list.clear(); | ||||
|  |  | |||
|  | @ -371,7 +371,7 @@ void WipingPanel::toggle_advanced(bool user_action) { | |||
|     else | ||||
|         m_advanced = !advanced_matches_simple(); // if called from constructor, show what is appropriate
 | ||||
| 
 | ||||
| 	(m_advanced ? m_page_advanced : m_page_simple)->Show(); | ||||
|     (m_advanced ? m_page_advanced : m_page_simple)->Show(); | ||||
| 	(!m_advanced ? m_page_advanced : m_page_simple)->Hide(); | ||||
| 
 | ||||
|     m_widget_button->SetLabel(m_advanced ? _(L("Show simplified settings")) : _(L("Show advanced settings"))); | ||||
|  |  | |||
|  | @ -669,7 +669,7 @@ wxDataViewItem ObjectDataViewModel::Add(const wxString &name, | |||
|     if (has_errors) | ||||
|         root->m_bmp = *m_warning_bmp; | ||||
| 
 | ||||
| 	m_objects.push_back(root); | ||||
|     m_objects.push_back(root); | ||||
| 	// notify control
 | ||||
| 	wxDataViewItem child((void*)root); | ||||
| 	wxDataViewItem parent((void*)NULL); | ||||
|  | @ -720,7 +720,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent | |||
|         root->SetBitmap(*m_warning_bmp); | ||||
| 
 | ||||
| 	// notify control
 | ||||
| 	const wxDataViewItem child((void*)node); | ||||
|     const wxDataViewItem child((void*)node); | ||||
|     ItemAdded(parent_item, child); | ||||
|     root->m_volumes_cnt++; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka