mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	WIP Standalone G-code viewer
This commit is contained in:
		
							parent
							
								
									f58d3116bf
								
							
						
					
					
						commit
						946f51467f
					
				
					 7 changed files with 192 additions and 38 deletions
				
			
		|  | @ -106,9 +106,9 @@ if (MINGW) | |||
|     set_target_properties(PrusaSlicer PROPERTIES PREFIX "") | ||||
| endif (MINGW) | ||||
| 
 | ||||
| if (NOT WIN32) | ||||
|     # Binary name on unix like systems (OSX, Linux) | ||||
|    set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer") | ||||
| if (NOT WIN32 AND NOT APPLE) | ||||
|     # Binary name on unix like systems (Linux, Unix) | ||||
|     set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer") | ||||
| endif () | ||||
| 
 | ||||
| target_link_libraries(PrusaSlicer libslic3r cereal) | ||||
|  | @ -209,20 +209,34 @@ if (WIN32) | |||
|     add_custom_target(PrusaSlicerDllsCopy ALL DEPENDS PrusaSlicer) | ||||
|     prusaslicer_copy_dlls(PrusaSlicerDllsCopy) | ||||
|      | ||||
| elseif (XCODE) | ||||
|     # Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level | ||||
|     add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|         COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/resources" | ||||
|         COMMENT "Symlinking the resources directory into the build tree" | ||||
|         VERBATIM | ||||
|     ) | ||||
| else () | ||||
|     if (APPLE) | ||||
|         # On OSX, the name of the binary matches the name of the Application. | ||||
|         add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|             COMMAND ln -sf PrusaSlicer prusa-slicer | ||||
|             COMMAND ln -sf PrusaSlicer prusa-gcodeviewer | ||||
|             COMMAND ln -sf PrusaSlicer PrusaGCodeViewer | ||||
|             WORKING_DIRECTORY "$<TARGET_FILE_DIR:PrusaSlicer>" | ||||
|             COMMENT "Symlinking the G-code viewer to PrusaSlicer, symlinking to prusa-slicer and prusa-gcodeviewer" | ||||
|             VERBATIM) | ||||
|     else () | ||||
|         add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|             COMMAND ln -sf prusa-slicer prusa-gcodeviewer | ||||
|             WORKING_DIRECTORY "$<TARGET_FILE_DIR:PrusaSlicer>" | ||||
|             COMMENT "Symlinking the G-code viewer to PrusaSlicer" | ||||
|             VERBATIM) | ||||
|     endif () | ||||
|     if (XCODE) | ||||
|         # Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level | ||||
|         set(BIN_RESOURCES_DIR "${CMAKE_CURRENT_BINARY_DIR}/resources") | ||||
|     else () | ||||
|         set(BIN_RESOURCES_DIR "${CMAKE_CURRENT_BINARY_DIR}/../resources") | ||||
|     endif () | ||||
|     add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|         COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources" | ||||
|         COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${BIN_RESOURCES_DIR}" | ||||
|         COMMENT "Symlinking the resources directory into the build tree" | ||||
|         VERBATIM | ||||
|     ) | ||||
| endif() | ||||
|         VERBATIM) | ||||
| endif () | ||||
| 
 | ||||
| # Slic3r binary install target | ||||
| if (WIN32) | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include <cstring> | ||||
| #include <iostream> | ||||
| #include <math.h> | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/nowide/args.hpp> | ||||
| #include <boost/nowide/cenv.hpp> | ||||
|  | @ -101,8 +102,14 @@ int CLI::run(int argc, char **argv) | |||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && | ||||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && | ||||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); | ||||
|     bool 							start_as_gcodeviewer = false; | ||||
|      | ||||
|     bool 							start_as_gcodeviewer = | ||||
| #ifdef _WIN32 | ||||
|             false; | ||||
| #else | ||||
|             // On Unix systems, the prusa-slicer binary may be symlinked to give the application a different meaning.
 | ||||
|             boost::algorithm::iends_with(boost::filesystem::path(argv[0]).filename().string(), "gcodeviewer"); | ||||
| #endif // _WIN32
 | ||||
| 
 | ||||
|     const std::vector<std::string> &load_configs		= m_config.option<ConfigOptionStrings>("load", true)->values; | ||||
| 
 | ||||
|     // load config files supplied via --load
 | ||||
|  |  | |||
|  | @ -195,6 +195,8 @@ set(SLIC3R_GUI_SOURCES | |||
|     Utils/Bonjour.hpp | ||||
|     Utils/PresetUpdater.cpp | ||||
|     Utils/PresetUpdater.hpp | ||||
|     Utils/Process.cpp | ||||
|     Utils/Process.hpp | ||||
|     Utils/Profile.hpp | ||||
|     Utils/UndoRedo.cpp | ||||
|     Utils/UndoRedo.hpp | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ | |||
| #include <wx/tooltip.h> | ||||
| //#include <wx/glcanvas.h>
 | ||||
| #include <wx/filename.h> | ||||
| #include <wx/stdpaths.h> | ||||
| #include <wx/debug.h> | ||||
| 
 | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
|  | @ -31,6 +30,7 @@ | |||
| #include "I18N.hpp" | ||||
| #include "GLCanvas3D.hpp" | ||||
| #include "Plater.hpp" | ||||
| #include "../Utils/Process.hpp" | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include "GUI_App.hpp" | ||||
|  | @ -40,12 +40,6 @@ | |||
| #include <shlobj.h> | ||||
| #endif // _WIN32
 | ||||
| 
 | ||||
| // For starting another PrusaSlicer instance on OSX.
 | ||||
| // Fails to compile on Windows on the build server.
 | ||||
| #ifdef __APPLE__ | ||||
|     #include <boost/process/spawn.hpp> | ||||
| #endif | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
|  | @ -1054,8 +1048,8 @@ void MainFrame::init_menubar() | |||
|         append_menu_item(fileMenu, wxID_ANY, _L("&Repair STL file") + dots, _L("Automatically repair an STL file"), | ||||
|             [this](wxCommandEvent&) { repair_stl(); }, "wrench", nullptr, | ||||
|             [this]() { return true; }, this); | ||||
| #if ENABLE_GCODE_VIEWER | ||||
|         fileMenu->AppendSeparator(); | ||||
| #if ENABLE_GCODE_VIEWER | ||||
|         append_menu_item(fileMenu, wxID_ANY, _L("&G-code preview"), _L("Switch to G-code preview mode"), | ||||
|             [this](wxCommandEvent&) { | ||||
|                 if (m_plater->model().objects.empty() || | ||||
|  | @ -1064,6 +1058,8 @@ void MainFrame::init_menubar() | |||
|                     set_mode(EMode::GCodeViewer); | ||||
|             }, "", nullptr); | ||||
| #endif // ENABLE_GCODE_VIEWER
 | ||||
|         append_menu_item(fileMenu, wxID_ANY, _L("&G-code preview") + dots, _L("Open G-code viewer"), | ||||
|             [this](wxCommandEvent&) { start_new_gcodeviewer_open_file(this); }, "", nullptr); | ||||
|         fileMenu->AppendSeparator(); | ||||
|         append_menu_item(fileMenu, wxID_EXIT, _L("&Quit"), wxString::Format(_L("Quit %s"), SLIC3R_APP_NAME), | ||||
|             [this](wxCommandEvent&) { Close(false); }); | ||||
|  | @ -1180,20 +1176,11 @@ void MainFrame::init_menubar() | |||
| 
 | ||||
|         windowMenu->AppendSeparator(); | ||||
|         append_menu_item(windowMenu, wxID_ANY, _L("Print &Host Upload Queue") + "\tCtrl+J", _L("Display the Print Host Upload Queue window"), | ||||
|             [this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue", nullptr, | ||||
|             [this]() {return true; }, this); | ||||
|             [this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue", nullptr, [this]() {return true; }, this); | ||||
|          | ||||
|         windowMenu->AppendSeparator(); | ||||
|         append_menu_item(windowMenu, wxID_ANY, _(L("Open new instance")) + "\tCtrl+I", _(L("Open a new PrusaSlicer instance")), | ||||
|                          [this](wxCommandEvent&) { | ||||
|                              wxString path = wxStandardPaths::Get().GetExecutablePath(); | ||||
| #ifdef __APPLE__ | ||||
|                              boost::process::spawn((const char*)path.c_str()); | ||||
| #else | ||||
|                              wxExecute(wxStandardPaths::Get().GetExecutablePath(), wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE | wxEXEC_MAKE_GROUP_LEADER); | ||||
| #endif | ||||
|                          }, "upload_queue", nullptr, | ||||
|                          [this]() {return true; }, this); | ||||
| 			[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr); | ||||
|     } | ||||
| 
 | ||||
|     // View menu
 | ||||
|  |  | |||
							
								
								
									
										125
									
								
								src/slic3r/Utils/Process.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/slic3r/Utils/Process.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,125 @@ | |||
| #include "Process.hpp" | ||||
| 
 | ||||
| #include <libslic3r/AppConfig.hpp> | ||||
| 
 | ||||
| #include "../GUI/GUI.hpp" | ||||
| // for file_wildcards()
 | ||||
| #include "../GUI/GUI_App.hpp" | ||||
| // localization
 | ||||
| #include "../GUI/I18N.hpp" | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| // For starting another PrusaSlicer instance on OSX.
 | ||||
| // Fails to compile on Windows on the build server.
 | ||||
| #ifdef __APPLE__ | ||||
|     #include <boost/process/spawn.hpp> | ||||
| #endif | ||||
| 
 | ||||
| #include <wx/stdpaths.h> | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| enum class NewSlicerInstanceType { | ||||
| 	Slicer, | ||||
| 	GCodeViewer | ||||
| }; | ||||
| 
 | ||||
| // Start a new Slicer process instance either in a Slicer mode or in a G-code mode.
 | ||||
| // Optionally load a 3MF, STL or a G-code on start.
 | ||||
| static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance_type, const wxString *path_to_open) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
| 	wxString path; | ||||
| 	wxFileName::SplitPath(wxStandardPaths::Get().GetExecutablePath(), &path, nullptr, nullptr, wxPATH_NATIVE); | ||||
| 	path += "\\"; | ||||
| 	path += (instance_type == NewSlicerInstanceType::Slicer) ? "prusa-slicer.exe" : "prusa-gcodeviewer.exe"; | ||||
| 	std::vector<const wchar_t*> args; | ||||
| 	args.reserve(3); | ||||
| 	args.emplace_back(path.wc_str()); | ||||
| 	if (path_to_open != nullptr) | ||||
| 		args.emplace_back(path_to_open->wc_str()); | ||||
| 	args.emplace_back(nullptr); | ||||
| 	BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << to_u8(path) << "\""; | ||||
| 	if (wxExecute(const_cast<wchar_t**>(args.data()), wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE | wxEXEC_MAKE_GROUP_LEADER) <= 0) | ||||
| 		BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << to_u8(path); | ||||
| #else  | ||||
| 	// Own executable path.
 | ||||
|     boost::filesystem::path bin_path = into_path(wxStandardPaths::Get().GetExecutablePath()); | ||||
| 	#if defined(__APPLE__) | ||||
| 	{ | ||||
| 		bin_path =	bin_path.parent_path() / ((instance_type == NewSlicerInstanceType::Slicer) ? "PrusaSlicer" : "PrusaGCodeViewer"); | ||||
| 		// On Apple the wxExecute fails, thus we use boost::process instead.
 | ||||
| 		BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << bin_path.string() << "\""; | ||||
| 		try { | ||||
| 	    	path_to_open ? boost::process::spawn(bin_path, into_u8(*path_to_open)) : boost::process::spawn(bin_path, boost::process::args()); | ||||
| 	    } catch (const std::exception &ex) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << bin_path.string() << "\": " << ex.what(); | ||||
| 	    } | ||||
| 	} | ||||
| 	#else // Linux or Unix
 | ||||
| 	{ | ||||
| 		std::vector<const char*> args; | ||||
| 	    args.reserve(3); | ||||
| 		#ifdef __linux | ||||
| 		static const char *gcodeviewer_param = "--gcodeviewer"; | ||||
| 	    { | ||||
| 			// If executed by an AppImage, start the AppImage, not the main process.
 | ||||
| 			// see https://docs.appimage.org/packaging-guide/environment-variables.html#id2
 | ||||
| 			const char *appimage_binary = std::getenv("APPIMAGE"); | ||||
| 			if (appimage_binary) { | ||||
| 				args.emplace_back(appimage_binary); | ||||
| 				if (instance_type == NewSlicerInstanceType::GCodeViewer) | ||||
| 					args.emplace_back(gcodeviewer_param); | ||||
| 			} | ||||
| 		} | ||||
| 		#endif // __linux
 | ||||
| 		std::string my_path; | ||||
| 		if (args.empty()) { | ||||
| 			// Binary path was not set to the AppImage in the Linux specific block above, call the application directly.
 | ||||
| 			my_path = (bin_path.parent_path() / ((instance_type == NewSlicerInstanceType::Slicer) ? "prusa-slicer" : "prusa-gcodeviewer")).string(); | ||||
| 			args.emplace_back(my_path.c_str()); | ||||
| 		} | ||||
| 	    std::string to_open; | ||||
| 	    if (path_to_open) { | ||||
| 	    	to_open = into_u8(*path_to_open); | ||||
| 	    	args.emplace_back(to_open.c_str()); | ||||
| 	    } | ||||
| 	    args.emplace_back(nullptr); | ||||
| 		BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << args[0] << "\""; | ||||
| 	    if (wxExecute(const_cast<char**>(args.data()), wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE | wxEXEC_MAKE_GROUP_LEADER) <= 0) | ||||
| 	    	BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << args[0]; | ||||
| 	} | ||||
| 	#endif // Linux or Unix
 | ||||
| #endif // Win32
 | ||||
| } | ||||
| 
 | ||||
| void start_new_slicer(const wxString *path_to_open) | ||||
| { | ||||
| 	start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::Slicer, path_to_open); | ||||
| } | ||||
| 
 | ||||
| void start_new_gcodeviewer(const wxString *path_to_open) | ||||
| { | ||||
| 	start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::GCodeViewer, path_to_open); | ||||
| } | ||||
| 
 | ||||
| void start_new_gcodeviewer_open_file(wxWindow *parent) | ||||
| { | ||||
|     wxFileDialog dialog(parent ? parent : wxGetApp().GetTopWindow(), | ||||
|         _L("Open G-code file:"), | ||||
|         from_u8(wxGetApp().app_config->get_last_dir()), wxString(), | ||||
|         file_wildcards(FT_GCODE), wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|     if (dialog.ShowModal() == wxID_OK) { | ||||
|         wxString path = dialog.GetPath(); | ||||
| 		start_new_gcodeviewer(&path); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
							
								
								
									
										19
									
								
								src/slic3r/Utils/Process.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/slic3r/Utils/Process.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| #ifndef GUI_PROCESS_HPP | ||||
| #define GUI_PROCESS_HPP | ||||
| 
 | ||||
| class wxWindow; | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
| 
 | ||||
| // Start a new slicer instance, optionally with a file to open.
 | ||||
| void start_new_slicer(const wxString *path_to_open = nullptr); | ||||
| // Start a new G-code viewer instance, optionally with a file to open.
 | ||||
| void start_new_gcodeviewer(const wxString *path_to_open = nullptr); | ||||
| // Open a file dialog, ask the user to select a new G-code to open, start a new G-code viewer.
 | ||||
| void start_new_gcodeviewer_open_file(wxWindow *parent = nullptr); | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #endif // GUI_PROCESS_HPP
 | ||||
|  | @ -1,5 +1,5 @@ | |||
| #ifndef THREAD_HPP | ||||
| #define THREAD_HPP | ||||
| #ifndef GUI_THREAD_HPP | ||||
| #define GUI_THREAD_HPP | ||||
| 
 | ||||
| #include <utility> | ||||
| #include <boost/thread.hpp> | ||||
|  | @ -25,4 +25,4 @@ template<class Fn> inline boost::thread create_thread(Fn &&fn) | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| #endif // THREAD_HPP
 | ||||
| #endif // GUI_THREAD_HPP
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vojtech Bubnik
						Vojtech Bubnik