mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-28 19:21:20 -06:00
Merge remote-tracking branch 'origin/master' into tm_colldetection_upgr
This commit is contained in:
commit
5b7a325983
14 changed files with 316 additions and 118 deletions
|
|
@ -487,7 +487,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
|||
// starts analyzer calculations
|
||||
if (m_enable_analyzer) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data);
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||
m_analyzer.reset();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,22 +137,22 @@ const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
|||
return m_process_output;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
// resets preview data
|
||||
preview_data.reset();
|
||||
|
||||
// calculates extrusion layers
|
||||
_calc_gcode_preview_extrusion_layers(preview_data);
|
||||
_calc_gcode_preview_extrusion_layers(preview_data, cancel_callback);
|
||||
|
||||
// calculates travel
|
||||
_calc_gcode_preview_travel(preview_data);
|
||||
_calc_gcode_preview_travel(preview_data, cancel_callback);
|
||||
|
||||
// calculates retractions
|
||||
_calc_gcode_preview_retractions(preview_data);
|
||||
_calc_gcode_preview_retractions(preview_data, cancel_callback);
|
||||
|
||||
// calculates unretractions
|
||||
_calc_gcode_preview_unretractions(preview_data);
|
||||
_calc_gcode_preview_unretractions(preview_data, cancel_callback);
|
||||
}
|
||||
|
||||
bool GCodeAnalyzer::is_valid_extrusion_role(ExtrusionRole role)
|
||||
|
|
@ -676,7 +676,7 @@ bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
|
|||
return ((int)erNone <= value) && (value <= (int)erMixed);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
struct Helper
|
||||
{
|
||||
|
|
@ -725,9 +725,18 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||
GCodePreviewData::Range feedrate_range;
|
||||
GCodePreviewData::Range volumetric_rate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
for (const GCodeMove& move : extrude_moves->second)
|
||||
{
|
||||
// to avoid to call the callback too often
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm))
|
||||
{
|
||||
// store current polyline
|
||||
|
|
@ -769,7 +778,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
|||
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
struct Helper
|
||||
{
|
||||
|
|
@ -797,9 +806,17 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
|||
GCodePreviewData::Range width_range;
|
||||
GCodePreviewData::Range feedrate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
for (const GCodeMove& move : travel_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
GCodePreviewData::Travel::EType move_type = (move.delta_extruder < 0.0f) ? GCodePreviewData::Travel::Retract : ((move.delta_extruder > 0.0f) ? GCodePreviewData::Travel::Extrude : GCodePreviewData::Travel::Move);
|
||||
GCodePreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x() != move.end_position.x()) || (move.start_position.y() != move.end_position.y())) ? GCodePreviewData::Travel::Polyline::Generic : GCodePreviewData::Travel::Polyline::Vertical;
|
||||
|
||||
|
|
@ -840,28 +857,44 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
|||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
TypeToMovesMap::iterator retraction_moves = m_moves_map.find(GCodeMove::Retract);
|
||||
if (retraction_moves == m_moves_map.end())
|
||||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : retraction_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
TypeToMovesMap::iterator unretraction_moves = m_moves_map.find(GCodeMove::Unretract);
|
||||
if (unretraction_moves == m_moves_map.end())
|
||||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25;
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : unretraction_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ public:
|
|||
const std::string& process_gcode(const std::string& gcode);
|
||||
|
||||
// Calculates all data needed for gcode visualization
|
||||
void calc_gcode_preview_data(GCodePreviewData& preview_data);
|
||||
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||
void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback = std::function<void()>());
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t memory_used() const;
|
||||
|
|
@ -237,10 +238,11 @@ private:
|
|||
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
|
||||
bool _is_valid_extrusion_role(int value) const;
|
||||
|
||||
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_travel(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data);
|
||||
// All the following methods throw CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
@ -88,7 +89,7 @@ static DWORD execute_process_winapi(const std::wstring &command_line)
|
|||
// Run the script. If it is a perl script, run it through the bundled perl interpreter.
|
||||
// If it is a batch file, run it through the cmd.exe.
|
||||
// Otherwise run it directly.
|
||||
static int run_script_win32(const std::string &script, const std::string &gcode)
|
||||
static int run_script(const std::string &script, const std::string &gcode, std::string &/*std_err*/)
|
||||
{
|
||||
// Unpack the argument list provided by the user.
|
||||
int nArgs;
|
||||
|
|
@ -132,9 +133,46 @@ static int run_script_win32(const std::string &script, const std::string &gcode)
|
|||
}
|
||||
|
||||
#else
|
||||
#include <sys/stat.h> //for getting filesystem UID/GID
|
||||
#include <unistd.h> //for getting current UID/GID
|
||||
#include <boost/process.hpp>
|
||||
// POSIX
|
||||
|
||||
#include <cstdlib> // getenv()
|
||||
#include <sstream>
|
||||
#include <boost/process.hpp>
|
||||
|
||||
namespace process = boost::process;
|
||||
|
||||
static int run_script(const std::string &script, const std::string &gcode, std::string &std_err)
|
||||
{
|
||||
// Try to obtain user's default shell
|
||||
const char *shell = ::getenv("SHELL");
|
||||
if (shell == nullptr) { shell = "sh"; }
|
||||
|
||||
// Quote and escape the gcode path argument
|
||||
std::string command { script };
|
||||
command.append(" '");
|
||||
for (char c : gcode) {
|
||||
if (c == '\'') { command.append("'\\''"); }
|
||||
else { command.push_back(c); }
|
||||
}
|
||||
command.push_back('\'');
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Executing script, shell: %1%, command: %2%") % shell % command;
|
||||
|
||||
process::ipstream istd_err;
|
||||
process::child child(shell, "-c", command, process::std_err > istd_err);
|
||||
|
||||
std_err.clear();
|
||||
std::string line;
|
||||
|
||||
while (child.running() && std::getline(istd_err, line)) {
|
||||
std_err.append(line);
|
||||
std_err.push_back('\n');
|
||||
}
|
||||
|
||||
child.wait();
|
||||
return child.exit_code();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
|
@ -158,27 +196,15 @@ void run_post_process_scripts(const std::string &path, const PrintConfig &config
|
|||
if (script.empty())
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(info) << "Executing script " << script << " on file " << path;
|
||||
#ifdef WIN32
|
||||
int result = run_script_win32(script, gcode_file.string());
|
||||
#else
|
||||
//FIXME testing existence of a script is risky, as the script line may contain the script and some additional command line parameters.
|
||||
// We would have to process the script line into parameters before testing for the existence of the command, the command may be looked up
|
||||
// in the PATH etc.
|
||||
if (! boost::filesystem::exists(boost::filesystem::path(script)))
|
||||
throw std::runtime_error(std::string("The configured post-processing script does not exist: ") + script);
|
||||
struct stat info;
|
||||
if (stat(script.c_str(), &info))
|
||||
throw std::runtime_error(std::string("Cannot read information for post-processing script: ") + script);
|
||||
boost::filesystem::perms script_perms = boost::filesystem::status(script).permissions();
|
||||
//if UID matches, check UID perm. else if GID matches, check GID perm. Otherwise check other perm.
|
||||
if (!(script_perms & ((info.st_uid == geteuid()) ? boost::filesystem::perms::owner_exe
|
||||
: ((info.st_gid == getegid()) ? boost::filesystem::perms::group_exe
|
||||
: boost::filesystem::perms::others_exe))))
|
||||
throw std::runtime_error(std::string("The configured post-processing script is not executable: check permissions. ") + script);
|
||||
int result = boost::process::system(script, gcode_file);
|
||||
if (result < 0)
|
||||
BOOST_LOG_TRIVIAL(error) << "Script " << script << " on file " << path << " failed. Negative error code returned.";
|
||||
#endif
|
||||
|
||||
std::string std_err;
|
||||
const int result = run_script(script, gcode_file.string(), std_err);
|
||||
if (result != 0) {
|
||||
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
|
||||
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue