mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_plater_thumbnail
This commit is contained in:
		
						commit
						8b8b6c1821
					
				
					 10 changed files with 307 additions and 25 deletions
				
			
		|  | @ -45,6 +45,7 @@ src/slic3r/GUI/WipeTowerDialog.cpp | |||
| src/slic3r/GUI/wxExtensions.cpp | ||||
| src/slic3r/Utils/Duet.cpp | ||||
| src/slic3r/Utils/OctoPrint.cpp | ||||
| src/slic3r/Utils/FlashAir.cpp | ||||
| src/slic3r/Utils/PresetUpdater.cpp | ||||
| src/slic3r/Utils/FixModelByWin10.cpp | ||||
| src/libslic3r/Zipper.cpp | ||||
|  |  | |||
|  | @ -951,6 +951,7 @@ ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperL | |||
| ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit) | ||||
| { | ||||
| 	assert(contour.size() == deltas.size()); | ||||
| 
 | ||||
| #ifndef NDEBUG | ||||
| 	// Verify that the deltas are either all positive, or all negative.
 | ||||
| 	bool positive = false; | ||||
|  | @ -986,7 +987,10 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v | |||
| 		double lmin  = *std::max_element(deltas.begin(), deltas.end()) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR; | ||||
| 		double l2min = lmin * lmin; | ||||
| 		// Minimum angle to consider two edges to be parallel.
 | ||||
| 		double sin_min_parallel = EPSILON + 1. / double(CLIPPER_OFFSET_SCALE); | ||||
| 		// Vojtech's estimate.
 | ||||
| //		const double sin_min_parallel = EPSILON + 1. / double(CLIPPER_OFFSET_SCALE);
 | ||||
| 		// Implementation equal to Clipper.
 | ||||
| 		const double sin_min_parallel = 1.; | ||||
| 
 | ||||
| 		// Find the last point further from pt by l2min.
 | ||||
| 		Vec2d  pt     = contour.front().cast<double>(); | ||||
|  | @ -1012,8 +1016,12 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v | |||
| 					if (l2 > l2min) | ||||
| 						break; | ||||
| 				} | ||||
| 				if (j > ilast) | ||||
| 				if (j > ilast) { | ||||
| 					assert(i <= ilast); | ||||
| 					// If the last edge is too short, merge it with the previous edge.
 | ||||
| 					i = ilast; | ||||
| 					ptnext = contour.front().cast<double>(); | ||||
| 				} | ||||
| 
 | ||||
| 				// Normal to the (ptnext - pt) segment.
 | ||||
| 				Vec2d nnext  = perp(ptnext - pt).normalized(); | ||||
|  | @ -1026,27 +1034,29 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v | |||
| 					add_offset_point(pt + nprev * delta); | ||||
| 					add_offset_point(pt); | ||||
| 					add_offset_point(pt + nnext * delta); | ||||
| 				} else if (convex < sin_min_parallel) { | ||||
| 					// Nearly parallel.
 | ||||
| 					add_offset_point((nprev.dot(nnext) > 0.) ? (pt + nprev * delta) : pt); | ||||
| 				} else { | ||||
| 					// Convex corner
 | ||||
| 					double dot = nprev.dot(nnext); | ||||
| 					double r = 1. + dot; | ||||
| 				  	if (r >= miter_limit) | ||||
| 						add_offset_point(pt + (nprev + nnext) * (delta / r)); | ||||
| 				  	else { | ||||
| 						double dx = std::tan(std::atan2(sin_a, dot) / 4.); | ||||
| 						Vec2d  newpt1 = pt + (nprev - perp(nprev) * dx) * delta; | ||||
| 						Vec2d  newpt2 = pt + (nnext + perp(nnext) * dx) * delta; | ||||
| 					if (convex < sin_min_parallel && dot > 0.) { | ||||
| 						// Nearly parallel.
 | ||||
| 						add_offset_point((nprev.dot(nnext) > 0.) ? (pt + nprev * delta) : pt); | ||||
| 					} else { | ||||
| 						// Convex corner, possibly extremely sharp if convex < sin_min_parallel.
 | ||||
| 						double r = 1. + dot; | ||||
| 					  	if (r >= miter_limit) | ||||
| 							add_offset_point(pt + (nprev + nnext) * (delta / r)); | ||||
| 					  	else { | ||||
| 							double dx = std::tan(std::atan2(sin_a, dot) / 4.); | ||||
| 							Vec2d  newpt1 = pt + (nprev - perp(nprev) * dx) * delta; | ||||
| 							Vec2d  newpt2 = pt + (nnext + perp(nnext) * dx) * delta; | ||||
| #ifndef NDEBUG | ||||
| 						Vec2d vedge = 0.5 * (newpt1 + newpt2) - pt; | ||||
| 						double dist_norm = vedge.norm(); | ||||
| 						assert(std::abs(dist_norm - delta) < EPSILON); | ||||
| 							Vec2d vedge = 0.5 * (newpt1 + newpt2) - pt; | ||||
| 							double dist_norm = vedge.norm(); | ||||
| 							assert(std::abs(dist_norm - std::abs(delta)) < SCALED_EPSILON); | ||||
| #endif /* NDEBUG */ | ||||
| 						add_offset_point(newpt1); | ||||
| 						add_offset_point(newpt2); | ||||
| 				  	} | ||||
| 							add_offset_point(newpt1); | ||||
| 							add_offset_point(newpt2); | ||||
| 					  	} | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				if (i == ilast) | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx | |||
| 
 | ||||
| 						if (std::abs(denom) >= EPSILON) { | ||||
| 							double t = cross2(dir2, vptpt2) / denom; | ||||
| 							assert(t > 0. && t <= 1.); | ||||
| 							assert(t > - EPSILON && t < 1. + EPSILON); | ||||
| 							bool this_valid = true; | ||||
| 							if (it_contour_and_segment->first == idx_contour) { | ||||
| 								// The intersected segment originates from the same contour as the starting point.
 | ||||
|  | @ -105,7 +105,7 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx | |||
| 									auto it = std::lower_bound(resampled_point_parameters.begin(), resampled_point_parameters.end(), key, lower); | ||||
| 									assert(it != resampled_point_parameters.end() && it->idx_src == ipt && ! it->interpolated); | ||||
| 									double t2 = cross2(dir, vptpt2) / denom; | ||||
| 									assert(t2 >= 0. && t2 <= 1.); | ||||
| 									assert(t2 > - EPSILON && t2 < 1. + EPSILON); | ||||
| 									if (++ ipt == ipts.size()) | ||||
| 										param_hi = t2 * dir2.norm(); | ||||
| 									else | ||||
|  |  | |||
|  | @ -1327,8 +1327,10 @@ void PrintConfigDef::init_fff_params() | |||
|     def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values(); | ||||
|     def->enum_values.push_back("octoprint"); | ||||
|     def->enum_values.push_back("duet"); | ||||
|     def->enum_values.push_back("flashair"); | ||||
|     def->enum_labels.push_back("OctoPrint"); | ||||
|     def->enum_labels.push_back("Duet"); | ||||
|     def->enum_labels.push_back("FlashAir"); | ||||
|     def->mode = comAdvanced; | ||||
|     def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ enum GCodeFlavor : unsigned char { | |||
| }; | ||||
| 
 | ||||
| enum PrintHostType { | ||||
|     htOctoPrint, htDuet | ||||
|     htOctoPrint, htDuet, htFlashAir | ||||
| }; | ||||
| 
 | ||||
| enum InfillPattern { | ||||
|  | @ -102,6 +102,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<PrintHostType>::g | |||
|     if (keys_map.empty()) { | ||||
|         keys_map["octoprint"]       = htOctoPrint; | ||||
|         keys_map["duet"]            = htDuet; | ||||
|         keys_map["flashair"]        = htFlashAir; | ||||
|     } | ||||
|     return keys_map; | ||||
| } | ||||
|  |  | |||
|  | @ -1772,7 +1772,8 @@ end: | |||
|                 float delta = float(scale_(m_config.xy_size_compensation.value)); | ||||
|                 //FIXME only apply the compensation if no raft is enabled.
 | ||||
|                 float elephant_foot_compensation = 0.f; | ||||
|                 if (layer_id == 0) | ||||
|                 if (layer_id == 0 && m_config.raft_layers == 0) | ||||
|                 	// Only enable Elephant foot compensation if printing directly on the print bed.
 | ||||
|                     elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value)); | ||||
|                 if (layer->m_regions.size() == 1) { | ||||
|                     // Optimized version for a single region layer.
 | ||||
|  | @ -1819,11 +1820,12 @@ end: | |||
|                     if (delta < 0.f || elephant_foot_compensation > 0.f) { | ||||
|                         // Apply the negative XY compensation.
 | ||||
|                         Polygons trimming; | ||||
|                         static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); | ||||
|                         if (elephant_foot_compensation > 0.f) { | ||||
| 							trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(float(EPSILON)), std::min(delta, 0.f) - float(EPSILON)),  | ||||
| 							trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(eps), std::min(delta, 0.f) - eps), | ||||
| 								layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation))); | ||||
|                         } else | ||||
| 	                        trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON)); | ||||
| 	                        trimming = offset(layer->merged(float(SCALED_EPSILON)), delta - float(SCALED_EPSILON)); | ||||
|                         for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) | ||||
|                             layer->m_regions[region_id]->trim_surfaces(trimming); | ||||
|                     } | ||||
|  |  | |||
|  | @ -144,6 +144,8 @@ set(SLIC3R_GUI_SOURCES | |||
|     Utils/OctoPrint.hpp | ||||
|     Utils/Duet.cpp | ||||
|     Utils/Duet.hpp | ||||
|     Utils/FlashAir.cpp | ||||
|     Utils/FlashAir.hpp | ||||
|     Utils/PrintHost.cpp | ||||
|     Utils/PrintHost.hpp | ||||
|     Utils/Bonjour.cpp | ||||
|  |  | |||
							
								
								
									
										218
									
								
								src/slic3r/Utils/FlashAir.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/slic3r/Utils/FlashAir.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,218 @@ | |||
| #include "FlashAir.hpp" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <ctime> | ||||
| #include <boost/filesystem/path.hpp> | ||||
| #include <boost/format.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| #include <wx/frame.h> | ||||
| #include <wx/event.h> | ||||
| #include <wx/progdlg.h> | ||||
| #include <wx/sizer.h> | ||||
| #include <wx/stattext.h> | ||||
| #include <wx/textctrl.h> | ||||
| #include <wx/checkbox.h> | ||||
| 
 | ||||
| #include "libslic3r/PrintConfig.hpp" | ||||
| #include "slic3r/GUI/GUI.hpp" | ||||
| #include "slic3r/GUI/I18N.hpp" | ||||
| #include "slic3r/GUI/MsgDialog.hpp" | ||||
| #include "Http.hpp" | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
| namespace pt = boost::property_tree; | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| FlashAir::FlashAir(DynamicPrintConfig *config) : | ||||
| 	host(config->opt_string("print_host")) | ||||
| {} | ||||
| 
 | ||||
| FlashAir::~FlashAir() {} | ||||
| 
 | ||||
| const char* FlashAir::get_name() const { return "FlashAir"; } | ||||
| 
 | ||||
| bool FlashAir::test(wxString &msg) const | ||||
| { | ||||
| 	// Since the request is performed synchronously here,
 | ||||
| 	// it is ok to refer to `msg` from within the closure
 | ||||
| 
 | ||||
| 	const char *name = get_name(); | ||||
| 
 | ||||
| 	bool res = false; | ||||
| 	auto url = make_url("command.cgi", "op", "118"); | ||||
| 
 | ||||
| 	BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get upload enabled at: %2%") % name % url; | ||||
| 
 | ||||
| 	auto http = Http::get(std::move(url)); | ||||
| 	http.on_error([&](std::string body, std::string error, unsigned status) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting upload enabled: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; | ||||
| 			res = false; | ||||
| 			msg = format_error(body, error, status); | ||||
| 		}) | ||||
| 		.on_complete([&, this](std::string body, unsigned) { | ||||
| 			BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got upload enabled: %2%") % name % body; | ||||
| 
 | ||||
| 			res = boost::starts_with(body, "1"); | ||||
| 			if (! res) { | ||||
| 				msg = _(L("Upload not enabled on FlashAir card.")); | ||||
| 			} | ||||
| 		}) | ||||
| 		.perform_sync(); | ||||
| 
 | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| wxString FlashAir::get_test_ok_msg () const | ||||
| { | ||||
| 	return _(L("Connection to FlashAir works correctly and upload is enabled.")); | ||||
| } | ||||
| 
 | ||||
| wxString FlashAir::get_test_failed_msg (wxString &msg) const | ||||
| { | ||||
| 	return wxString::Format("%s: %s", _(L("Could not connect to FlashAir")), msg, _(L("Note: FlashAir with firmware 2.00.02 or newer and activated upload function is required."))); | ||||
| } | ||||
| 
 | ||||
| bool FlashAir::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const | ||||
| { | ||||
| 	const char *name = get_name(); | ||||
| 
 | ||||
| 	const auto upload_filename = upload_data.upload_path.filename(); | ||||
| 	const auto upload_parent_path = upload_data.upload_path.parent_path(); | ||||
| 
 | ||||
| 	wxString test_msg; | ||||
| 	if (! test(test_msg)) { | ||||
| 		error_fn(std::move(test_msg)); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	bool res = false; | ||||
| 
 | ||||
| 	auto urlPrepare = make_url("upload.cgi", "WRITEPROTECT=ON&FTIME", timestamp_str()); | ||||
| 	auto urlUpload = make_url("upload.cgi"); | ||||
| 
 | ||||
| 	BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3% / %4%, filename: %5%") | ||||
| 		% name | ||||
| 		% upload_data.source_path | ||||
| 		% urlPrepare | ||||
| 		% urlUpload | ||||
| 		% upload_filename.string(); | ||||
| 
 | ||||
| 	// set filetime for upload and make card writeprotect to prevent filesystem damage
 | ||||
| 	auto httpPrepare = Http::get(std::move(urlPrepare)); | ||||
| 	httpPrepare.on_error([&](std::string body, std::string error, unsigned status) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error prepareing upload: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; | ||||
| 			error_fn(format_error(body, error, status)); | ||||
| 			res = false; | ||||
| 		}) | ||||
| 		.on_complete([&, this](std::string body, unsigned) { | ||||
| 			BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got prepare result: %2%") % name % body; | ||||
| 			res = boost::icontains(body, "SUCCESS"); | ||||
| 			if (! res) { | ||||
| 				BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name; | ||||
| 				error_fn(format_error(body, L("Unknown error occured"), 0)); | ||||
| 			} | ||||
| 		}) | ||||
| 		.perform_sync(); | ||||
| 	 | ||||
| 	if(! res ) { | ||||
| 		return res; | ||||
| 	} | ||||
| 	 | ||||
| 	// start file upload
 | ||||
| 	auto http = Http::post(std::move(urlUpload)); | ||||
| 	http.form_add_file("file", upload_data.source_path.string(), upload_filename.string()) | ||||
| 		.on_complete([&](std::string body, unsigned status) { | ||||
| 			BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; | ||||
| 			res = boost::icontains(body, "SUCCESS"); | ||||
| 			if (! res) { | ||||
| 				BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name; | ||||
| 				error_fn(format_error(body, L("Unknown error occured"), 0)); | ||||
| 			} | ||||
| 		}) | ||||
| 		.on_error([&](std::string body, std::string error, unsigned status) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; | ||||
| 			error_fn(format_error(body, error, status)); | ||||
| 			res = false; | ||||
| 		}) | ||||
| 		.on_progress([&](Http::Progress progress, bool &cancel) { | ||||
| 			prorgess_fn(std::move(progress), cancel); | ||||
| 			if (cancel) { | ||||
| 				// Upload was canceled
 | ||||
| 				BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Upload canceled") % name; | ||||
| 				res = false; | ||||
| 			} | ||||
| 		}) | ||||
| 		.perform_sync(); | ||||
| 
 | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| bool FlashAir::has_auto_discovery() const | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool FlashAir::can_test() const | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool FlashAir::can_start_print() const | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| std::string FlashAir::timestamp_str() const | ||||
| { | ||||
| 	auto t = std::time(nullptr); | ||||
| 	auto tm = *std::localtime(&t); | ||||
| 
 | ||||
| 	const char *name = get_name(); | ||||
| 
 | ||||
| 	unsigned long fattime = ((tm.tm_year - 80) << 25) |  | ||||
| 							((tm.tm_mon + 1) << 21) | | ||||
| 							(tm.tm_mday << 16) | | ||||
| 							(tm.tm_hour << 11) | | ||||
| 							(tm.tm_min << 5) | | ||||
| 							(tm.tm_sec >> 1); | ||||
| 
 | ||||
| 	return (boost::format("%1$#x") % fattime).str(); | ||||
| } | ||||
| 
 | ||||
| std::string FlashAir::make_url(const std::string &path) const | ||||
| { | ||||
| 	if (host.find("http://") == 0 || host.find("https://") == 0) { | ||||
| 		if (host.back() == '/') { | ||||
| 			return (boost::format("%1%%2%") % host % path).str(); | ||||
| 		} else { | ||||
| 			return (boost::format("%1%/%2%") % host % path).str(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (host.back() == '/') { | ||||
| 			return (boost::format("http://%1%%2%") % host % path).str(); | ||||
| 		} else { | ||||
| 			return (boost::format("http://%1%/%2%") % host % path).str(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| std::string FlashAir::make_url(const std::string &path, const std::string &arg, const std::string &val) const | ||||
| { | ||||
| 	if (host.find("http://") == 0 || host.find("https://") == 0) { | ||||
| 		if (host.back() == '/') { | ||||
| 			return (boost::format("%1%%2%?%3%=%4%") % host % path % arg % val).str(); | ||||
| 		} else { | ||||
| 			return (boost::format("%1%/%2%?%3%=%4%") % host % path % arg % val).str(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (host.back() == '/') { | ||||
| 			return (boost::format("http://%1%%2%?%3%=%4%") % host % path % arg % val).str(); | ||||
| 		} else { | ||||
| 			return (boost::format("http://%1%/%2%?%3%=%4%") % host % path % arg % val).str(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										44
									
								
								src/slic3r/Utils/FlashAir.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/slic3r/Utils/FlashAir.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| #ifndef slic3r_FlashAir_hpp_ | ||||
| #define slic3r_FlashAir_hpp_ | ||||
| 
 | ||||
| #include <string> | ||||
| #include <wx/string.h> | ||||
| 
 | ||||
| #include "PrintHost.hpp" | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| 
 | ||||
| class DynamicPrintConfig; | ||||
| class Http; | ||||
| 
 | ||||
| class FlashAir : public PrintHost | ||||
| { | ||||
| public: | ||||
| 	FlashAir(DynamicPrintConfig *config); | ||||
| 	virtual ~FlashAir(); | ||||
| 
 | ||||
| 	virtual const char* get_name() const; | ||||
| 
 | ||||
| 	virtual bool test(wxString &curl_msg) const; | ||||
| 	virtual wxString get_test_ok_msg () const; | ||||
| 	virtual wxString get_test_failed_msg (wxString &msg) const; | ||||
| 	virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const; | ||||
| 	virtual bool has_auto_discovery() const; | ||||
| 	virtual bool can_test() const; | ||||
| 	virtual bool can_start_print() const; | ||||
| 	virtual std::string get_host() const { return host; } | ||||
| 
 | ||||
| private: | ||||
| 	std::string host; | ||||
| 
 | ||||
| 	std::string timestamp_str() const; | ||||
| 	std::string make_url(const std::string &path) const; | ||||
| 	std::string make_url(const std::string &path, const std::string &arg, const std::string &val) const; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -14,6 +14,7 @@ | |||
| #include "libslic3r/Channel.hpp" | ||||
| #include "OctoPrint.hpp" | ||||
| #include "Duet.hpp" | ||||
| #include "FlashAir.hpp" | ||||
| #include "../GUI/PrintHostDialogs.hpp" | ||||
| 
 | ||||
| namespace fs = boost::filesystem; | ||||
|  | @ -43,6 +44,7 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config) | |||
|         switch (host_type) { | ||||
|             case htOctoPrint: return new OctoPrint(config); | ||||
|             case htDuet:      return new Duet(config); | ||||
|             case htFlashAir:  return new FlashAir(config); | ||||
|             default:          return nullptr; | ||||
|         } | ||||
|     } else { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri