Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_world_coordinates

This commit is contained in:
enricoturri1966 2022-02-02 08:11:26 +01:00
commit 3e399f1f98
32 changed files with 311 additions and 107 deletions

View File

@ -33,6 +33,7 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
option(SLIC3R_UBSAN "Enable UBSan on Clang and GCC" 0)
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
@ -239,6 +240,11 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
add_compile_options(-Wno-deprecated-declarations)
endif()
# Clang reports misleading indentation for some IF blocks because of mixing tabs with spaces.
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
add_compile_options(-Wno-misleading-indentation)
endif()
#GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
@ -266,6 +272,32 @@ if (SLIC3R_ASAN)
endif ()
endif ()
if (SLIC3R_UBSAN)
# Stacktrace for every report is enabled by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
# Define macro SLIC3R_UBSAN to allow detection in the source code if this sanitizer is enabled.
add_compile_definitions(SLIC3R_UBSAN)
# Clang supports much more useful checks than GCC, so when Clang is detected, another checks will be enabled.
# List of what GCC is checking: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
# List of what Clang is checking: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(_ubsan_flags "-fsanitize=undefined,integer")
else ()
set(_ubsan_flags "-fsanitize=undefined")
endif ()
add_compile_options(${_ubsan_flags} -fno-omit-frame-pointer)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_ubsan_flags}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${_ubsan_flags}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${_ubsan_flags}")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lubsan")
endif ()
endif ()
if (APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")

View File

@ -120,6 +120,12 @@ set(_build_cmd ${_build_cmd}
set(_install_cmd ${_build_cmd} --prefix=${_prefix} install)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
# Because of that, UndefinedBehaviorSanitizer is disabled for those functions that use __int128.
list(APPEND _patch_command COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/Boost.patch)
endif ()
ExternalProject_Add(
dep_Boost
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"

23
deps/Boost/Boost.patch vendored Normal file
View File

@ -0,0 +1,23 @@
diff -u ../boost_1_75_0-orig/boost/rational.hpp ./boost/rational.hpp
--- ../boost_1_75_0-orig/boost/rational.hpp 2020-12-03 06:02:19.000000000 +0100
+++ ./boost/rational.hpp 2022-01-27 16:02:27.993848905 +0100
@@ -302,6 +302,9 @@
return *this;
}
template <class T>
+ #if defined(__clang__)
+ __attribute__((no_sanitize("undefined")))
+ #endif
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator*= (const T& i)
{
// Avoid overflow and preserve normalization
@@ -311,6 +314,9 @@
return *this;
}
template <class T>
+ #if defined(__clang__)
+ __attribute__((no_sanitize("undefined")))
+ #endif
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator/= (const T& i)
{
// Avoid repeated construction

View File

@ -498,6 +498,7 @@ use_volumetric_e = 0
variable_layer_height = 0
wipe = 0,0
z_offset = 0
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0
default_filament_profile = "Generic PLA @Jubilee; Generic PLA @Jubilee"
default_print_profile = 0.2mm V6, aesthetic @Jubilee

View File

@ -384,7 +384,7 @@ top_solid_infill_speed = 60%
# Common printer preset
[printer:*common*]
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
between_objects_gcode =
color_change_gcode = M600
cooling_tube_length = 5
@ -453,7 +453,7 @@ printer_variant = 0.4
[printer:*vminion-klipper*]
inherits = *common*
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
default_filament_profile = "Generic PLA @RatRig"
default_print_profile = 0.20mm NORMAL V-Minion @RatRig
deretract_speed = 40

View File

@ -168,7 +168,7 @@ default_print_profile = 0.4mm 1.2nozzle
# Common printer preset
[printer:*common*]
printer_technology = FFF
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n
between_objects_gcode =
deretract_speed = 25
end_gcode = print_end ;end script from macro

View File

@ -843,6 +843,15 @@ extern "C" {
}
#endif
#if defined(SLIC3R_UBSAN)
extern "C" {
// Enable printing stacktrace by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
const char *__ubsan_default_options() {
return "print_stacktrace=1";
}
}
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
extern "C" {
__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv)

View File

@ -2391,7 +2391,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
// Probability (unnormalized) of traversing a link between two monotonic regions.
auto path_probability = [
#ifndef __APPLE__
#if !defined(__APPLE__) && !defined(__clang__)
// clang complains when capturing constexpr constants.
pheromone_alpha, pheromone_beta
#endif // __APPLE__

View File

@ -283,25 +283,28 @@ void AMFParserContext::startElement(const char *name, const char **atts)
m_value[0] = type;
node_type_new = NODE_TYPE_METADATA;
}
} else if (strcmp(name, "material") == 0) {
}
else if (strcmp(name, "material") == 0) {
const char *material_id = get_attribute(atts, "id");
m_material = m_model.add_material((material_id == nullptr) ? "_" : material_id);
node_type_new = NODE_TYPE_MATERIAL;
} else if (strcmp(name, "object") == 0) {
}
else if (strcmp(name, "object") == 0) {
const char *object_id = get_attribute(atts, "id");
if (object_id == nullptr)
this->stop();
else {
assert(m_object_vertices.empty());
m_object = m_model.add_object();
m_object->name = std::string(object_id);
m_object_instances_map[object_id].idx = int(m_model.objects.size())-1;
node_type_new = NODE_TYPE_OBJECT;
}
} else if (strcmp(name, "constellation") == 0) {
node_type_new = NODE_TYPE_CONSTELLATION;
} else if (strcmp(name, "custom_gcodes_per_height") == 0) {
node_type_new = NODE_TYPE_CUSTOM_GCODE;
}
else if (strcmp(name, "constellation") == 0)
node_type_new = NODE_TYPE_CONSTELLATION;
else if (strcmp(name, "custom_gcodes_per_height") == 0)
node_type_new = NODE_TYPE_CUSTOM_GCODE;
break;
case 2:
if (strcmp(name, "metadata") == 0) {
@ -309,12 +312,14 @@ void AMFParserContext::startElement(const char *name, const char **atts)
m_value[0] = get_attribute(atts, "type");
node_type_new = NODE_TYPE_METADATA;
}
} else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
}
else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
node_type_new = NODE_TYPE_LAYER_CONFIG;
else if (strcmp(name, "mesh") == 0) {
if (m_path[1] == NODE_TYPE_OBJECT)
node_type_new = NODE_TYPE_MESH;
} else if (strcmp(name, "instance") == 0) {
}
else if (strcmp(name, "instance") == 0) {
if (m_path[1] == NODE_TYPE_CONSTELLATION) {
const char *object_id = get_attribute(atts, "objectid");
if (object_id == nullptr)
@ -910,12 +915,17 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, ConfigSubstitut
if (result)
ctx.endDocument();
for (ModelObject* o : model->objects)
{
for (ModelVolume* v : o->volumes)
{
if (v->source.input_file.empty() && (v->type() == ModelVolumeType::MODEL_PART))
for (ModelObject* o : model->objects) {
unsigned int counter = 0;
for (ModelVolume* v : o->volumes) {
++counter;
if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART)
v->source.input_file = path;
if (v->name.empty()) {
v->name = o->name;
if (o->volumes.size() > 1)
v->name += "_" + std::to_string(counter);
}
}
}

View File

@ -1188,6 +1188,7 @@ void GCodeProcessor::reset()
m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f };
m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f };
m_saved_position = { 0.0f, 0.0f, 0.0f, 0.0f };
m_origin = { 0.0f, 0.0f, 0.0f, 0.0f };
m_cached_position.reset();
m_wiping = false;
@ -1616,6 +1617,13 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
default: break;
}
break;
case '6':
switch (cmd[2]) {
case '0': { process_G60(line); break; } // Save Current Position
case '1': { process_G61(line); break; } // Return to Saved Position
default: break;
}
break;
case '9':
switch (cmd[2]) {
case '0': { process_G90(line); break; } // Set to Absolute Positioning
@ -2828,6 +2836,43 @@ void GCodeProcessor::process_G28(const GCodeReader::GCodeLine& line)
process_G1(new_gline);
}
void GCodeProcessor::process_G60(const GCodeReader::GCodeLine& line)
{
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware)
m_saved_position = m_end_position;
}
void GCodeProcessor::process_G61(const GCodeReader::GCodeLine& line)
{
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) {
bool modified = false;
if (line.has_x()) {
m_end_position[X] = m_saved_position[X];
modified = true;
}
if (line.has_y()) {
m_end_position[Y] = m_saved_position[Y];
modified = true;
}
if (line.has_z()) {
m_end_position[Z] = m_saved_position[Z];
modified = true;
}
if (line.has_e()) {
m_end_position[E] = m_saved_position[E];
modified = true;
}
if (line.has_f())
m_feedrate = line.f();
if (!modified)
m_end_position = m_saved_position;
store_move_vertex(EMoveType::Travel);
}
}
void GCodeProcessor::process_G90(const GCodeReader::GCodeLine& line)
{
m_global_positioning_type = EPositioningType::Absolute;

View File

@ -517,6 +517,7 @@ namespace Slic3r {
AxisCoords m_start_position; // mm
AxisCoords m_end_position; // mm
AxisCoords m_saved_position; // mm
AxisCoords m_origin; // mm
CachedPosition m_cached_position;
bool m_wiping;
@ -661,6 +662,12 @@ namespace Slic3r {
// Move to origin
void process_G28(const GCodeReader::GCodeLine& line);
// Save Current Position
void process_G60(const GCodeReader::GCodeLine& line);
// Return to Saved Position
void process_G61(const GCodeReader::GCodeLine& line);
// Set to Absolute Positioning
void process_G90(const GCodeReader::GCodeLine& line);

View File

@ -105,6 +105,11 @@ public:
static inline Int128 multiply(int64_t lhs, int64_t rhs) { return Int128(__int128(lhs) * __int128(rhs)); }
#if defined(__clang__)
// When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
// Because of that, UndefinedBehaviorSanitizer is disabled for this function.
__attribute__((no_sanitize("undefined")))
#endif
// Evaluate signum of a 2x2 determinant.
static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
{

View File

@ -2264,7 +2264,7 @@ void check_model_ids_validity(const Model &model)
for (const ModelInstance *model_instance : model_object->instances)
check(model_instance->id());
}
for (const auto mm : model.materials) {
for (const auto &mm : model.materials) {
check(mm.second->id());
check(mm.second->config.id());
}

View File

@ -17,7 +17,8 @@ class MultiPoint
public:
Points points;
MultiPoint() {}
MultiPoint() = default;
virtual ~MultiPoint() = default;
MultiPoint(const MultiPoint &other) : points(other.points) {}
MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {}
MultiPoint(std::initializer_list<Point> list) : points(list) {}

View File

@ -19,7 +19,7 @@ class Polygon : public MultiPoint
{
public:
Polygon() = default;
virtual ~Polygon() = default;
~Polygon() override = default;
explicit Polygon(const Points &points) : MultiPoint(points) {}
Polygon(std::initializer_list<Point> points) : MultiPoint(points) {}
Polygon(const Polygon &other) : MultiPoint(other.points) {}

View File

@ -16,7 +16,8 @@ typedef std::vector<ThickPolyline> ThickPolylines;
class Polyline : public MultiPoint {
public:
Polyline() {};
Polyline() = default;
~Polyline() override = default;
Polyline(const Polyline &other) : MultiPoint(other.points) {}
Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {}
Polyline(std::initializer_list<Point> list) : MultiPoint(list) {}

View File

@ -22,6 +22,7 @@
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>
// Mark string for localization and translate.
#define L(s) Slic3r::I18N::translate(s)
@ -438,7 +439,8 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print)
return it == print_instances_ordered.end() || (*it)->print_object->height() <= scale_(print.config().extruder_clearance_height.value);
}
// Matches "G92 E0" with various forms of writing the zero and with an optional comment.
boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" };
// Precondition: Print::validate() requires the Print::apply() to be called its invocation.
std::string Print::validate(std::string* warning) const
@ -652,6 +654,18 @@ std::string Print::validate(std::string* warning) const
return err_msg;
}
}
{
bool before_layer_gcode_resets_extruder = boost::regex_search(m_config.before_layer_gcode.value, regex_g92e0);
bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_gcode.value, regex_g92e0);
if (m_config.use_relative_e_distances) {
// See GH issues #6336 #5073
if (! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder)
return L("Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode.");
} else if (before_layer_gcode_resets_extruder)
return L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing.");
else if (layer_gcode_resets_extruder)
return L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing.");
}
return std::string();
}

View File

@ -26,6 +26,8 @@
#define ENABLE_GCODE_VIEWER_DATA_CHECKING 0
// Enable project dirty state manager debug window
#define ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW 0
// Disable using instanced models to render options in gcode preview
#define DISABLE_GCODEVIEWER_INSTANCED_MODELS 1
// Enable rendering of objects using environment map

View File

@ -78,6 +78,7 @@ extern std::string normalize_utf8_nfc(const char *src);
// Returns next utf8 sequence length. =number of bytes in string, that creates together one utf-8 character.
// Starting at pos. ASCII characters returns 1. Works also if pos is in the middle of the sequence.
extern size_t get_utf8_sequence_length(const std::string& text, size_t pos = 0);
extern size_t get_utf8_sequence_length(const char *seq, size_t size);
// Safely rename a file even if the target exists.
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file

View File

@ -866,8 +866,13 @@ std::string normalize_utf8_nfc(const char *src)
size_t get_utf8_sequence_length(const std::string& text, size_t pos)
{
assert(pos < text.size());
return get_utf8_sequence_length(text.c_str() + pos, text.size() - pos);
}
size_t get_utf8_sequence_length(const char *seq, size_t size)
{
size_t length = 0;
unsigned char c = text[pos];
unsigned char c = seq[0];
if (c < 0x80) { // 0x00-0x7F
// is ASCII letter
length++;
@ -876,8 +881,8 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos)
// pos is in the middle of a utf-8 sequence. Add the utf-8 trailer bytes.
else if (c < 0xC0) { // 0x80-0xBF
length++;
while (pos + length < text.size()) {
c = text[pos + length];
while (length < size) {
c = seq[length];
if (c < 0x80 || c >= 0xC0) {
break; // prevent overrun
}
@ -888,36 +893,36 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos)
// The number of one bits above the topmost zero bit indicates the number of bytes (including this one) in the whole sequence.
else if (c < 0xE0) { // 0xC0-0xDF
// add a utf-8 sequence (2 bytes)
if (pos + 2 > text.size()) {
return text.size() - pos; // prevent overrun
if (2 > size) {
return size; // prevent overrun
}
length += 2;
}
else if (c < 0xF0) { // 0xE0-0xEF
// add a utf-8 sequence (3 bytes)
if (pos + 3 > text.size()) {
return text.size() - pos; // prevent overrun
if (3 > size) {
return size; // prevent overrun
}
length += 3;
}
else if (c < 0xF8) { // 0xF0-0xF7
// add a utf-8 sequence (4 bytes)
if (pos + 4 > text.size()) {
return text.size() - pos; // prevent overrun
if (4 > size) {
return size; // prevent overrun
}
length += 4;
}
else if (c < 0xFC) { // 0xF8-0xFB
// add a utf-8 sequence (5 bytes)
if (pos + 5 > text.size()) {
return text.size() - pos; // prevent overrun
if (5 > size) {
return size; // prevent overrun
}
length += 5;
}
else if (c < 0xFE) { // 0xFC-0xFD
// add a utf-8 sequence (6 bytes)
if (pos + 6 > text.size()) {
return text.size() - pos; // prevent overrun
if (6 > size) {
return size; // prevent overrun
}
length += 6;
}

View File

@ -654,7 +654,7 @@ void FirmwareDialog::priv::perform_upload()
}
})
.on_message([
#ifndef __APPLE__
#if !defined(__APPLE__) && !defined(__clang__)
// clang complains when capturing constants.
extra_verbose,
#endif // __APPLE__

View File

@ -584,14 +584,16 @@ void GCodeViewer::init()
case EMoveType::Retract:
case EMoveType::Unretract:
case EMoveType::Seam: {
// if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
// buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel;
// buffer.shader = "gouraud_light_instanced";
// buffer.model.model.init_from(diamond(16));
// buffer.model.color = option_color(type);
// buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel;
// }
// else {
#if !DISABLE_GCODEVIEWER_INSTANCED_MODELS
if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel;
buffer.shader = "gouraud_light_instanced";
buffer.model.model.init_from(diamond(16));
buffer.model.color = option_color(type);
buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel;
}
else {
#endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
buffer.shader = "gouraud_light";
@ -599,8 +601,10 @@ void GCodeViewer::init()
buffer.model.data = diamond(16);
buffer.model.color = option_color(type);
buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel;
// }
break;
#if !DISABLE_GCODEVIEWER_INSTANCED_MODELS
}
#endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS
break;
}
case EMoveType::Wipe:
case EMoveType::Extrude: {

View File

@ -871,8 +871,8 @@ void GUI_App::init_app_config()
{
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
// SetAppName(SLIC3R_APP_KEY);
SetAppName(SLIC3R_APP_KEY "-alpha");
// SetAppName(SLIC3R_APP_KEY "-beta");
// SetAppName(SLIC3R_APP_KEY "-alpha");
SetAppName(SLIC3R_APP_KEY "-beta");
// SetAppDisplayName(SLIC3R_APP_NAME);
// Set the Slic3r data directory at the Slic3r XS module.

View File

@ -239,7 +239,8 @@ ObjectList::ObjectList(wxWindow* parent) :
ObjectList::~ObjectList()
{
delete m_objects_model;
if (m_objects_model)
m_objects_model->DecRef();
}
void ObjectList::set_min_height()

View File

@ -292,42 +292,58 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString&
finalize();
}
wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/)
wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
{
#ifdef __WXMSW__
char slash = '\\';
#else
char slash = '/';
#endif
char space = ' ';
char new_line = '\n';
wxString out;
wxString text = text_in;
int idx = -1;
size_t cur_len = 0;
size_t text_len = text.Len();
for (size_t i = 0; i < text_len; i++) {
cur_len++;
if (text[i] == space || text[i] == slash)
idx = i;
if (text[i] == new_line) {
idx = -1;
cur_len = 0;
continue;
for (size_t i = 0; i < in.size();) {
// Overwrite the character (space or newline) starting at ibreak?
bool overwrite = false;
#if wxUSE_UNICODE_WCHAR
// On Windows, most likely the internal representation of wxString is wide char.
size_t end = std::min(in.size(), i + line_len);
size_t ibreak = end;
for (size_t j = i; j < end; ++ j) {
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
ibreak = j;
overwrite = true;
if (newline)
break;
} else if (in[j] == '/' || in[j] == '\\')
ibreak = j + 1;
}
if (cur_len >= line_len && idx >= 0) {
if (text[idx] == slash) {
text.insert(static_cast<size_t>(idx) + 1, 1, new_line);
text_len++;
#else
// UTF8 representation of wxString.
// Where to break the line, index of character at the start of a UTF-8 sequence.
size_t ibreak = size_t(-1);
// Overwrite the character at ibreak (it is a whitespace) or not?
for (size_t cnt = 0, j = i; j < in.size();) {
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
// Overwrite the whitespace.
ibreak = j ++;
overwrite = true;
if (newline)
break;
} else if (in[j] == '/') {
// Insert after the slash.
ibreak = ++ j;
} else
j += get_utf8_sequence_length(in.c_str() + j, in.size() - j);
if (++ cnt == line_len) {
if (ibreak == size_t(-1))
ibreak = j;
break;
}
else // space
text[idx] = new_line;
cur_len = i - static_cast<size_t>(idx);
}
#endif
out.append(in.begin() + i, in.begin() + ibreak);
out.append('\n');
i = ibreak;
if (overwrite)
++ i;
}
return text;
return out;
}
}

View File

@ -185,7 +185,7 @@ public:
OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
column_t extra_clmn = nullptr);
~OptionsGroup() { clear(true); }
virtual ~OptionsGroup() { clear(true); }
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
const std::vector<Line>& get_lines() { return m_lines; }
@ -253,6 +253,7 @@ public:
OptionsGroup(parent, title, is_tab_opt, extra_clmn), m_config(&config->get()), m_modelconfig(config) {}
ConfigOptionsGroup( wxWindow* parent) :
OptionsGroup(parent, wxEmptyString, true, nullptr) {}
~ConfigOptionsGroup() override = default;
const wxString& config_category() const throw() { return m_config_category; }
int config_type() const throw() { return m_config_type; }

View File

@ -2594,8 +2594,13 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
for (ModelObject* model_object : model.objects) {
if (!type_3mf && !type_zip_amf)
if (!type_3mf && !type_zip_amf) {
model_object->center_around_origin(false);
if (type_any_amf && model_object->instances.empty()) {
ModelInstance* instance = model_object->add_instance();
instance->set_offset(-model_object->origin_translation);
}
}
model_object->ensure_on_bed(is_project_file);
}
@ -2611,7 +2616,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
if (one_by_one) {
if (type_3mf && !is_project_file)
if ((type_3mf && !is_project_file) || (type_any_amf && !type_zip_amf))
model.center_instances_around_point(this->bed.build_volume().bed_center());
auto loaded_idxs = load_model_objects(model.objects, is_project_file);
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
@ -3694,12 +3699,20 @@ void Plater::priv::reload_from_disk()
if (has_source || has_name) {
int new_volume_idx = -1;
int new_object_idx = -1;
// if (has_source) {
// // take idxs from source
// new_volume_idx = old_volume->source.volume_idx;
// new_object_idx = old_volume->source.object_idx;
// }
// else {
bool match_found = false;
// take idxs from the matching volume
if (has_source && old_volume->source.object_idx < int(new_model.objects.size())) {
const ModelObject* obj = new_model.objects[old_volume->source.object_idx];
if (old_volume->source.volume_idx < int(obj->volumes.size())) {
if (obj->volumes[old_volume->source.volume_idx]->name == old_volume->name) {
new_volume_idx = old_volume->source.volume_idx;
new_object_idx = old_volume->source.object_idx;
match_found = true;
}
}
}
if (!match_found && has_name) {
// take idxs from the 1st matching volume
for (size_t o = 0; o < new_model.objects.size(); ++o) {
ModelObject* obj = new_model.objects[o];
@ -3715,7 +3728,7 @@ void Plater::priv::reload_from_disk()
if (found)
break;
}
// }
}
if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) {
fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));

View File

@ -1647,18 +1647,6 @@ void TabPrint::build()
option.opt.full_width = true;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Post-processing scripts"), 0);
line = { "", "" };
line.full_width = 1;
line.widget = [this](wxWindow* parent) {
return description_line_widget(parent, &m_post_process_explanation);
};
optgroup->append_line(line);
option = optgroup->get_option("post_process");
option.opt.full_width = true;
option.opt.height = 5;//50;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Other"));
create_line_with_widget(optgroup.get(), "gcode_substitutions", "g-code-substitutions_301694", [this](wxWindow* parent) {
@ -1671,6 +1659,18 @@ void TabPrint::build()
};
optgroup->append_line(line);
optgroup = page->new_optgroup(L("Post-processing scripts"), 0);
line = { "", "" };
line.full_width = 1;
line.widget = [this](wxWindow* parent) {
return description_line_widget(parent, &m_post_process_explanation);
};
optgroup->append_line(line);
option = optgroup->get_option("post_process");
option.opt.full_width = true;
option.opt.height = 5;//50;
optgroup->append_single_option_line(option);
page = add_options_page(L("Notes"), "note.png");
optgroup = page->new_optgroup(L("Notes"), 0);
option = optgroup->get_option("notes");
@ -3967,7 +3967,7 @@ void SubstitutionManager::add_substitution( int substitution_id,
editor->SetFont(wxGetApp().normal_font());
wxGetApp().UpdateDarkUI(editor);
top_sizer->Add(editor, proportion, wxALIGN_CENTER_VERTICAL | wxEXPAND| wxRIGHT, m_em);
top_sizer->Add(editor, proportion, wxALIGN_CENTER_VERTICAL | wxRIGHT, m_em);
editor->Bind(wxEVT_TEXT_ENTER, [this, editor, substitution_id, opt_pos](wxEvent& e) {
#if !defined(__WXGTK__)
@ -4032,7 +4032,7 @@ void SubstitutionManager::add_substitution( int substitution_id,
auto v_sizer = new wxBoxSizer(wxVERTICAL);
v_sizer->Add(top_sizer, 1, wxEXPAND);
v_sizer->Add(params_sizer, 1, wxEXPAND|wxTOP|wxBOTTOM, int(0.5* m_em));
m_grid_sizer->Add(v_sizer, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND);
m_grid_sizer->Add(v_sizer, 1, wxEXPAND);
if (call_after_layout) {
m_parent->GetParent()->Layout();

View File

@ -1158,10 +1158,11 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
}
if (opt_key == "gcode_substitutions") {
if (!strings->empty())
for (size_t id = 0; id < strings->size(); id += 3)
for (size_t id = 0; id < strings->size(); id += 4)
out += from_u8(strings->get_at(id)) + ";\t" +
from_u8(strings->get_at(id + 1)) + ";\t" +
from_u8(strings->get_at(id + 2)) + ";\n";
from_u8(strings->get_at(id + 2)) + ";\t" +
from_u8(strings->get_at(id + 3)) + ";\n";
return out;
}
if (!strings->empty() && opt_idx < strings->values.size())

View File

@ -204,7 +204,12 @@ class DiffViewCtrl : public wxDataViewCtrl
public:
DiffViewCtrl(wxWindow* parent, wxSize size);
~DiffViewCtrl() override { Clear(); delete model; }
~DiffViewCtrl() override {
if (model) {
Clear();
model->DecRef();
}
}
DiffModel* model{ nullptr };

View File

@ -133,6 +133,7 @@ use Slic3r::Test;
my $config = Slic3r::Config::new_from_defaults;
$config->set('retract_length', [1000000]);
$config->set('use_relative_e_distances', 1);
$config->set('layer_gcode', "G92 E0\n");
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
Slic3r::Test::gcode($print);
ok $print->print->total_used_filament > 0, 'final retraction is not considered in total used filament';

View File

@ -3,7 +3,7 @@
set(SLIC3R_APP_NAME "PrusaSlicer")
set(SLIC3R_APP_KEY "PrusaSlicer")
set(SLIC3R_VERSION "2.4.1-alpha0")
set(SLIC3R_VERSION "2.4.1-beta1")
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
set(SLIC3R_RC_VERSION "2,4,1,0")
set(SLIC3R_RC_VERSION_DOTS "2.4.1.0")