mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-03 00:20:39 +08:00
Merge branch 'master' into fs_undoredo
This commit is contained in:
commit
cc9a3a473e
@ -37,6 +37,7 @@ std::pair<double, double> Extruder::extrude(double dE)
|
|||||||
value supplied will overwrite the previous one if any. */
|
value supplied will overwrite the previous one if any. */
|
||||||
std::pair<double, double> Extruder::retract(double retract_length, double restart_extra)
|
std::pair<double, double> Extruder::retract(double retract_length, double restart_extra)
|
||||||
{
|
{
|
||||||
|
assert(restart_extra >= 0);
|
||||||
// in case of relative E distances we always reset to 0 before any output
|
// in case of relative E distances we always reset to 0 before any output
|
||||||
if (m_config->use_relative_e_distances)
|
if (m_config->use_relative_e_distances)
|
||||||
m_E = 0.;
|
m_E = 0.;
|
||||||
@ -64,6 +65,24 @@ std::pair<double, double> Extruder::unretract()
|
|||||||
return std::make_pair(dE, emitE);
|
return std::make_pair(dE, emitE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setting the retract state from the script.
|
||||||
|
// Sets current retraction value & restart extra filament amount if retracted > 0.
|
||||||
|
void Extruder::set_retracted(double retracted, double restart_extra)
|
||||||
|
{
|
||||||
|
if (retracted < - EPSILON)
|
||||||
|
throw Slic3r::RuntimeError("Custom G-code reports negative z_retracted.");
|
||||||
|
if (restart_extra < - EPSILON)
|
||||||
|
throw Slic3r::RuntimeError("Custom G-code reports negative z_restart_extra.");
|
||||||
|
|
||||||
|
if (retracted > EPSILON) {
|
||||||
|
m_retracted = retracted;
|
||||||
|
m_restart_extra = restart_extra < EPSILON ? 0 : restart_extra;
|
||||||
|
} else {
|
||||||
|
m_retracted = 0;
|
||||||
|
m_restart_extra = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Used filament volume in mm^3.
|
// Used filament volume in mm^3.
|
||||||
double Extruder::extruded_volume() const
|
double Extruder::extruded_volume() const
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,19 @@ public:
|
|||||||
double extruded_volume() const;
|
double extruded_volume() const;
|
||||||
// Used filament length in mm.
|
// Used filament length in mm.
|
||||||
double used_filament() const;
|
double used_filament() const;
|
||||||
|
|
||||||
|
// Getters for the PlaceholderParser.
|
||||||
|
// Get current extruder position. Only applicable with absolute extruder addressing.
|
||||||
|
double position() const { return m_E; }
|
||||||
|
// Get current retraction value. Only non-negative values.
|
||||||
|
double retracted() const { return m_retracted; }
|
||||||
|
// Get extra retraction planned after
|
||||||
|
double restart_extra() const { return m_restart_extra; }
|
||||||
|
// Setters for the PlaceholderParser.
|
||||||
|
// Set current extruder position. Only applicable with absolute extruder addressing.
|
||||||
|
void set_position(double e) { m_E = e; }
|
||||||
|
// Sets current retraction value & restart extra filament amount if retracted > 0.
|
||||||
|
void set_retracted(double retracted, double restart_extra);
|
||||||
|
|
||||||
double filament_diameter() const;
|
double filament_diameter() const;
|
||||||
double filament_crossection() const { return this->filament_diameter() * this->filament_diameter() * 0.25 * PI; }
|
double filament_crossection() const { return this->filament_diameter() * this->filament_diameter() * 0.25 * PI; }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "ExtrusionRole.hpp"
|
#include "ExtrusionRole.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "SLAArchiveReader.hpp"
|
#include "SLAArchiveReader.hpp"
|
||||||
#include "SL1.hpp"
|
#include "SL1.hpp"
|
||||||
#include "SL1_SVG.hpp"
|
#include "SL1_SVG.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
#include "libslic3r/SlicesToTriangleMesh.hpp"
|
#include "libslic3r/SlicesToTriangleMesh.hpp"
|
||||||
|
|
||||||
@ -36,8 +37,8 @@ static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
|
|||||||
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1Reader>(fname, quality, progr); } }
|
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1Reader>(fname, quality, progr); } }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SL2",
|
"SL1SVG",
|
||||||
{ L("SL2 archive files"), {"sl2", "sl1_svg"/*, "zip"*/}, // also a zip but unnecessary hassle to implement single extension for multiple archives
|
{ L("SL1SVG archive files"), {"sl1_svg"/*, "zip"*/}, // also a zip but unnecessary hassle to implement single extension for multiple archives
|
||||||
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1_SVGReader>(fname, quality, progr); }}
|
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1_SVGReader>(fname, quality, progr); }}
|
||||||
},
|
},
|
||||||
// TODO: pwmx and future others.
|
// TODO: pwmx and future others.
|
||||||
|
@ -25,9 +25,13 @@ static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
|
|||||||
"SL1",
|
"SL1",
|
||||||
{ "sl1", [] (const auto &cfg) { return std::make_unique<SL1Archive>(cfg); } }
|
{ "sl1", [] (const auto &cfg) { return std::make_unique<SL1Archive>(cfg); } }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"SL1SVG",
|
||||||
|
{ "sl1_svg", [] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); } }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"SL2",
|
"SL2",
|
||||||
{ "sl2", [] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); } }
|
{ "sl1_svg", [] (const auto &cfg) { return std::make_unique<SL1_SVGArchive>(cfg); } }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pwmx",
|
"pwmx",
|
||||||
|
@ -419,7 +419,7 @@ namespace Slic3r {
|
|||||||
std::string WipeTowerIntegration::finalize(GCode& gcodegen)
|
std::string WipeTowerIntegration::finalize(GCode& gcodegen)
|
||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
if (std::abs(gcodegen.writer().get_position()(2) - m_final_purge.print_z) > EPSILON)
|
if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON)
|
||||||
gcode += gcodegen.change_layer(m_final_purge.print_z);
|
gcode += gcodegen.change_layer(m_final_purge.print_z);
|
||||||
gcode += append_tcr(gcodegen, m_final_purge, -1);
|
gcode += append_tcr(gcodegen, m_final_purge, -1);
|
||||||
return gcode;
|
return gcode;
|
||||||
@ -429,6 +429,90 @@ namespace Slic3r {
|
|||||||
|
|
||||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
|
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
|
||||||
|
|
||||||
|
void GCode::PlaceholderParserIntegration::reset()
|
||||||
|
{
|
||||||
|
this->failed_templates.clear();
|
||||||
|
this->output_config.clear();
|
||||||
|
this->opt_position = nullptr;
|
||||||
|
this->opt_zhop = nullptr;
|
||||||
|
this->opt_e_position = nullptr;
|
||||||
|
this->opt_e_retracted = nullptr;
|
||||||
|
this->opt_e_restart_extra = nullptr;
|
||||||
|
this->num_extruders = 0;
|
||||||
|
this->position.clear();
|
||||||
|
this->e_position.clear();
|
||||||
|
this->e_retracted.clear();
|
||||||
|
this->e_restart_extra.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCode::PlaceholderParserIntegration::init(const GCodeWriter &writer)
|
||||||
|
{
|
||||||
|
this->reset();
|
||||||
|
const std::vector<Extruder> &extruders = writer.extruders();
|
||||||
|
if (! extruders.empty()) {
|
||||||
|
this->num_extruders = extruders.back().id() + 1;
|
||||||
|
this->e_retracted.assign(num_extruders, 0);
|
||||||
|
this->e_restart_extra.assign(num_extruders, 0);
|
||||||
|
this->opt_e_retracted = new ConfigOptionFloats(e_retracted);
|
||||||
|
this->opt_e_restart_extra = new ConfigOptionFloats(e_restart_extra);
|
||||||
|
this->output_config.set_key_value("e_retracted", this->opt_e_retracted);
|
||||||
|
this->output_config.set_key_value("e_restart_extra", this->opt_e_restart_extra);
|
||||||
|
if (! writer.config.use_relative_e_distances) {
|
||||||
|
e_position.assign(num_extruders, 0);
|
||||||
|
opt_e_position = new ConfigOptionFloats(e_position);
|
||||||
|
this->output_config.set_key_value("e_position", opt_e_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve buffer for current position.
|
||||||
|
this->position.assign(3, 0);
|
||||||
|
this->opt_position = new ConfigOptionFloats(this->position);
|
||||||
|
// Store zhop variable into the parser itself, it is a read-only variable to the script.
|
||||||
|
this->opt_zhop = new ConfigOptionFloat(writer.get_zhop());
|
||||||
|
this->parser.set("zhop", this->opt_zhop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCode::PlaceholderParserIntegration::update_from_gcodewriter(const GCodeWriter &writer)
|
||||||
|
{
|
||||||
|
memcpy(this->position.data(), writer.get_position().data(), sizeof(double) * 3);
|
||||||
|
this->opt_position->values = this->position;
|
||||||
|
this->opt_zhop->value = writer.get_zhop();
|
||||||
|
|
||||||
|
if (this->num_extruders > 0) {
|
||||||
|
const std::vector<Extruder> &extruders = writer.extruders();
|
||||||
|
assert(! extruders.empty() && num_extruders == extruders.back().id() + 1);
|
||||||
|
this->e_retracted.assign(num_extruders, 0);
|
||||||
|
this->e_restart_extra.assign(num_extruders, 0);
|
||||||
|
for (const Extruder &e : extruders) {
|
||||||
|
this->e_retracted[e.id()] = e.retracted();
|
||||||
|
this->e_restart_extra[e.id()] = e.restart_extra();
|
||||||
|
}
|
||||||
|
opt_e_retracted->values = this->e_retracted;
|
||||||
|
opt_e_restart_extra->values = this->e_restart_extra;
|
||||||
|
if (! writer.config.use_relative_e_distances) {
|
||||||
|
this->e_position.assign(num_extruders, 0);
|
||||||
|
for (const Extruder &e : extruders)
|
||||||
|
this->e_position[e.id()] = e.position();
|
||||||
|
this->opt_e_position->values = this->e_position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw if any of the output vector variables were resized by the script.
|
||||||
|
void GCode::PlaceholderParserIntegration::validate_output_vector_variables()
|
||||||
|
{
|
||||||
|
if (this->opt_position->values.size() != 3)
|
||||||
|
throw Slic3r::RuntimeError("\"position\" output variable must not be resized by the script.");
|
||||||
|
if (this->num_extruders > 0) {
|
||||||
|
if (this->opt_e_position && this->opt_e_position->values.size() != this->num_extruders)
|
||||||
|
throw Slic3r::RuntimeError("\"e_position\" output variable must not be resized by the script.");
|
||||||
|
if (this->opt_e_retracted->values.size() != this->num_extruders)
|
||||||
|
throw Slic3r::RuntimeError("\"e_retracted\" output variable must not be resized by the script.");
|
||||||
|
if (this->opt_e_restart_extra->values.size() != this->num_extruders)
|
||||||
|
throw Slic3r::RuntimeError("\"e_restart_extra\" output variable must not be resized by the script.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect pairs of object_layer + support_layer sorted by print_z.
|
// Collect pairs of object_layer + support_layer sorted by print_z.
|
||||||
// object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON.
|
// object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON.
|
||||||
GCode::ObjectsLayerToPrint GCode::collect_layers_to_print(const PrintObject& object)
|
GCode::ObjectsLayerToPrint GCode::collect_layers_to_print(const PrintObject& object)
|
||||||
@ -728,7 +812,6 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||||||
throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_placeholder_parser_failed_templates.clear();
|
|
||||||
this->_do_export(*print, file, thumbnail_cb);
|
this->_do_export(*print, file, thumbnail_cb);
|
||||||
file.flush();
|
file.flush();
|
||||||
if (file.is_error()) {
|
if (file.is_error()) {
|
||||||
@ -745,11 +828,11 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
if (! m_placeholder_parser_failed_templates.empty()) {
|
if (! m_placeholder_parser_integration.failed_templates.empty()) {
|
||||||
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
||||||
//FIXME localize!
|
//FIXME localize!
|
||||||
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
||||||
for (const auto &name_and_error : m_placeholder_parser_failed_templates)
|
for (const auto &name_and_error : m_placeholder_parser_integration.failed_templates)
|
||||||
msg += name_and_error.first + "\n" + name_and_error.second + "\n";
|
msg += name_and_error.first + "\n" + name_and_error.second + "\n";
|
||||||
msg += "\nPlease inspect the file ";
|
msg += "\nPlease inspect the file ";
|
||||||
msg += path_tmp + " for error messages enclosed between\n";
|
msg += path_tmp + " for error messages enclosed between\n";
|
||||||
@ -1078,12 +1161,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
file.find_replace_enable();
|
file.find_replace_enable();
|
||||||
|
|
||||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||||
m_placeholder_parser = print.placeholder_parser();
|
m_placeholder_parser_integration.parser = print.placeholder_parser();
|
||||||
m_placeholder_parser.update_timestamp();
|
m_placeholder_parser_integration.parser.update_timestamp();
|
||||||
m_placeholder_parser_context.rng = std::mt19937(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
m_placeholder_parser_integration.context.rng = std::mt19937(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||||
// Enable passing global variables between PlaceholderParser invocations.
|
// Enable passing global variables between PlaceholderParser invocations.
|
||||||
m_placeholder_parser_context.global_config = std::make_unique<DynamicConfig>();
|
m_placeholder_parser_integration.context.global_config = std::make_unique<DynamicConfig>();
|
||||||
print.update_object_placeholders(m_placeholder_parser.config_writable(), ".gcode");
|
print.update_object_placeholders(m_placeholder_parser_integration.parser.config_writable(), ".gcode");
|
||||||
|
|
||||||
// Get optimal tool ordering to minimize tool switches of a multi-exruder print.
|
// Get optimal tool ordering to minimize tool switches of a multi-exruder print.
|
||||||
// For a print by objects, find the 1st printing object.
|
// For a print by objects, find the 1st printing object.
|
||||||
@ -1147,23 +1230,25 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
// Emit machine envelope limits for the Marlin firmware.
|
// Emit machine envelope limits for the Marlin firmware.
|
||||||
this->print_machine_envelope(file, print);
|
this->print_machine_envelope(file, print);
|
||||||
|
|
||||||
|
// Update output variables after the extruders were initialized.
|
||||||
|
m_placeholder_parser_integration.init(m_writer);
|
||||||
// Let the start-up script prime the 1st printing tool.
|
// Let the start-up script prime the 1st printing tool.
|
||||||
m_placeholder_parser.set("initial_tool", initial_extruder_id);
|
this->placeholder_parser().set("initial_tool", initial_extruder_id);
|
||||||
m_placeholder_parser.set("initial_extruder", initial_extruder_id);
|
this->placeholder_parser().set("initial_extruder", initial_extruder_id);
|
||||||
m_placeholder_parser.set("current_extruder", initial_extruder_id);
|
this->placeholder_parser().set("current_extruder", initial_extruder_id);
|
||||||
//Set variable for total layer count so it can be used in custom gcode.
|
//Set variable for total layer count so it can be used in custom gcode.
|
||||||
m_placeholder_parser.set("total_layer_count", m_layer_count);
|
this->placeholder_parser().set("total_layer_count", m_layer_count);
|
||||||
// Useful for sequential prints.
|
// Useful for sequential prints.
|
||||||
m_placeholder_parser.set("current_object_idx", 0);
|
this->placeholder_parser().set("current_object_idx", 0);
|
||||||
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
||||||
m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
|
this->placeholder_parser().set("has_wipe_tower", has_wipe_tower);
|
||||||
m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
this->placeholder_parser().set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
||||||
m_placeholder_parser.set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
|
this->placeholder_parser().set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
|
||||||
{
|
{
|
||||||
BoundingBoxf bbox(print.config().bed_shape.values);
|
BoundingBoxf bbox(print.config().bed_shape.values);
|
||||||
m_placeholder_parser.set("print_bed_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
|
this->placeholder_parser().set("print_bed_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
|
||||||
m_placeholder_parser.set("print_bed_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
this->placeholder_parser().set("print_bed_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
||||||
m_placeholder_parser.set("print_bed_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
this->placeholder_parser().set("print_bed_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
|
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
|
||||||
@ -1176,15 +1261,15 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
for (const Point &pt : print.first_layer_convex_hull().points)
|
for (const Point &pt : print.first_layer_convex_hull().points)
|
||||||
pts->values.emplace_back(unscale(pt));
|
pts->values.emplace_back(unscale(pt));
|
||||||
BoundingBoxf bbox(pts->values);
|
BoundingBoxf bbox(pts->values);
|
||||||
m_placeholder_parser.set("first_layer_print_convex_hull", pts.release());
|
this->placeholder_parser().set("first_layer_print_convex_hull", pts.release());
|
||||||
m_placeholder_parser.set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
|
this->placeholder_parser().set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
|
||||||
m_placeholder_parser.set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
this->placeholder_parser().set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
||||||
m_placeholder_parser.set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
this->placeholder_parser().set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
||||||
|
|
||||||
std::vector<unsigned char> is_extruder_used(print.config().nozzle_diameter.size(), 0);
|
std::vector<unsigned char> is_extruder_used(print.config().nozzle_diameter.size(), 0);
|
||||||
for (unsigned int extruder_id : tool_ordering.all_extruders())
|
for (unsigned int extruder_id : tool_ordering.all_extruders())
|
||||||
is_extruder_used[extruder_id] = true;
|
is_extruder_used[extruder_id] = true;
|
||||||
m_placeholder_parser.set("is_extruder_used", new ConfigOptionBools(is_extruder_used));
|
this->placeholder_parser().set("is_extruder_used", new ConfigOptionBools(is_extruder_used));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable ooze prevention if configured so.
|
// Enable ooze prevention if configured so.
|
||||||
@ -1251,7 +1336,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
// Ff we are printing the bottom layer of an object, and we have already finished
|
// Ff we are printing the bottom layer of an object, and we have already finished
|
||||||
// another one, set first layer temperatures. This happens before the Z move
|
// another one, set first layer temperatures. This happens before the Z move
|
||||||
// is triggered, so machine has more time to reach such temperatures.
|
// is triggered, so machine has more time to reach such temperatures.
|
||||||
m_placeholder_parser.set("current_object_idx", int(finished_objects));
|
this->placeholder_parser().set("current_object_idx", int(finished_objects));
|
||||||
std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id);
|
std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id);
|
||||||
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
||||||
this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false);
|
this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false);
|
||||||
@ -1337,7 +1422,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
{
|
{
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||||
config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
|
config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position().z() - m_config.z_offset.value));
|
||||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||||
if (print.config().single_extruder_multi_material) {
|
if (print.config().single_extruder_multi_material) {
|
||||||
// Process the end_filament_gcode for the active filament only.
|
// Process the end_filament_gcode for the active filament only.
|
||||||
@ -1560,17 +1645,46 @@ void GCode::process_layers(
|
|||||||
output_stream.find_replace_enable();
|
output_stream.find_replace_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)
|
std::string GCode::placeholder_parser_process(
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &templ,
|
||||||
|
unsigned int current_extruder_id,
|
||||||
|
const DynamicConfig *config_override)
|
||||||
{
|
{
|
||||||
|
PlaceholderParserIntegration &ppi = m_placeholder_parser_integration;
|
||||||
try {
|
try {
|
||||||
return m_placeholder_parser.process(templ, current_extruder_id, config_override, &m_placeholder_parser_context);
|
ppi.update_from_gcodewriter(m_writer);
|
||||||
} catch (std::runtime_error &err) {
|
std::string output = ppi.parser.process(templ, current_extruder_id, config_override, &ppi.output_config, &ppi.context);
|
||||||
|
ppi.validate_output_vector_variables();
|
||||||
|
|
||||||
|
if (const std::vector<double> &pos = ppi.opt_position->values; ppi.position != pos) {
|
||||||
|
// Update G-code writer.
|
||||||
|
m_writer.update_position({ pos[0], pos[1], pos[2] });
|
||||||
|
this->set_last_pos(this->gcode_to_point({ pos[0], pos[1] }));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Extruder &e : m_writer.extruders()) {
|
||||||
|
unsigned int eid = e.id();
|
||||||
|
assert(eid < ppi.num_extruders);
|
||||||
|
if ( eid < ppi.num_extruders) {
|
||||||
|
if (! m_writer.config.use_relative_e_distances && ! is_approx(ppi.e_position[eid], ppi.opt_e_position->values[eid]))
|
||||||
|
const_cast<Extruder&>(e).set_position(ppi.opt_e_position->values[eid]);
|
||||||
|
if (! is_approx(ppi.e_retracted[eid], ppi.opt_e_retracted->values[eid]) ||
|
||||||
|
! is_approx(ppi.e_restart_extra[eid], ppi.opt_e_restart_extra->values[eid]))
|
||||||
|
const_cast<Extruder&>(e).set_retracted(ppi.opt_e_retracted->values[eid], ppi.opt_e_restart_extra->values[eid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
catch (std::runtime_error &err)
|
||||||
|
{
|
||||||
// Collect the names of failed template substitutions for error reporting.
|
// Collect the names of failed template substitutions for error reporting.
|
||||||
auto it = m_placeholder_parser_failed_templates.find(name);
|
auto it = ppi.failed_templates.find(name);
|
||||||
if (it == m_placeholder_parser_failed_templates.end())
|
if (it == ppi.failed_templates.end())
|
||||||
// Only if there was no error reported for this template, store the first error message into the map to be reported.
|
// Only if there was no error reported for this template, store the first error message into the map to be reported.
|
||||||
// We don't want to collect error message for each and every occurence of a single custom G-code section.
|
// We don't want to collect error message for each and every occurence of a single custom G-code section.
|
||||||
m_placeholder_parser_failed_templates.insert(it, std::make_pair(name, std::string(err.what())));
|
ppi.failed_templates.insert(it, std::make_pair(name, std::string(err.what())));
|
||||||
// Insert the macro error message into the G-code.
|
// Insert the macro error message into the G-code.
|
||||||
return
|
return
|
||||||
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
||||||
@ -3160,7 +3274,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||||||
|
|
||||||
// if we are running a single-extruder setup, just set the extruder and return nothing
|
// if we are running a single-extruder setup, just set the extruder and return nothing
|
||||||
if (!m_writer.multiple_extruders) {
|
if (!m_writer.multiple_extruders) {
|
||||||
m_placeholder_parser.set("current_extruder", extruder_id);
|
this->placeholder_parser().set("current_extruder", extruder_id);
|
||||||
|
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
// Append the filament start G-code.
|
// Append the filament start G-code.
|
||||||
@ -3169,7 +3283,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||||||
// Process the start_filament_gcode for the filament.
|
// Process the start_filament_gcode for the filament.
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||||
config.set_key_value("layer_z", new ConfigOptionFloat(this->writer().get_position()(2) - m_config.z_offset.value));
|
config.set_key_value("layer_z", new ConfigOptionFloat(this->writer().get_position().z() - m_config.z_offset.value));
|
||||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||||
config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(extruder_id)));
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(extruder_id)));
|
||||||
gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id, &config);
|
gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id, &config);
|
||||||
@ -3233,7 +3347,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||||||
gcode += m_writer.set_temperature(temp, false);
|
gcode += m_writer.set_temperature(temp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_placeholder_parser.set("current_extruder", extruder_id);
|
this->placeholder_parser().set("current_extruder", extruder_id);
|
||||||
|
|
||||||
// Append the filament start G-code.
|
// Append the filament start G-code.
|
||||||
const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id);
|
const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id);
|
||||||
@ -3241,7 +3355,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||||||
// Process the start_filament_gcode for the new filament.
|
// Process the start_filament_gcode for the new filament.
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||||
config.set_key_value("layer_z", new ConfigOptionFloat(this->writer().get_position()(2) - m_config.z_offset.value));
|
config.set_key_value("layer_z", new ConfigOptionFloat(this->writer().get_position().z() - m_config.z_offset.value));
|
||||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||||
config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(extruder_id)));
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(extruder_id)));
|
||||||
gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id, &config);
|
gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id, &config);
|
||||||
|
@ -173,8 +173,8 @@ public:
|
|||||||
const Layer* layer() const { return m_layer; }
|
const Layer* layer() const { return m_layer; }
|
||||||
GCodeWriter& writer() { return m_writer; }
|
GCodeWriter& writer() { return m_writer; }
|
||||||
const GCodeWriter& writer() const { return m_writer; }
|
const GCodeWriter& writer() const { return m_writer; }
|
||||||
PlaceholderParser& placeholder_parser() { return m_placeholder_parser; }
|
PlaceholderParser& placeholder_parser() { return m_placeholder_parser_integration.parser; }
|
||||||
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
|
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser_integration.parser; }
|
||||||
// Process a template through the placeholder parser, collect error messages to be reported
|
// Process a template through the placeholder parser, collect error messages to be reported
|
||||||
// inside the generated string and after the G-code export finishes.
|
// inside the generated string and after the G-code export finishes.
|
||||||
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
|
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
|
||||||
@ -343,11 +343,33 @@ private:
|
|||||||
// scaled G-code resolution
|
// scaled G-code resolution
|
||||||
double m_scaled_resolution;
|
double m_scaled_resolution;
|
||||||
GCodeWriter m_writer;
|
GCodeWriter m_writer;
|
||||||
PlaceholderParser m_placeholder_parser;
|
|
||||||
// For random number generator etc.
|
struct PlaceholderParserIntegration {
|
||||||
PlaceholderParser::ContextData m_placeholder_parser_context;
|
void reset();
|
||||||
// Collection of templates, on which the placeholder substitution failed.
|
void init(const GCodeWriter &config);
|
||||||
std::map<std::string, std::string> m_placeholder_parser_failed_templates;
|
void update_from_gcodewriter(const GCodeWriter &writer);
|
||||||
|
void validate_output_vector_variables();
|
||||||
|
|
||||||
|
PlaceholderParser parser;
|
||||||
|
// For random number generator etc.
|
||||||
|
PlaceholderParser::ContextData context;
|
||||||
|
// Collection of templates, on which the placeholder substitution failed.
|
||||||
|
std::map<std::string, std::string> failed_templates;
|
||||||
|
// Input/output from/to custom G-code block, for returning position, retraction etc.
|
||||||
|
DynamicConfig output_config;
|
||||||
|
ConfigOptionFloats *opt_position { nullptr };
|
||||||
|
ConfigOptionFloat *opt_zhop { nullptr };
|
||||||
|
ConfigOptionFloats *opt_e_position { nullptr };
|
||||||
|
ConfigOptionFloats *opt_e_retracted { nullptr };
|
||||||
|
ConfigOptionFloats *opt_e_restart_extra { nullptr };
|
||||||
|
// Caches of the data passed to the script.
|
||||||
|
size_t num_extruders;
|
||||||
|
std::vector<double> position;
|
||||||
|
std::vector<double> e_position;
|
||||||
|
std::vector<double> e_retracted;
|
||||||
|
std::vector<double> e_restart_extra;
|
||||||
|
} m_placeholder_parser_integration;
|
||||||
|
|
||||||
OozePrevention m_ooze_prevention;
|
OozePrevention m_ooze_prevention;
|
||||||
Wipe m_wipe;
|
Wipe m_wipe;
|
||||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||||
@ -403,15 +425,15 @@ private:
|
|||||||
// Index of a last object copy extruded.
|
// Index of a last object copy extruded.
|
||||||
std::pair<const PrintObject*, Point> m_last_obj_copy;
|
std::pair<const PrintObject*, Point> m_last_obj_copy;
|
||||||
|
|
||||||
bool m_silent_time_estimator_enabled;
|
bool m_silent_time_estimator_enabled;
|
||||||
|
|
||||||
// Processor
|
// Processor
|
||||||
GCodeProcessor m_processor;
|
GCodeProcessor m_processor;
|
||||||
|
|
||||||
std::string _extrude(const ExtrusionPath &path, const std::string_view description, double speed = -1);
|
std::string _extrude(const ExtrusionPath &path, const std::string_view description, double speed = -1);
|
||||||
void print_machine_envelope(GCodeOutputStream &file, Print &print);
|
void print_machine_envelope(GCodeOutputStream &file, Print &print);
|
||||||
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||||
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
|
||||||
// On the first printing layer. This flag triggers first layer speeds.
|
// On the first printing layer. This flag triggers first layer speeds.
|
||||||
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
|
||||||
// To control print speed of 1st object layer over raft interface.
|
// To control print speed of 1st object layer over raft interface.
|
||||||
|
@ -486,6 +486,20 @@ std::string GCodeWriter::unlift()
|
|||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCodeWriter::update_position(const Vec3d &new_pos)
|
||||||
|
{
|
||||||
|
assert(this->m_lifted >= 0);
|
||||||
|
const double nominal_z = m_pos.z() - m_lifted;
|
||||||
|
m_lifted = new_pos.z() - nominal_z;
|
||||||
|
if (m_lifted < - EPSILON)
|
||||||
|
throw Slic3r::RuntimeError("Custom G-code reports negative Z-hop. Final Z position is below the print_z height.");
|
||||||
|
// In case that retract_lift == layer_height we could end up with almost zero in_m_lifted
|
||||||
|
// and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154
|
||||||
|
if (m_lifted < EPSILON)
|
||||||
|
m_lifted = 0.;
|
||||||
|
m_pos = new_pos;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed)
|
std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed)
|
||||||
{
|
{
|
||||||
std::ostringstream gcode;
|
std::ostringstream gcode;
|
||||||
|
@ -68,7 +68,18 @@ public:
|
|||||||
std::string unretract();
|
std::string unretract();
|
||||||
std::string lift();
|
std::string lift();
|
||||||
std::string unlift();
|
std::string unlift();
|
||||||
|
|
||||||
|
// Current position of the printer, in G-code coordinates.
|
||||||
|
// Z coordinate of current position contains zhop. If zhop is applied (this->zhop() > 0),
|
||||||
|
// then the print_z = this->get_position().z() - this->zhop().
|
||||||
Vec3d get_position() const { return m_pos; }
|
Vec3d get_position() const { return m_pos; }
|
||||||
|
// Current Z hop value.
|
||||||
|
double get_zhop() const { return m_lifted; }
|
||||||
|
// Update position of the print head based on the final position returned by a custom G-code block.
|
||||||
|
// The new position Z coordinate contains the Z-hop.
|
||||||
|
// GCodeWriter expects the custom script to NOT change print_z, only Z-hop, thus the print_z is maintained
|
||||||
|
// by this function while the current Z-hop accumulator is updated.
|
||||||
|
void update_position(const Vec3d &new_pos);
|
||||||
|
|
||||||
// Returns whether this flavor supports separate print and travel acceleration.
|
// Returns whether this flavor supports separate print and travel acceleration.
|
||||||
static bool supports_separate_travel_acceleration(GCodeFlavor flavor);
|
static bool supports_separate_travel_acceleration(GCodeFlavor flavor);
|
||||||
|
@ -727,7 +727,7 @@ void LayerRegion::prepare_fill_surfaces()
|
|||||||
if (! spiral_vase && this->region().config().top_solid_layers == 0) {
|
if (! spiral_vase && this->region().config().top_solid_layers == 0) {
|
||||||
for (Surface &surface : m_fill_surfaces)
|
for (Surface &surface : m_fill_surfaces)
|
||||||
if (surface.is_top())
|
if (surface.is_top())
|
||||||
surface.surface_type = this->layer()->object()->config().infill_only_where_needed && this->region().config().fill_pattern != ipLightning ? stInternalVoid : stInternal;
|
surface.surface_type = /*this->layer()->object()->config().infill_only_where_needed && this->region().config().fill_pattern != ipLightning ? stInternalVoid :*/ stInternal;
|
||||||
}
|
}
|
||||||
if (this->region().config().bottom_solid_layers == 0) {
|
if (this->region().config().bottom_solid_layers == 0) {
|
||||||
for (Surface &surface : m_fill_surfaces)
|
for (Surface &surface : m_fill_surfaces)
|
||||||
|
@ -177,7 +177,7 @@ namespace client
|
|||||||
bool writable { false };
|
bool writable { false };
|
||||||
// -1 means it is a scalar variable, or it is a vector variable and index was not assigned yet or the whole vector is considered.
|
// -1 means it is a scalar variable, or it is a vector variable and index was not assigned yet or the whole vector is considered.
|
||||||
int index { -1 };
|
int index { -1 };
|
||||||
IteratorRange it_range;
|
IteratorRange it_range;
|
||||||
|
|
||||||
bool empty() const { return opt == nullptr; }
|
bool empty() const { return opt == nullptr; }
|
||||||
bool has_index() const { return index != -1; }
|
bool has_index() const { return index != -1; }
|
||||||
@ -1862,7 +1862,7 @@ namespace client
|
|||||||
// Allow back tracking after '{' in case of a text_block embedded inside a condition.
|
// Allow back tracking after '{' in case of a text_block embedded inside a condition.
|
||||||
// In that case the inner-most {else} wins and the {if}/{elsif}/{else} shall be paired.
|
// In that case the inner-most {else} wins and the {if}/{elsif}/{else} shall be paired.
|
||||||
// {elsif}/{else} without an {if} will be allowed to back track from the embedded text_block.
|
// {elsif}/{else} without an {if} will be allowed to back track from the embedded text_block.
|
||||||
| (lit('{') >> macro(_r1)[_val+=_1] > *(+lit(';') >> macro(_r1)[_val+=_1]) > *lit(';') > '}')
|
| (lit('{') >> (macros(_r1)[_val += _1] > '}') | '}')
|
||||||
| (lit('[') > legacy_variable_expansion(_r1) [_val+=_1] > ']')
|
| (lit('[') > legacy_variable_expansion(_r1) [_val+=_1] > ']')
|
||||||
);
|
);
|
||||||
text_block.name("text_block");
|
text_block.name("text_block");
|
||||||
@ -1874,26 +1874,45 @@ namespace client
|
|||||||
|
|
||||||
// New style of macro expansion.
|
// New style of macro expansion.
|
||||||
// The macro expansion may contain numeric or string expressions, ifs and cases.
|
// The macro expansion may contain numeric or string expressions, ifs and cases.
|
||||||
macro =
|
macros =
|
||||||
(kw["if"] > if_else_output(_r1) [_val = _1])
|
+(block(_r1)[_val += _1] | (statement(_r1) > (+lit(';') | &lit('}')))[_val += _1] | +lit(';'));
|
||||||
// | (kw["switch"] > switch_output(_r1) [_val = _1])
|
macros.name("macro");
|
||||||
| (assignment_statement(_r1) [_val = _1])
|
// if_macros and else_macros only differ by the look-ahead ending condition, which is to not have to repeat the last semicolon
|
||||||
| (new_variable_statement(_r1) [_val = _1])
|
// at the end of the block.
|
||||||
| (conditional_expression(_r1) [ px::bind(&expr::to_string2, _1, _val) ])
|
if_macros = kw["then"] > *(block(_r1)[_val += _1] | (statement(_r1) > (+lit(';') | &(kw["elsif"] | kw["else"] | kw["endif"])))[_val += _1] | +lit(';'));
|
||||||
|
if_macros.name("if_macros");
|
||||||
|
else_macros = *(block(_r1)[_val += _1] | (statement(_r1) > (+lit(';') | &kw["endif"]))[_val += _1] | +lit(';'));
|
||||||
|
else_macros.name("else_macros");
|
||||||
|
|
||||||
|
// Blocks do not require a separating semicolon.
|
||||||
|
block =
|
||||||
|
(kw["if"] > if_else_output(_r1)[_val = _1])
|
||||||
|
// (kw["switch"] ...
|
||||||
|
;
|
||||||
|
block.name("block");
|
||||||
|
|
||||||
|
// Statements require a separating semicolon.
|
||||||
|
statement =
|
||||||
|
(assignment_statement(_r1) [_val = _1])
|
||||||
|
| (new_variable_statement(_r1)[_val = _1])
|
||||||
|
| (conditional_expression(_r1)[px::bind(&expr::to_string2, _1, _val)])
|
||||||
;
|
;
|
||||||
macro.name("macro");
|
|
||||||
|
|
||||||
// An if expression enclosed in {} (the outmost {} are already parsed by the caller).
|
// An if expression enclosed in {} (the outmost {} are already parsed by the caller).
|
||||||
|
// Also }{ could be replaced with ; to simplify writing of pure code.
|
||||||
if_else_output =
|
if_else_output =
|
||||||
eps[_a=true] >
|
eps[_a=true] >
|
||||||
(bool_expr_eval(_r1)[px::bind(&MyContext::block_enter, _r1, _1)] > '}' >
|
(bool_expr_eval(_r1)[px::bind(&MyContext::block_enter, _r1, _1)] > (if_text_block(_r1) | if_macros(_r1)))
|
||||||
text_block(_r1))[px::bind(&MyContext::block_exit, _r1, _1, _a, _2, _val)] > '{' >
|
[px::bind(&MyContext::block_exit, _r1, _1, _a, _2, _val)] >
|
||||||
*((kw["elsif"] > bool_expr_eval(_r1)[px::bind(&MyContext::block_enter, _r1, _1 && _a)] > '}' >
|
*((kw["elsif"] > bool_expr_eval(_r1)[px::bind(&MyContext::block_enter, _r1, _1 && _a)] > (if_text_block(_r1) | if_macros(_r1)))
|
||||||
text_block(_r1))[px::bind(&MyContext::block_exit, _r1, _1, _a, _2, _val)] > '{') >
|
[px::bind(&MyContext::block_exit, _r1, _1, _a, _2, _val)]) >
|
||||||
-(kw["else"] > eps[px::bind(&MyContext::block_enter, _r1, _a)] > lit('}') >
|
-(kw["else"] > eps[px::bind(&MyContext::block_enter, _r1, _a)] > (if_text_block(_r1) | else_macros(_r1)))
|
||||||
text_block(_r1)[px::bind(&MyContext::block_exit, _r1, _a, _a, _1, _val)] > '{') >
|
[px::bind(&MyContext::block_exit, _r1, _a, _a, _1, _val)] >
|
||||||
kw["endif"];
|
kw["endif"];
|
||||||
if_else_output.name("if_else_output");
|
if_else_output.name("if_else_output");
|
||||||
|
if_text_block = (lit('}') > text_block(_r1) > '{');
|
||||||
|
if_text_block.name("if_text_block");
|
||||||
|
|
||||||
// A switch expression enclosed in {} (the outmost {} are already parsed by the caller).
|
// A switch expression enclosed in {} (the outmost {} are already parsed by the caller).
|
||||||
/*
|
/*
|
||||||
switch_output =
|
switch_output =
|
||||||
@ -2119,7 +2138,7 @@ namespace client
|
|||||||
debug(start);
|
debug(start);
|
||||||
debug(text);
|
debug(text);
|
||||||
debug(text_block);
|
debug(text_block);
|
||||||
debug(macro);
|
debug(macros);
|
||||||
debug(if_else_output);
|
debug(if_else_output);
|
||||||
debug(interpolate_table);
|
debug(interpolate_table);
|
||||||
// debug(switch_output);
|
// debug(switch_output);
|
||||||
@ -2155,7 +2174,7 @@ namespace client
|
|||||||
// A free-form text, possibly empty, possibly containing macro expansions.
|
// A free-form text, possibly empty, possibly containing macro expansions.
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> text_block;
|
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> text_block;
|
||||||
// Statements enclosed in curely braces {}
|
// Statements enclosed in curely braces {}
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> macro;
|
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> block, statement, macros, if_text_block, if_macros, else_macros;
|
||||||
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
|
||||||
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> legacy_variable_expansion;
|
qi::rule<Iterator, std::string(const MyContext*), spirit_encoding::space_type> legacy_variable_expansion;
|
||||||
// Parsed identifier name.
|
// Parsed identifier name.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "Exception.hpp"
|
#include "Exception.hpp"
|
||||||
#include "Preset.hpp"
|
#include "Preset.hpp"
|
||||||
#include "AppConfig.hpp"
|
#include "AppConfig.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@ -424,7 +425,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||||||
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
|
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
|
||||||
"extra_perimeters", "extra_perimeters_on_overhangs", "avoid_crossing_curled_overhangs", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
"extra_perimeters", "extra_perimeters_on_overhangs", "avoid_crossing_curled_overhangs", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
||||||
"seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
|
"seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
|
||||||
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
|
"infill_every_layers", /*"infill_only_where_needed",*/ "solid_infill_every_layers", "fill_angle", "bridge_angle",
|
||||||
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
|
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
|
||||||
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
|
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
|
||||||
"max_print_speed", "max_volumetric_speed", "avoid_crossing_perimeters_max_detour",
|
"max_print_speed", "max_volumetric_speed", "avoid_crossing_perimeters_max_detour",
|
||||||
|
@ -1560,14 +1560,14 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comExpert;
|
def->mode = comExpert;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("infill_only_where_needed", coBool);
|
// def = this->add("infill_only_where_needed", coBool);
|
||||||
def->label = L("Only infill where needed");
|
// def->label = L("Only infill where needed");
|
||||||
def->category = L("Infill");
|
// def->category = L("Infill");
|
||||||
def->tooltip = L("This option will limit infill to the areas actually needed for supporting ceilings "
|
// def->tooltip = L("This option will limit infill to the areas actually needed for supporting ceilings "
|
||||||
"(it will act as internal support material). If enabled, slows down the G-code generation "
|
// "(it will act as internal support material). If enabled, slows down the G-code generation "
|
||||||
"due to the multiple checks involved.");
|
// "due to the multiple checks involved.");
|
||||||
def->mode = comAdvanced;
|
// def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
// def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("infill_overlap", coFloatOrPercent);
|
def = this->add("infill_overlap", coFloatOrPercent);
|
||||||
def->label = L("Infill/perimeters overlap");
|
def->label = L("Infill/perimeters overlap");
|
||||||
@ -4154,6 +4154,8 @@ static std::set<std::string> PrintConfigDef_ignore = {
|
|||||||
"wall_add_middle_threshold", "wall_split_middle_threshold",
|
"wall_add_middle_threshold", "wall_split_middle_threshold",
|
||||||
// Replaced by new concentric ensuring in 2.6.0-alpha5
|
// Replaced by new concentric ensuring in 2.6.0-alpha5
|
||||||
"ensure_vertical_shell_thickness",
|
"ensure_vertical_shell_thickness",
|
||||||
|
// Disabled in 2.6.0-alpha6, this option is problematic
|
||||||
|
"infill_only_where_needed",
|
||||||
};
|
};
|
||||||
|
|
||||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||||
@ -4552,12 +4554,19 @@ std::string validate(const FullPrintConfig &cfg)
|
|||||||
}
|
}
|
||||||
case coFloats:
|
case coFloats:
|
||||||
case coPercents:
|
case coPercents:
|
||||||
for (double v : static_cast<const ConfigOptionVector<double>*>(opt)->values)
|
{
|
||||||
|
const auto* vec = static_cast<const ConfigOptionVector<double>*>(opt);
|
||||||
|
for (size_t i = 0; i < vec->size(); ++i) {
|
||||||
|
if (vec->is_nil(i))
|
||||||
|
continue;
|
||||||
|
double v = vec->values[i];
|
||||||
if (v < optdef->min || v > optdef->max) {
|
if (v < optdef->min || v > optdef->max) {
|
||||||
out_of_range = true;
|
out_of_range = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case coInt:
|
case coInt:
|
||||||
{
|
{
|
||||||
auto *iopt = static_cast<const ConfigOptionInt*>(opt);
|
auto *iopt = static_cast<const ConfigOptionInt*>(opt);
|
||||||
@ -4565,12 +4574,19 @@ std::string validate(const FullPrintConfig &cfg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case coInts:
|
case coInts:
|
||||||
for (int v : static_cast<const ConfigOptionVector<int>*>(opt)->values)
|
{
|
||||||
|
const auto* vec = static_cast<const ConfigOptionVector<int>*>(opt);
|
||||||
|
for (size_t i = 0; i < vec->size(); ++i) {
|
||||||
|
if (vec->is_nil(i))
|
||||||
|
continue;
|
||||||
|
int v = vec->values[i];
|
||||||
if (v < optdef->min || v > optdef->max) {
|
if (v < optdef->min || v > optdef->max) {
|
||||||
out_of_range = true;
|
out_of_range = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
if (out_of_range)
|
if (out_of_range)
|
||||||
|
@ -495,7 +495,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
((ConfigOptionFloatOrPercent, extrusion_width))
|
((ConfigOptionFloatOrPercent, extrusion_width))
|
||||||
((ConfigOptionFloat, first_layer_acceleration_over_raft))
|
((ConfigOptionFloat, first_layer_acceleration_over_raft))
|
||||||
((ConfigOptionFloatOrPercent, first_layer_speed_over_raft))
|
((ConfigOptionFloatOrPercent, first_layer_speed_over_raft))
|
||||||
((ConfigOptionBool, infill_only_where_needed))
|
// ((ConfigOptionBool, infill_only_where_needed))
|
||||||
// Force the generation of solid shells between adjacent materials/volumes.
|
// Force the generation of solid shells between adjacent materials/volumes.
|
||||||
((ConfigOptionBool, interface_shells))
|
((ConfigOptionBool, interface_shells))
|
||||||
((ConfigOptionFloat, layer_height))
|
((ConfigOptionFloat, layer_height))
|
||||||
|
@ -348,8 +348,8 @@ void PrintObject::prepare_infill()
|
|||||||
//FIXME The surfaces are supported by a sparse infill, but the sparse infill is only as large as the area to support.
|
//FIXME The surfaces are supported by a sparse infill, but the sparse infill is only as large as the area to support.
|
||||||
// Likely the sparse infill will not be anchored correctly, so it will not work as intended.
|
// Likely the sparse infill will not be anchored correctly, so it will not work as intended.
|
||||||
// Also one wishes the perimeters to be supported by a full infill.
|
// Also one wishes the perimeters to be supported by a full infill.
|
||||||
this->clip_fill_surfaces();
|
// this->clip_fill_surfaces();
|
||||||
m_print->throw_if_canceled();
|
// m_print->throw_if_canceled();
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
|
||||||
@ -2107,7 +2107,7 @@ void PrintObject::bridge_over_infill()
|
|||||||
total_fill_area = closing(total_fill_area, SCALED_EPSILON);
|
total_fill_area = closing(total_fill_area, SCALED_EPSILON);
|
||||||
expansion_area = closing(expansion_area, SCALED_EPSILON);
|
expansion_area = closing(expansion_area, SCALED_EPSILON);
|
||||||
expansion_area = intersection(expansion_area, deep_infill_area);
|
expansion_area = intersection(expansion_area, deep_infill_area);
|
||||||
Polylines anchors = intersection_pl(infill_lines[lidx - 1], expansion_area);
|
Polylines anchors = intersection_pl(infill_lines[lidx - 1], shrink(expansion_area, spacing));
|
||||||
|
|
||||||
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
||||||
debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) + "_" +
|
debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) + "_" +
|
||||||
@ -2419,98 +2419,98 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
|
|||||||
// Also one wishes the perimeters to be supported by a full infill.
|
// Also one wishes the perimeters to be supported by a full infill.
|
||||||
// Idempotence of this method is guaranteed by the fact that we don't remove things from
|
// Idempotence of this method is guaranteed by the fact that we don't remove things from
|
||||||
// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
|
// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
|
||||||
void PrintObject::clip_fill_surfaces()
|
// void PrintObject::clip_fill_surfaces()
|
||||||
{
|
// {
|
||||||
bool has_lightning_infill = false;
|
// bool has_lightning_infill = false;
|
||||||
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id)
|
// for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id)
|
||||||
if (const PrintRegionConfig &config = this->printing_region(region_id).config(); config.fill_density > 0 && config.fill_pattern == ipLightning)
|
// if (const PrintRegionConfig &config = this->printing_region(region_id).config(); config.fill_density > 0 && config.fill_pattern == ipLightning)
|
||||||
has_lightning_infill = true;
|
// has_lightning_infill = true;
|
||||||
|
|
||||||
// For Lightning infill, infill_only_where_needed is ignored because both
|
// // For Lightning infill, infill_only_where_needed is ignored because both
|
||||||
// do a similar thing, and their combination doesn't make much sense.
|
// // do a similar thing, and their combination doesn't make much sense.
|
||||||
if (! m_config.infill_only_where_needed.value || has_lightning_infill)
|
// if (! m_config.infill_only_where_needed.value || has_lightning_infill)
|
||||||
return;
|
// return;
|
||||||
bool has_infill = false;
|
// bool has_infill = false;
|
||||||
for (size_t i = 0; i < this->num_printing_regions(); ++ i)
|
// for (size_t i = 0; i < this->num_printing_regions(); ++ i)
|
||||||
if (this->printing_region(i).config().fill_density > 0) {
|
// if (this->printing_region(i).config().fill_density > 0) {
|
||||||
has_infill = true;
|
// has_infill = true;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
if (! has_infill)
|
// if (! has_infill)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// We only want infill under ceilings; this is almost like an
|
// // We only want infill under ceilings; this is almost like an
|
||||||
// internal support material.
|
// // internal support material.
|
||||||
// Proceed top-down, skipping the bottom layer.
|
// // Proceed top-down, skipping the bottom layer.
|
||||||
Polygons upper_internal;
|
// Polygons upper_internal;
|
||||||
for (int layer_id = int(m_layers.size()) - 1; layer_id > 0; -- layer_id) {
|
// for (int layer_id = int(m_layers.size()) - 1; layer_id > 0; -- layer_id) {
|
||||||
Layer *layer = m_layers[layer_id];
|
// Layer *layer = m_layers[layer_id];
|
||||||
Layer *lower_layer = m_layers[layer_id - 1];
|
// Layer *lower_layer = m_layers[layer_id - 1];
|
||||||
// Detect things that we need to support.
|
// // Detect things that we need to support.
|
||||||
// Cummulative fill surfaces.
|
// // Cummulative fill surfaces.
|
||||||
Polygons fill_surfaces;
|
// Polygons fill_surfaces;
|
||||||
// Solid surfaces to be supported.
|
// // Solid surfaces to be supported.
|
||||||
Polygons overhangs;
|
// Polygons overhangs;
|
||||||
for (const LayerRegion *layerm : layer->m_regions)
|
// for (const LayerRegion *layerm : layer->m_regions)
|
||||||
for (const Surface &surface : layerm->fill_surfaces()) {
|
// for (const Surface &surface : layerm->fill_surfaces()) {
|
||||||
Polygons polygons = to_polygons(surface.expolygon);
|
// Polygons polygons = to_polygons(surface.expolygon);
|
||||||
if (surface.is_solid())
|
// if (surface.is_solid())
|
||||||
polygons_append(overhangs, polygons);
|
// polygons_append(overhangs, polygons);
|
||||||
polygons_append(fill_surfaces, std::move(polygons));
|
// polygons_append(fill_surfaces, std::move(polygons));
|
||||||
}
|
// }
|
||||||
Polygons lower_layer_fill_surfaces;
|
// Polygons lower_layer_fill_surfaces;
|
||||||
Polygons lower_layer_internal_surfaces;
|
// Polygons lower_layer_internal_surfaces;
|
||||||
for (const LayerRegion *layerm : lower_layer->m_regions)
|
// for (const LayerRegion *layerm : lower_layer->m_regions)
|
||||||
for (const Surface &surface : layerm->fill_surfaces()) {
|
// for (const Surface &surface : layerm->fill_surfaces()) {
|
||||||
Polygons polygons = to_polygons(surface.expolygon);
|
// Polygons polygons = to_polygons(surface.expolygon);
|
||||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
// if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||||
polygons_append(lower_layer_internal_surfaces, polygons);
|
// polygons_append(lower_layer_internal_surfaces, polygons);
|
||||||
polygons_append(lower_layer_fill_surfaces, std::move(polygons));
|
// polygons_append(lower_layer_fill_surfaces, std::move(polygons));
|
||||||
}
|
// }
|
||||||
// We also need to support perimeters when there's at least one full unsupported loop
|
// // We also need to support perimeters when there's at least one full unsupported loop
|
||||||
{
|
// {
|
||||||
// Get perimeters area as the difference between slices and fill_surfaces
|
// // Get perimeters area as the difference between slices and fill_surfaces
|
||||||
// Only consider the area that is not supported by lower perimeters
|
// // Only consider the area that is not supported by lower perimeters
|
||||||
Polygons perimeters = intersection(diff(layer->lslices, fill_surfaces), lower_layer_fill_surfaces);
|
// Polygons perimeters = intersection(diff(layer->lslices, fill_surfaces), lower_layer_fill_surfaces);
|
||||||
// Only consider perimeter areas that are at least one extrusion width thick.
|
// // Only consider perimeter areas that are at least one extrusion width thick.
|
||||||
//FIXME Offset2 eats out from both sides, while the perimeters are create outside in.
|
// //FIXME Offset2 eats out from both sides, while the perimeters are create outside in.
|
||||||
//Should the pw not be half of the current value?
|
// //Should the pw not be half of the current value?
|
||||||
float pw = FLT_MAX;
|
// float pw = FLT_MAX;
|
||||||
for (const LayerRegion *layerm : layer->m_regions)
|
// for (const LayerRegion *layerm : layer->m_regions)
|
||||||
pw = std::min(pw, (float)layerm->flow(frPerimeter).scaled_width());
|
// pw = std::min(pw, (float)layerm->flow(frPerimeter).scaled_width());
|
||||||
// Append such thick perimeters to the areas that need support
|
// // Append such thick perimeters to the areas that need support
|
||||||
polygons_append(overhangs, opening(perimeters, pw));
|
// polygons_append(overhangs, opening(perimeters, pw));
|
||||||
}
|
// }
|
||||||
// Merge the new overhangs, find new internal infill.
|
// // Merge the new overhangs, find new internal infill.
|
||||||
polygons_append(upper_internal, std::move(overhangs));
|
// polygons_append(upper_internal, std::move(overhangs));
|
||||||
static constexpr const auto closing_radius = scaled<float>(2.f);
|
// static constexpr const auto closing_radius = scaled<float>(2.f);
|
||||||
upper_internal = intersection(
|
// upper_internal = intersection(
|
||||||
// Regularize the overhang regions, so that the infill areas will not become excessively jagged.
|
// // Regularize the overhang regions, so that the infill areas will not become excessively jagged.
|
||||||
smooth_outward(
|
// smooth_outward(
|
||||||
closing(upper_internal, closing_radius, ClipperLib::jtSquare, 0.),
|
// closing(upper_internal, closing_radius, ClipperLib::jtSquare, 0.),
|
||||||
scaled<coord_t>(0.1)),
|
// scaled<coord_t>(0.1)),
|
||||||
lower_layer_internal_surfaces);
|
// lower_layer_internal_surfaces);
|
||||||
// Apply new internal infill to regions.
|
// // Apply new internal infill to regions.
|
||||||
for (LayerRegion *layerm : lower_layer->m_regions) {
|
// for (LayerRegion *layerm : lower_layer->m_regions) {
|
||||||
if (layerm->region().config().fill_density.value == 0)
|
// if (layerm->region().config().fill_density.value == 0)
|
||||||
continue;
|
// continue;
|
||||||
Polygons internal;
|
// Polygons internal;
|
||||||
for (Surface &surface : layerm->m_fill_surfaces.surfaces)
|
// for (Surface &surface : layerm->m_fill_surfaces.surfaces)
|
||||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
// if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||||
polygons_append(internal, std::move(surface.expolygon));
|
// polygons_append(internal, std::move(surface.expolygon));
|
||||||
layerm->m_fill_surfaces.remove_types({ stInternal, stInternalVoid });
|
// layerm->m_fill_surfaces.remove_types({ stInternal, stInternalVoid });
|
||||||
layerm->m_fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal);
|
// layerm->m_fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal);
|
||||||
layerm->m_fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid);
|
// layerm->m_fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid);
|
||||||
// If there are voids it means that our internal infill is not adjacent to
|
// // If there are voids it means that our internal infill is not adjacent to
|
||||||
// perimeters. In this case it would be nice to add a loop around infill to
|
// // perimeters. In this case it would be nice to add a loop around infill to
|
||||||
// make it more robust and nicer. TODO.
|
// // make it more robust and nicer. TODO.
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
// #ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
layerm->export_region_fill_surfaces_to_svg_debug("6_clip_fill_surfaces");
|
// layerm->export_region_fill_surfaces_to_svg_debug("6_clip_fill_surfaces");
|
||||||
#endif
|
// #endif
|
||||||
}
|
// }
|
||||||
m_print->throw_if_canceled();
|
// m_print->throw_if_canceled();
|
||||||
}
|
// }
|
||||||
} // void PrintObject::clip_fill_surfaces()
|
// } // void PrintObject::clip_fill_surfaces()
|
||||||
|
|
||||||
void PrintObject::discover_horizontal_shells()
|
void PrintObject::discover_horizontal_shells()
|
||||||
{
|
{
|
||||||
|
@ -588,6 +588,15 @@ std::string SLAPrint::validate(std::string*) const
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SLAPrint::export_print(const std::string &fname, const ThumbnailsList &thumbnails, const std::string &projectname)
|
||||||
|
{
|
||||||
|
if (m_archiver)
|
||||||
|
m_archiver->export_print(fname, *this, thumbnails, projectname);
|
||||||
|
else {
|
||||||
|
throw ExportError(format(_u8L("Unknown archive format: %s"), m_printer_config.sla_archive_format.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SLAPrint::invalidate_step(SLAPrintStep step)
|
bool SLAPrint::invalidate_step(SLAPrintStep step)
|
||||||
{
|
{
|
||||||
bool invalidated = Inherited::invalidate_step(step);
|
bool invalidated = Inherited::invalidate_step(step);
|
||||||
|
@ -546,10 +546,7 @@ public:
|
|||||||
|
|
||||||
void export_print(const std::string &fname,
|
void export_print(const std::string &fname,
|
||||||
const ThumbnailsList &thumbnails,
|
const ThumbnailsList &thumbnails,
|
||||||
const std::string &projectname = "")
|
const std::string &projectname = "");
|
||||||
{
|
|
||||||
m_archiver->export_print(fname, *this, thumbnails, projectname);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -199,7 +199,13 @@ void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep st
|
|||||||
m = csgmesh_merge_positive_parts(r);
|
m = csgmesh_merge_positive_parts(r);
|
||||||
handled = true;
|
handled = true;
|
||||||
} else if (csg::check_csgmesh_booleans(r) == r.end()) {
|
} else if (csg::check_csgmesh_booleans(r) == r.end()) {
|
||||||
auto cgalmeshptr = csg::perform_csgmesh_booleans(r);
|
MeshBoolean::cgal::CGALMeshPtr cgalmeshptr;
|
||||||
|
try {
|
||||||
|
cgalmeshptr = csg::perform_csgmesh_booleans(r);
|
||||||
|
} catch (...) {
|
||||||
|
// leaves cgalmeshptr as nullptr
|
||||||
|
}
|
||||||
|
|
||||||
if (cgalmeshptr) {
|
if (cgalmeshptr) {
|
||||||
m = MeshBoolean::cgal::cgal_to_indexed_triangle_set(*cgalmeshptr);
|
m = MeshBoolean::cgal::cgal_to_indexed_triangle_set(*cgalmeshptr);
|
||||||
handled = true;
|
handled = true;
|
||||||
|
@ -44,17 +44,23 @@ void CoordAxes::render(const Transform3d& trafo, float emission_factor)
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", emission_factor);
|
shader->set_uniform("emission_factor", emission_factor);
|
||||||
|
|
||||||
|
// Scale the axes if the camera is close to them to avoid issues
|
||||||
|
// such as https://github.com/prusa3d/PrusaSlicer/issues/9483
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
Transform3d scale_tr = Transform3d::Identity();
|
||||||
|
scale_tr.scale(std::min(1., camera.get_inv_zoom() * 10.));
|
||||||
|
|
||||||
// x axis
|
// x axis
|
||||||
m_arrow.set_color(ColorRGBA::X());
|
m_arrow.set_color(ColorRGBA::X());
|
||||||
render_axis(*shader, trafo * Geometry::translation_transform(m_origin) * Geometry::rotation_transform({ 0.0, 0.5 * M_PI, 0.0 }));
|
render_axis(*shader, trafo * Geometry::translation_transform(m_origin) * Geometry::rotation_transform({ 0.0, 0.5 * M_PI, 0.0 }) * scale_tr);
|
||||||
|
|
||||||
// y axis
|
// y axis
|
||||||
m_arrow.set_color(ColorRGBA::Y());
|
m_arrow.set_color(ColorRGBA::Y());
|
||||||
render_axis(*shader, trafo * Geometry::translation_transform(m_origin) * Geometry::rotation_transform({ -0.5 * M_PI, 0.0, 0.0 }));
|
render_axis(*shader, trafo * Geometry::translation_transform(m_origin) * Geometry::rotation_transform({ -0.5 * M_PI, 0.0, 0.0 }) * scale_tr);
|
||||||
|
|
||||||
// z axis
|
// z axis
|
||||||
m_arrow.set_color(ColorRGBA::Z());
|
m_arrow.set_color(ColorRGBA::Z());
|
||||||
render_axis(*shader, trafo * Geometry::translation_transform(m_origin));
|
render_axis(*shader, trafo * Geometry::translation_transform(m_origin) * scale_tr);
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
if (curr_shader != nullptr)
|
if (curr_shader != nullptr)
|
||||||
|
@ -1572,8 +1572,7 @@ void GLCanvas3D::render()
|
|||||||
_render_objects(GLVolumeCollection::ERenderType::Opaque);
|
_render_objects(GLVolumeCollection::ERenderType::Opaque);
|
||||||
_render_sla_slices();
|
_render_sla_slices();
|
||||||
_render_selection();
|
_render_selection();
|
||||||
if (m_show_bed_axes)
|
_render_bed_axes();
|
||||||
_render_bed_axes();
|
|
||||||
if (is_looking_downward)
|
if (is_looking_downward)
|
||||||
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), false);
|
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), false);
|
||||||
if (!m_main_toolbar.is_enabled())
|
if (!m_main_toolbar.is_enabled())
|
||||||
@ -2351,15 +2350,6 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||||||
#endif /* __APPLE__ */
|
#endif /* __APPLE__ */
|
||||||
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
|
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
|
||||||
break;
|
break;
|
||||||
#ifdef __APPLE__
|
|
||||||
case 'd':
|
|
||||||
case 'D':
|
|
||||||
#else /* __APPLE__ */
|
|
||||||
case WXK_CONTROL_D:
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
m_show_bed_axes = !m_show_bed_axes;
|
|
||||||
m_dirty = true;
|
|
||||||
break;
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
|
@ -522,7 +522,6 @@ private:
|
|||||||
ECursorType m_cursor_type;
|
ECursorType m_cursor_type;
|
||||||
GLSelectionRectangle m_rectangle_selection;
|
GLSelectionRectangle m_rectangle_selection;
|
||||||
std::vector<int> m_hover_volume_idxs;
|
std::vector<int> m_hover_volume_idxs;
|
||||||
bool m_show_bed_axes{ true };
|
|
||||||
|
|
||||||
// Following variable is obsolete and it should be safe to remove it.
|
// Following variable is obsolete and it should be safe to remove it.
|
||||||
// I just don't want to do it now before a release (Lukas Matena 24.3.2019)
|
// I just don't want to do it now before a release (Lukas Matena 24.3.2019)
|
||||||
|
@ -1322,7 +1322,7 @@ bool GUI_App::on_init_inner()
|
|||||||
if (!delayed_error_load_presets.empty())
|
if (!delayed_error_load_presets.empty())
|
||||||
show_error(nullptr, delayed_error_load_presets);
|
show_error(nullptr, delayed_error_load_presets);
|
||||||
|
|
||||||
mainframe = new MainFrame();
|
mainframe = new MainFrame(app_config->has("font_size") ? atoi(app_config->get("font_size").c_str()) : -1);
|
||||||
// hide settings tabs after first Layout
|
// hide settings tabs after first Layout
|
||||||
if (is_editor())
|
if (is_editor())
|
||||||
mainframe->select_tab(size_t(0));
|
mainframe->select_tab(size_t(0));
|
||||||
@ -1810,7 +1810,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||||||
dlg.Update(10, _L("Recreating") + dots);
|
dlg.Update(10, _L("Recreating") + dots);
|
||||||
|
|
||||||
MainFrame *old_main_frame = mainframe;
|
MainFrame *old_main_frame = mainframe;
|
||||||
mainframe = new MainFrame();
|
mainframe = new MainFrame(app_config->has("font_size") ? atoi(app_config->get("font_size").c_str()) : -1);
|
||||||
if (is_editor())
|
if (is_editor())
|
||||||
// hide settings tabs after first Layout
|
// hide settings tabs after first Layout
|
||||||
mainframe->select_tab(size_t(0));
|
mainframe->select_tab(size_t(0));
|
||||||
|
@ -2939,6 +2939,16 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
|||||||
if (obj_idx >= m_objects->size())
|
if (obj_idx >= m_objects->size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
wxDataViewItemArray sels;
|
||||||
|
if (!selections) {
|
||||||
|
GetSelections(sels);
|
||||||
|
for (wxDataViewItem item : sels)
|
||||||
|
if (item.IsOk() && m_objects_model->GetItemType(item) == itVolume) {
|
||||||
|
selections = &sels;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ModelObject* model_object = (*m_objects)[obj_idx];
|
const ModelObject* model_object = (*m_objects)[obj_idx];
|
||||||
wxDataViewItem item_obj = m_objects_model->GetItemById(obj_idx);
|
wxDataViewItem item_obj = m_objects_model->GetItemById(obj_idx);
|
||||||
assert(item_obj.IsOk());
|
assert(item_obj.IsOk());
|
||||||
|
@ -82,7 +82,7 @@ template<class P> class DPIAware : public P
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
|
DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
|
||||||
const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)
|
const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name= wxFrameNameStr, const int font_point_size = -1)
|
||||||
: P(parent, id, title, pos, size, style, name)
|
: P(parent, id, title, pos, size, style, name)
|
||||||
{
|
{
|
||||||
int dpi = get_dpi_for_window(this);
|
int dpi = get_dpi_for_window(this);
|
||||||
@ -90,6 +90,9 @@ public:
|
|||||||
m_prev_scale_factor = m_scale_factor;
|
m_prev_scale_factor = m_scale_factor;
|
||||||
m_normal_font = get_default_font_for_dpi(this, dpi);
|
m_normal_font = get_default_font_for_dpi(this, dpi);
|
||||||
|
|
||||||
|
if (font_point_size > 0)
|
||||||
|
m_normal_font.SetPointSize(font_point_size);
|
||||||
|
|
||||||
/* Because of default window font is a primary display font,
|
/* Because of default window font is a primary display font,
|
||||||
* We should set correct font for window before getting em_unit value.
|
* We should set correct font for window before getting em_unit value.
|
||||||
*/
|
*/
|
||||||
|
@ -774,7 +774,7 @@ GLGizmoEmboss::GuiCfg GLGizmoEmboss::create_gui_configuration()
|
|||||||
tr.skew_ration = _u8L("Skew ratio");
|
tr.skew_ration = _u8L("Skew ratio");
|
||||||
tr.from_surface = _u8L("From surface");
|
tr.from_surface = _u8L("From surface");
|
||||||
tr.rotation = _u8L("Rotation");
|
tr.rotation = _u8L("Rotation");
|
||||||
tr.keep_up = _u8L("Keep Up");
|
tr.keep_up = "Keep Rotation";
|
||||||
tr.collection = _u8L("Collection");
|
tr.collection = _u8L("Collection");
|
||||||
|
|
||||||
float max_advanced_text_width = std::max({
|
float max_advanced_text_width = std::max({
|
||||||
@ -2996,7 +2996,7 @@ void GLGizmoEmboss::draw_advanced()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("%s", _u8L("Keep text orientation during surface dragging.\nNot stable between horizontal and vertical alignment.").c_str());
|
ImGui::SetTooltip("%s", _u8L("Lock the text's rotation when moving text along the object's surface.").c_str());
|
||||||
|
|
||||||
// when more collection add selector
|
// when more collection add selector
|
||||||
if (ff.font_file->infos.size() > 1) {
|
if (ff.font_file->infos.size() > 1) {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r::GUI {
|
namespace Slic3r::GUI {
|
||||||
|
@ -151,7 +151,6 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
{ L("Arrow Right"), L("Move selection 10 mm in positive X direction") },
|
{ L("Arrow Right"), L("Move selection 10 mm in positive X direction") },
|
||||||
{ std::string("Shift+") + L("Any arrow"), L("Movement step set to 1 mm") },
|
{ std::string("Shift+") + L("Any arrow"), L("Movement step set to 1 mm") },
|
||||||
{ ctrl + L("Any arrow"), L("Movement in camera space") },
|
{ ctrl + L("Any arrow"), L("Movement in camera space") },
|
||||||
{ ctrl + "D", L("Show/hide reference axes") },
|
|
||||||
{ L("Page Up"), L("Rotate selection 45 degrees CCW") },
|
{ L("Page Up"), L("Rotate selection 45 degrees CCW") },
|
||||||
{ L("Page Down"), L("Rotate selection 45 degrees CW") },
|
{ L("Page Down"), L("Rotate selection 45 degrees CW") },
|
||||||
{ "M", L("Gizmo move") },
|
{ "M", L("Gizmo move") },
|
||||||
@ -232,7 +231,6 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
{ "X", L("On/Off one layer mode of the vertical slider") },
|
{ "X", L("On/Off one layer mode of the vertical slider") },
|
||||||
{ "L", L("Show/Hide legend") },
|
{ "L", L("Show/Hide legend") },
|
||||||
{ "C", L("Show/Hide G-code window") },
|
{ "C", L("Show/Hide G-code window") },
|
||||||
{ ctrl + "D", L("Show/hide reference axes") },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
m_full_shortcuts.push_back({ { _L("Preview"), "" }, preview_shortcuts });
|
m_full_shortcuts.push_back({ { _L("Preview"), "" }, preview_shortcuts });
|
||||||
|
@ -122,8 +122,8 @@ static wxIcon main_frame_icon(GUI_App::EAppMode app_mode)
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
MainFrame::MainFrame() :
|
MainFrame::MainFrame(const int font_point_size) :
|
||||||
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
|
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe", font_point_size),
|
||||||
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||||
, m_recent_projects(9)
|
, m_recent_projects(9)
|
||||||
, m_settings_dialog(this)
|
, m_settings_dialog(this)
|
||||||
@ -1540,6 +1540,7 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
// assign menubar to frame after appending items, otherwise special items
|
// assign menubar to frame after appending items, otherwise special items
|
||||||
// will not be handled correctly
|
// will not be handled correctly
|
||||||
m_menubar = new wxMenuBar();
|
m_menubar = new wxMenuBar();
|
||||||
|
m_menubar->SetFont(this->normal_font());
|
||||||
m_menubar->Append(fileMenu, _L("&File"));
|
m_menubar->Append(fileMenu, _L("&File"));
|
||||||
if (editMenu) m_menubar->Append(editMenu, _L("&Edit"));
|
if (editMenu) m_menubar->Append(editMenu, _L("&Edit"));
|
||||||
m_menubar->Append(windowMenu, _L("&Window"));
|
m_menubar->Append(windowMenu, _L("&Window"));
|
||||||
@ -2237,7 +2238,7 @@ std::string MainFrame::get_dir_name(const wxString &full_name) const
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
SettingsDialog::SettingsDialog(MainFrame* mainframe)
|
SettingsDialog::SettingsDialog(MainFrame* mainframe)
|
||||||
:DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "settings_dialog"),
|
:DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "settings_dialog", mainframe->normal_font().GetPointSize()),
|
||||||
//: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize,
|
//: DPIDialog(mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Settings"), wxDefaultPosition, wxDefaultSize,
|
||||||
// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
|
// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
|
||||||
m_main_frame(mainframe)
|
m_main_frame(mainframe)
|
||||||
|
@ -139,7 +139,7 @@ protected:
|
|||||||
virtual void on_sys_color_changed() override;
|
virtual void on_sys_color_changed() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainFrame();
|
MainFrame(const int font_point_size);
|
||||||
~MainFrame() = default;
|
~MainFrame() = default;
|
||||||
|
|
||||||
void update_layout();
|
void update_layout();
|
||||||
|
@ -136,7 +136,7 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin
|
|||||||
msg_lines++;
|
msg_lines++;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
wxFont font = wxGetApp().normal_font();//wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||||
wxFont monospace = wxGetApp().code_font();
|
wxFont monospace = wxGetApp().code_font();
|
||||||
wxColour text_clr = wxGetApp().get_label_clr_default();
|
wxColour text_clr = wxGetApp().get_label_clr_default();
|
||||||
wxColour bgr_clr = parent->GetBackgroundColour();
|
wxColour bgr_clr = parent->GetBackgroundColour();
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
#include "libslic3r/miniz_extension.hpp"
|
#include "libslic3r/miniz_extension.hpp"
|
||||||
|
|
||||||
|
// For stl export
|
||||||
|
#include "libslic3r/CSGMesh/ModelToCSGMesh.hpp"
|
||||||
|
#include "libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp"
|
||||||
|
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "GUI_ObjectList.hpp"
|
#include "GUI_ObjectList.hpp"
|
||||||
@ -6382,14 +6386,34 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Following lambda generates a combined mesh for export with normals pointing outwards.
|
// Following lambda generates a combined mesh for export with normals pointing outwards.
|
||||||
auto mesh_to_export_fff = [](const ModelObject& mo, int instance_id) {
|
auto mesh_to_export_fff = [this](const ModelObject& mo, int instance_id) {
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
for (const ModelVolume* v : mo.volumes)
|
|
||||||
if (v->is_model_part()) {
|
std::vector<csg::CSGPart> csgmesh;
|
||||||
TriangleMesh vol_mesh(v->mesh());
|
csgmesh.reserve(2 * mo.volumes.size());
|
||||||
vol_mesh.transform(v->get_matrix(), true);
|
csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh),
|
||||||
mesh.merge(vol_mesh);
|
csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits);
|
||||||
}
|
|
||||||
|
if (csg::check_csgmesh_booleans(range(csgmesh)) == csgmesh.end()) {
|
||||||
|
try {
|
||||||
|
auto cgalm = csg::perform_csgmesh_booleans(range(csgmesh));
|
||||||
|
mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalm);
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.empty()) {
|
||||||
|
get_notification_manager()->push_plater_error_notification(
|
||||||
|
_u8L("Unable to perform boolean operation on model meshes. "
|
||||||
|
"Only positive parts will be exported."));
|
||||||
|
|
||||||
|
for (const ModelVolume* v : mo.volumes)
|
||||||
|
if (v->is_model_part()) {
|
||||||
|
TriangleMesh vol_mesh(v->mesh());
|
||||||
|
vol_mesh.transform(v->get_matrix(), true);
|
||||||
|
mesh.merge(vol_mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (instance_id == -1) {
|
if (instance_id == -1) {
|
||||||
TriangleMesh vols_mesh(mesh);
|
TriangleMesh vols_mesh(mesh);
|
||||||
mesh = TriangleMesh();
|
mesh = TriangleMesh();
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#include <wx/notebook.h>
|
#include <wx/notebook.h>
|
||||||
#include "Notebook.hpp"
|
#include "Notebook.hpp"
|
||||||
@ -580,6 +581,7 @@ void PreferencesDialog::build()
|
|||||||
activate_options_tab(m_optgroup_other);
|
activate_options_tab(m_optgroup_other);
|
||||||
|
|
||||||
create_downloader_path_sizer();
|
create_downloader_path_sizer();
|
||||||
|
// create_settings_font_widget();
|
||||||
|
|
||||||
#if ENABLE_ENVIRONMENT_MAP
|
#if ENABLE_ENVIRONMENT_MAP
|
||||||
// Add "Render" tab
|
// Add "Render" tab
|
||||||
@ -694,7 +696,7 @@ void PreferencesDialog::accept(wxEvent&)
|
|||||||
|
|
||||||
bool update_filament_sidebar = (m_values.find("no_templates") != m_values.end());
|
bool update_filament_sidebar = (m_values.find("no_templates") != m_values.end());
|
||||||
|
|
||||||
std::vector<std::string> options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled" };
|
std::vector<std::string> options_to_recreate_GUI = { "no_defaults", "tabs_as_menu", "sys_menu_enabled", "font_size" };
|
||||||
|
|
||||||
for (const std::string& option : options_to_recreate_GUI) {
|
for (const std::string& option : options_to_recreate_GUI) {
|
||||||
if (m_values.find(option) != m_values.end()) {
|
if (m_values.find(option) != m_values.end()) {
|
||||||
@ -943,7 +945,6 @@ void PreferencesDialog::create_icon_size_slider()
|
|||||||
void PreferencesDialog::create_settings_mode_widget()
|
void PreferencesDialog::create_settings_mode_widget()
|
||||||
{
|
{
|
||||||
wxWindow* parent = m_optgroup_gui->parent();
|
wxWindow* parent = m_optgroup_gui->parent();
|
||||||
wxGetApp().UpdateDarkUI(parent);
|
|
||||||
|
|
||||||
wxString title = L("Layout Options");
|
wxString title = L("Layout Options");
|
||||||
wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title));
|
wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title));
|
||||||
@ -1045,6 +1046,74 @@ void PreferencesDialog::create_settings_mode_color_widget()
|
|||||||
append_preferences_option_to_searcher(m_optgroup_gui, opt_key, title);
|
append_preferences_option_to_searcher(m_optgroup_gui, opt_key, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PreferencesDialog::create_settings_font_widget()
|
||||||
|
{
|
||||||
|
wxWindow* parent = m_optgroup_other->parent();
|
||||||
|
wxGetApp().UpdateDarkUI(parent);
|
||||||
|
|
||||||
|
const wxString title = L("Application font size");
|
||||||
|
wxStaticBox* stb = new wxStaticBox(parent, wxID_ANY, _(title));
|
||||||
|
if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
|
|
||||||
|
const std::string opt_key = "font_size";
|
||||||
|
m_blinkers[opt_key] = new BlinkingBitmap(parent);
|
||||||
|
|
||||||
|
wxSizer* stb_sizer = new wxStaticBoxSizer(stb, wxHORIZONTAL);
|
||||||
|
|
||||||
|
wxStaticText* font_example = new wxStaticText(parent, wxID_ANY, "Application text");
|
||||||
|
int val = wxGetApp().normal_font().GetPointSize();
|
||||||
|
wxSpinCtrl* size_sc = new wxSpinCtrl(parent, wxID_ANY, format_wxstr("%1%", val), wxDefaultPosition, wxSize(15*em_unit(), -1), wxTE_PROCESS_ENTER | wxSP_ARROW_KEYS
|
||||||
|
#ifdef _WIN32
|
||||||
|
| wxBORDER_SIMPLE
|
||||||
|
#endif
|
||||||
|
, 8, 20);
|
||||||
|
wxGetApp().UpdateDarkUI(size_sc);
|
||||||
|
|
||||||
|
auto apply_font = [this, font_example, opt_key](const int val, const wxFont& font) {
|
||||||
|
font_example->SetFont(font);
|
||||||
|
m_values[opt_key] = format("%1%", val);
|
||||||
|
refresh_og(m_optgroup_other);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto change_value = [size_sc, apply_font](wxCommandEvent& evt) {
|
||||||
|
const int val = size_sc->GetValue();
|
||||||
|
wxFont font = wxGetApp().normal_font();
|
||||||
|
font.SetPointSize(val);
|
||||||
|
|
||||||
|
apply_font(val, font);
|
||||||
|
};
|
||||||
|
size_sc->Bind(wxEVT_SPINCTRL, change_value);
|
||||||
|
size_sc->Bind(wxEVT_TEXT_ENTER, change_value);
|
||||||
|
|
||||||
|
auto revert_btn = new ScalableButton(parent, wxID_ANY, "undo");
|
||||||
|
revert_btn->SetToolTip(_L("Revert font to default"));
|
||||||
|
revert_btn->Bind(wxEVT_BUTTON, [size_sc, apply_font](wxEvent& event) {
|
||||||
|
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||||
|
const int val = font.GetPointSize();
|
||||||
|
size_sc->SetValue(val);
|
||||||
|
apply_font(val, font);
|
||||||
|
});
|
||||||
|
parent->Bind(wxEVT_UPDATE_UI, [size_sc](wxUpdateUIEvent& evt) {
|
||||||
|
const int def_size = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize();
|
||||||
|
evt.Enable(def_size != size_sc->GetValue());
|
||||||
|
}, revert_btn->GetId());
|
||||||
|
|
||||||
|
stb_sizer->Add(new wxStaticText(parent, wxID_ANY, _L("Font size") + ":"), 0, wxALIGN_CENTER_VERTICAL | wxLEFT, em_unit());
|
||||||
|
stb_sizer->Add(size_sc, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, em_unit());
|
||||||
|
stb_sizer->Add(revert_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, em_unit());
|
||||||
|
wxBoxSizer* font_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
font_sizer->Add(font_example, 1, wxALIGN_CENTER_HORIZONTAL);
|
||||||
|
stb_sizer->Add(font_sizer, 1, wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
|
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
sizer->Add(m_blinkers[opt_key], 0, wxRIGHT, 2);
|
||||||
|
sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL);
|
||||||
|
|
||||||
|
m_optgroup_other->sizer->Add(sizer, 1, wxEXPAND | wxTOP, em_unit());
|
||||||
|
|
||||||
|
append_preferences_option_to_searcher(m_optgroup_other, opt_key, title);
|
||||||
|
}
|
||||||
|
|
||||||
void PreferencesDialog::create_downloader_path_sizer()
|
void PreferencesDialog::create_downloader_path_sizer()
|
||||||
{
|
{
|
||||||
wxWindow* parent = m_optgroup_other->parent();
|
wxWindow* parent = m_optgroup_other->parent();
|
||||||
|
@ -91,10 +91,12 @@ protected:
|
|||||||
void layout();
|
void layout();
|
||||||
void clear_cache();
|
void clear_cache();
|
||||||
void refresh_og(std::shared_ptr<ConfigOptionsGroup> og);
|
void refresh_og(std::shared_ptr<ConfigOptionsGroup> og);
|
||||||
|
void refresh_og(ConfigOptionsGroup* og);
|
||||||
void create_icon_size_slider();
|
void create_icon_size_slider();
|
||||||
void create_settings_mode_widget();
|
void create_settings_mode_widget();
|
||||||
void create_settings_text_color_widget();
|
void create_settings_text_color_widget();
|
||||||
void create_settings_mode_color_widget();
|
void create_settings_mode_color_widget();
|
||||||
|
void create_settings_font_widget();
|
||||||
void create_downloader_path_sizer();
|
void create_downloader_path_sizer();
|
||||||
void init_highlighter(const t_config_option_key& opt_key);
|
void init_highlighter(const t_config_option_key& opt_key);
|
||||||
std::vector<ConfigOptionsGroup*> optgroups();
|
std::vector<ConfigOptionsGroup*> optgroups();
|
||||||
|
@ -85,18 +85,17 @@ void SavePresetDialog::Item::init_input_name_ctrl(wxBoxSizer *input_name_sizer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString SavePresetDialog::Item::get_top_label_text() const
|
static std::map<Preset::Type, std::string> TOP_LABELS =
|
||||||
{
|
{
|
||||||
const std::string label_str = m_use_text_ctrl ?
|
// type Save settings
|
||||||
// TRN %1% = "Preset"
|
{ Preset::Type::TYPE_PRINT, L("Save print settings as") },
|
||||||
L("Rename %1% to") :
|
{ Preset::Type::TYPE_SLA_PRINT, L("Save print settings as") },
|
||||||
// TRN %1% = "Preset"
|
{ Preset::Type::TYPE_FILAMENT, L("Save filament settings as")},
|
||||||
L("Save %1% as");
|
{ Preset::Type::TYPE_SLA_MATERIAL, L("Save material settings as")},
|
||||||
Tab* tab = wxGetApp().get_tab(m_type);
|
{ Preset::Type::TYPE_PRINTER, L("Save printer settings as") },
|
||||||
return format_wxstr(_(label_str) + ":", tab->title());
|
};
|
||||||
}
|
|
||||||
|
|
||||||
SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
|
SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent, bool is_for_multiple_save):
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_use_text_ctrl(parent->is_for_rename()),
|
m_use_text_ctrl(parent->is_for_rename()),
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
@ -105,14 +104,15 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox
|
|||||||
{
|
{
|
||||||
m_valid_label->SetFont(wxGetApp().bold_font());
|
m_valid_label->SetFont(wxGetApp().bold_font());
|
||||||
|
|
||||||
wxStaticText* label_top = new wxStaticText(m_parent, wxID_ANY, get_top_label_text());
|
wxStaticText* label_top = is_for_multiple_save ? new wxStaticText(m_parent, wxID_ANY, _(TOP_LABELS.at(m_type)) + ":") : nullptr;
|
||||||
|
|
||||||
wxBoxSizer* input_name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* input_name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
input_name_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
|
input_name_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
|
||||||
init_input_name_ctrl(input_name_sizer, get_init_preset_name(suffix));
|
init_input_name_ctrl(input_name_sizer, get_init_preset_name(suffix));
|
||||||
|
|
||||||
sizer->Add(label_top, 0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
|
if (label_top)
|
||||||
sizer->Add(input_name_sizer,0, wxEXPAND | wxBOTTOM, BORDER_W);
|
sizer->Add(label_top, 0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
|
||||||
|
sizer->Add(input_name_sizer,0, wxEXPAND | (label_top ? 0 : wxTOP) | wxBOTTOM, BORDER_W);
|
||||||
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
||||||
|
|
||||||
if (m_type == Preset::TYPE_PRINTER)
|
if (m_type == Preset::TYPE_PRINTER)
|
||||||
@ -205,8 +205,6 @@ void SavePresetDialog::Item::update()
|
|||||||
if ((!m_use_text_ctrl && m_presets->get_edited_preset().is_dirty) ||
|
if ((!m_use_text_ctrl && m_presets->get_edited_preset().is_dirty) ||
|
||||||
(dlg && dlg->get_preset_bundle())) // means that we save modifications from the DiffDialog
|
(dlg && dlg->get_preset_bundle())) // means that we save modifications from the DiffDialog
|
||||||
info_line = _L("Save preset modifications to existing user profile");
|
info_line = _L("Save preset modifications to existing user profile");
|
||||||
else
|
|
||||||
info_line = _L("Nothing changed");
|
|
||||||
m_valid_type = ValidationType::Valid;
|
m_valid_type = ValidationType::Valid;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -266,8 +264,8 @@ void SavePresetDialog::Item::update()
|
|||||||
|
|
||||||
void SavePresetDialog::Item::update_valid_bmp()
|
void SavePresetDialog::Item::update_valid_bmp()
|
||||||
{
|
{
|
||||||
std::string bmp_name = m_valid_type == ValidationType::Warning ? "exclamation" :
|
std::string bmp_name = m_valid_type == ValidationType::Warning ? "exclamation_manifold" :
|
||||||
m_valid_type == ValidationType::NoValid ? "cross" : "tick_mark" ;
|
m_valid_type == ValidationType::NoValid ? "exclamation" : "tick_mark" ;
|
||||||
m_valid_bmp->SetBitmap(*get_bmp_bundle(bmp_name));
|
m_valid_bmp->SetBitmap(*get_bmp_bundle(bmp_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,22 +287,17 @@ void SavePresetDialog::Item::Enable(bool enable /*= true*/)
|
|||||||
// SavePresetDialog
|
// SavePresetDialog
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
|
|
||||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix, bool template_filament)
|
|
||||||
: DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
|
||||||
{
|
|
||||||
build(std::vector<Preset::Type>{type}, suffix, template_filament);
|
|
||||||
}
|
|
||||||
|
|
||||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix, bool template_filament/* =false*/, PresetBundle* preset_bundle/* = nullptr*/)
|
SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix, bool template_filament/* =false*/, PresetBundle* preset_bundle/* = nullptr*/)
|
||||||
: DPIDialog(parent, wxID_ANY, _L("Save presets"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER),
|
: DPIDialog(parent, wxID_ANY, types.size() == 1 ? _L("Save preset") : _L("Save presets"),
|
||||||
|
wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING),
|
||||||
m_preset_bundle(preset_bundle)
|
m_preset_bundle(preset_bundle)
|
||||||
{
|
{
|
||||||
build(types, suffix, template_filament);
|
build(types, suffix, template_filament);
|
||||||
}
|
}
|
||||||
|
|
||||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, bool rename, const wxString& info_line_extention)
|
SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, const wxString& info_line_extention)
|
||||||
: DPIDialog(parent, wxID_ANY, _L("Rename preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER),
|
: DPIDialog(parent, wxID_ANY, _L("Rename preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING),
|
||||||
m_use_for_rename(rename),
|
m_use_for_rename(true),
|
||||||
m_info_line_extention(info_line_extention)
|
m_info_line_extention(info_line_extention)
|
||||||
{
|
{
|
||||||
build(std::vector<Preset::Type>{type});
|
build(std::vector<Preset::Type>{type});
|
||||||
@ -318,11 +311,13 @@ SavePresetDialog::~SavePresetDialog()
|
|||||||
|
|
||||||
void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix, bool template_filament)
|
void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix, bool template_filament)
|
||||||
{
|
{
|
||||||
|
this->SetFont(wxGetApp().normal_font());
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
// ys_FIXME! temporary workaround for correct font scaling
|
// ys_FIXME! temporary workaround for correct font scaling
|
||||||
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
||||||
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
||||||
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
// this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
#else
|
#else
|
||||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
@ -335,9 +330,9 @@ void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix
|
|||||||
|
|
||||||
m_presets_sizer = new wxBoxSizer(wxVERTICAL);
|
m_presets_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
// Add first item
|
const bool is_for_multiple_save = types.size() > 1;
|
||||||
for (Preset::Type type : types)
|
for (const Preset::Type& type : types)
|
||||||
AddItem(type, suffix);
|
AddItem(type, suffix, is_for_multiple_save);
|
||||||
|
|
||||||
// Add dialog's buttons
|
// Add dialog's buttons
|
||||||
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||||
@ -367,9 +362,9 @@ void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix)
|
void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix, bool is_for_multiple_save)
|
||||||
{
|
{
|
||||||
m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this});
|
m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this, is_for_multiple_save});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SavePresetDialog::get_name()
|
std::string SavePresetDialog::get_name()
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
Warning
|
Warning
|
||||||
};
|
};
|
||||||
|
|
||||||
Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent);
|
Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent, bool is_for_multiple_save);
|
||||||
Item(wxWindow* parent, wxBoxSizer* sizer, const std::string& def_name, PrinterTechnology pt = ptFFF);
|
Item(wxWindow* parent, wxBoxSizer* sizer, const std::string& def_name, PrinterTechnology pt = ptFFF);
|
||||||
|
|
||||||
void update_valid_bmp();
|
void update_valid_bmp();
|
||||||
@ -65,7 +65,6 @@ public:
|
|||||||
std::string get_init_preset_name(const std::string &suffix);
|
std::string get_init_preset_name(const std::string &suffix);
|
||||||
void init_input_name_ctrl(wxBoxSizer *input_name_sizer, std::string preset_name);
|
void init_input_name_ctrl(wxBoxSizer *input_name_sizer, std::string preset_name);
|
||||||
const Preset* get_existing_preset() const ;
|
const Preset* get_existing_preset() const ;
|
||||||
wxString get_top_label_text() const ;
|
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
};
|
};
|
||||||
@ -89,12 +88,11 @@ public:
|
|||||||
|
|
||||||
const wxString& get_info_line_extention() { return m_info_line_extention; }
|
const wxString& get_info_line_extention() { return m_info_line_extention; }
|
||||||
|
|
||||||
SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix = "", bool template_filament = false);
|
|
||||||
SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix = "", bool template_filament = false, PresetBundle* preset_bundle = nullptr);
|
SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix = "", bool template_filament = false, PresetBundle* preset_bundle = nullptr);
|
||||||
SavePresetDialog(wxWindow* parent, Preset::Type type, bool rename, const wxString& info_line_extention);
|
SavePresetDialog(wxWindow* parent, Preset::Type type, const wxString& info_line_extention);
|
||||||
~SavePresetDialog() override;
|
~SavePresetDialog() override;
|
||||||
|
|
||||||
void AddItem(Preset::Type type, const std::string& suffix);
|
void AddItem(Preset::Type type, const std::string& suffix, bool is_for_multiple_save);
|
||||||
|
|
||||||
PresetBundle* get_preset_bundle() const { return m_preset_bundle; }
|
PresetBundle* get_preset_bundle() const { return m_preset_bundle; }
|
||||||
std::string get_name();
|
std::string get_name();
|
||||||
|
@ -265,6 +265,7 @@ void Tab::create_preset_tab()
|
|||||||
// tree
|
// tree
|
||||||
m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1),
|
m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1),
|
||||||
wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS);
|
wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS);
|
||||||
|
m_treectrl->SetFont(wxGetApp().normal_font());
|
||||||
m_left_sizer->Add(m_treectrl, 1, wxEXPAND);
|
m_left_sizer->Add(m_treectrl, 1, wxEXPAND);
|
||||||
// Index of the last icon inserted into m_treectrl
|
// Index of the last icon inserted into m_treectrl
|
||||||
m_icon_count = -1;
|
m_icon_count = -1;
|
||||||
@ -1469,7 +1470,7 @@ void TabPrint::build()
|
|||||||
optgroup = page->new_optgroup(L("Reducing printing time"));
|
optgroup = page->new_optgroup(L("Reducing printing time"));
|
||||||
category_path = "infill_42#";
|
category_path = "infill_42#";
|
||||||
optgroup->append_single_option_line("infill_every_layers", category_path + "combine-infill-every-x-layers");
|
optgroup->append_single_option_line("infill_every_layers", category_path + "combine-infill-every-x-layers");
|
||||||
optgroup->append_single_option_line("infill_only_where_needed", category_path + "only-infill-where-needed");
|
// optgroup->append_single_option_line("infill_only_where_needed", category_path + "only-infill-where-needed");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(L("Advanced"));
|
optgroup = page->new_optgroup(L("Advanced"));
|
||||||
optgroup->append_single_option_line("solid_infill_every_layers", category_path + "solid-infill-every-x-layers");
|
optgroup->append_single_option_line("solid_infill_every_layers", category_path + "solid-infill-every-x-layers");
|
||||||
@ -3820,7 +3821,7 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : "", from_template);
|
SavePresetDialog dlg(m_parent, { m_type }, detach ? _u8L("Detached") : "", from_template);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
name = dlg.get_name();
|
name = dlg.get_name();
|
||||||
@ -3931,7 +3932,7 @@ void Tab::rename_preset()
|
|||||||
|
|
||||||
// get new name
|
// get new name
|
||||||
|
|
||||||
SavePresetDialog dlg(m_parent, m_type, true, msg);
|
SavePresetDialog dlg(m_parent, m_type, msg);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -837,7 +837,8 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||||||
// ys_FIXME! temporary workaround for correct font scaling
|
// ys_FIXME! temporary workaround for correct font scaling
|
||||||
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
||||||
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
||||||
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
// this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
|
this->SetFont(wxGetApp().normal_font());
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
|
|
||||||
int border = 10;
|
int border = 10;
|
||||||
@ -850,7 +851,8 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||||||
add_new_value_column = false;
|
add_new_value_column = false;
|
||||||
|
|
||||||
m_action_line = new wxStaticText(this, wxID_ANY, "");
|
m_action_line = new wxStaticText(this, wxID_ANY, "");
|
||||||
m_action_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
// m_action_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
||||||
|
m_action_line->SetFont(wxGetApp().bold_font());
|
||||||
|
|
||||||
m_tree = new DiffViewCtrl(this, wxSize(em * (add_new_value_column ? 80 : 60), em * 30));
|
m_tree = new DiffViewCtrl(this, wxSize(em * (add_new_value_column ? 80 : 60), em * 30));
|
||||||
m_tree->AppendToggleColumn_(L"\u2714" , DiffModel::colToggle, wxLinux ? 9 : 6);
|
m_tree->AppendToggleColumn_(L"\u2714" , DiffModel::colToggle, wxLinux ? 9 : 6);
|
||||||
@ -910,7 +912,8 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||||||
cancel_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { this->EndModal(wxID_CANCEL); });
|
cancel_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { this->EndModal(wxID_CANCEL); });
|
||||||
|
|
||||||
m_info_line = new wxStaticText(this, wxID_ANY, "");
|
m_info_line = new wxStaticText(this, wxID_ANY, "");
|
||||||
m_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
// m_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
||||||
|
m_info_line->SetFont(wxGetApp().bold_font());
|
||||||
m_info_line->Hide();
|
m_info_line->Hide();
|
||||||
|
|
||||||
if (!m_app_config_key.empty()) {
|
if (!m_app_config_key.empty()) {
|
||||||
@ -1012,7 +1015,7 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets, bool show_s
|
|||||||
|
|
||||||
// for system/default/external presets we should take an edited name
|
// for system/default/external presets we should take an edited name
|
||||||
if (preset.is_system || preset.is_default || preset.is_external) {
|
if (preset.is_system || preset.is_default || preset.is_external) {
|
||||||
SavePresetDialog save_dlg(this, preset.type);
|
SavePresetDialog save_dlg(this, { preset.type });
|
||||||
if (save_dlg.ShowModal() != wxID_OK) {
|
if (save_dlg.ShowModal() != wxID_OK) {
|
||||||
m_exit_action = Action::Discard;
|
m_exit_action = Action::Discard;
|
||||||
return false;
|
return false;
|
||||||
@ -1362,6 +1365,7 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString
|
|||||||
: wxDialog(nullptr, wxID_ANY, option_name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
: wxDialog(nullptr, wxID_ANY, option_name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||||
{
|
{
|
||||||
wxGetApp().UpdateDarkUI(this);
|
wxGetApp().UpdateDarkUI(this);
|
||||||
|
this->SetFont(wxGetApp().normal_font());
|
||||||
|
|
||||||
int border = 10;
|
int border = 10;
|
||||||
bool has_new_value_column = !new_value_header.IsEmpty();
|
bool has_new_value_column = !new_value_header.IsEmpty();
|
||||||
@ -1528,7 +1532,8 @@ void DiffPresetDialog::create_show_all_presets_chb()
|
|||||||
|
|
||||||
void DiffPresetDialog::create_info_lines()
|
void DiffPresetDialog::create_info_lines()
|
||||||
{
|
{
|
||||||
const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
|
// const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
|
||||||
|
const wxFont font = GetFont().Bold();
|
||||||
|
|
||||||
m_top_info_line = new wxStaticText(this, wxID_ANY, _L("Select presets to compare"));
|
m_top_info_line = new wxStaticText(this, wxID_ANY, _L("Select presets to compare"));
|
||||||
m_top_info_line->SetFont(font);
|
m_top_info_line->SetFont(font);
|
||||||
@ -1668,7 +1673,8 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||||||
// ys_FIXME! temporary workaround for correct font scaling
|
// ys_FIXME! temporary workaround for correct font scaling
|
||||||
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
||||||
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
||||||
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
// this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
|
this->SetFont(mainframe->normal_font());
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
|
|
||||||
// Init bundles
|
// Init bundles
|
||||||
|
@ -512,11 +512,8 @@ std::string OctoPrint::make_url(const std::string &path) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SL1Host::SL1Host(DynamicPrintConfig *config) :
|
SL1Host::SL1Host(DynamicPrintConfig *config)
|
||||||
OctoPrint(config),
|
: PrusaLink(config)
|
||||||
m_authorization_type(dynamic_cast<const ConfigOptionEnum<AuthorizationType>*>(config->option("printhost_authorization_type"))->value),
|
|
||||||
m_username(config->opt_string("printhost_user")),
|
|
||||||
m_password(config->opt_string("printhost_password"))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,22 +535,6 @@ bool SL1Host::validate_version_text(const boost::optional<std::string> &version_
|
|||||||
return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false;
|
return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SL1Host::set_auth(Http &http) const
|
|
||||||
{
|
|
||||||
switch (m_authorization_type) {
|
|
||||||
case atKeyPassword:
|
|
||||||
http.header("X-Api-Key", get_apikey());
|
|
||||||
break;
|
|
||||||
case atUserPassword:
|
|
||||||
http.auth_digest(m_username, m_password);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! get_cafile().empty()) {
|
|
||||||
http.ca_file(get_cafile());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrusaLink
|
// PrusaLink
|
||||||
PrusaLink::PrusaLink(DynamicPrintConfig* config, bool show_after_message) :
|
PrusaLink::PrusaLink(DynamicPrintConfig* config, bool show_after_message) :
|
||||||
OctoPrint(config),
|
OctoPrint(config),
|
||||||
|
@ -55,30 +55,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class SL1Host: public OctoPrint
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SL1Host(DynamicPrintConfig *config);
|
|
||||||
~SL1Host() override = default;
|
|
||||||
|
|
||||||
const char* get_name() const override;
|
|
||||||
|
|
||||||
wxString get_test_ok_msg() const override;
|
|
||||||
wxString get_test_failed_msg(wxString &msg) const override;
|
|
||||||
PrintHostPostUploadActions get_post_upload_actions() const override { return {}; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool validate_version_text(const boost::optional<std::string> &version_text) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void set_auth(Http &http) const override;
|
|
||||||
|
|
||||||
// Host authorization type.
|
|
||||||
AuthorizationType m_authorization_type;
|
|
||||||
// username and password for HTTP Digest Authentization (RFC RFC2617)
|
|
||||||
std::string m_username;
|
|
||||||
std::string m_password;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PrusaLink : public OctoPrint
|
class PrusaLink : public OctoPrint
|
||||||
{
|
{
|
||||||
@ -106,6 +82,12 @@ protected:
|
|||||||
bool upload_inner_with_resolved_ip(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn, const boost::asio::ip::address& resolved_addr) const override;
|
bool upload_inner_with_resolved_ip(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn, const boost::asio::ip::address& resolved_addr) const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Host authorization type.
|
||||||
|
AuthorizationType m_authorization_type;
|
||||||
|
// username and password for HTTP Digest Authentization (RFC RFC2617)
|
||||||
|
std::string m_username;
|
||||||
|
std::string m_password;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool test_with_method_check(wxString& curl_msg, bool& use_put) const;
|
bool test_with_method_check(wxString& curl_msg, bool& use_put) const;
|
||||||
bool put_inner(PrintHostUpload upload_data, std::string url, const std::string& name, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const;
|
bool put_inner(PrintHostUpload upload_data, std::string url, const std::string& name, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const;
|
||||||
@ -113,11 +95,7 @@ private:
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
bool test_with_resolved_ip_and_method_check(wxString& curl_msg, bool& use_put) const;
|
bool test_with_resolved_ip_and_method_check(wxString& curl_msg, bool& use_put) const;
|
||||||
#endif
|
#endif
|
||||||
// Host authorization type.
|
|
||||||
AuthorizationType m_authorization_type;
|
|
||||||
// username and password for HTTP Digest Authentization (RFC RFC2617)
|
|
||||||
std::string m_username;
|
|
||||||
std::string m_password;
|
|
||||||
bool m_show_after_message;
|
bool m_show_after_message;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -149,6 +127,22 @@ public:
|
|||||||
const char* get_name() const override { return "Mainsail/Fluidd"; }
|
const char* get_name() const override { return "Mainsail/Fluidd"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SL1Host : public PrusaLink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SL1Host(DynamicPrintConfig* config);
|
||||||
|
~SL1Host() override = default;
|
||||||
|
|
||||||
|
const char* get_name() const override;
|
||||||
|
|
||||||
|
wxString get_test_ok_msg() const override;
|
||||||
|
wxString get_test_failed_msg(wxString& msg) const override;
|
||||||
|
PrintHostPostUploadActions get_post_upload_actions() const override { return {}; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool validate_version_text(const boost::optional<std::string>& version_text) const override;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -252,85 +252,85 @@ SCENARIO("Infill does not exceed perimeters", "[Fill]")
|
|||||||
GIVEN("Concentric") { test("concentric"sv); }
|
GIVEN("Concentric") { test("concentric"sv); }
|
||||||
}
|
}
|
||||||
|
|
||||||
SCENARIO("Infill only where needed", "[Fill]")
|
// SCENARIO("Infill only where needed", "[Fill]")
|
||||||
{
|
// {
|
||||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
// DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||||
config.set_deserialize_strict({
|
// config.set_deserialize_strict({
|
||||||
{ "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" },
|
// { "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" },
|
||||||
{ "infill_only_where_needed", true },
|
// { "infill_only_where_needed", true },
|
||||||
{ "bottom_solid_layers", 0 },
|
// { "bottom_solid_layers", 0 },
|
||||||
{ "infill_extruder", 2 },
|
// { "infill_extruder", 2 },
|
||||||
{ "infill_extrusion_width", 0.5 },
|
// { "infill_extrusion_width", 0.5 },
|
||||||
{ "wipe_into_infill", false },
|
// { "wipe_into_infill", false },
|
||||||
{ "fill_density", 0.4 },
|
// { "fill_density", 0.4 },
|
||||||
// for preventing speeds from being altered
|
// // for preventing speeds from being altered
|
||||||
{ "cooling", "0, 0, 0, 0" },
|
// { "cooling", "0, 0, 0, 0" },
|
||||||
// for preventing speeds from being altered
|
// // for preventing speeds from being altered
|
||||||
{ "first_layer_speed", "100%" }
|
// { "first_layer_speed", "100%" }
|
||||||
});
|
// });
|
||||||
|
|
||||||
auto test = [&config]() -> double {
|
// auto test = [&config]() -> double {
|
||||||
TriangleMesh pyramid = Test::mesh(Slic3r::Test::TestMesh::pyramid);
|
// TriangleMesh pyramid = Test::mesh(Slic3r::Test::TestMesh::pyramid);
|
||||||
// Arachne doesn't use "Detect thin walls," and because of this, it filters out tiny infill areas differently.
|
// // Arachne doesn't use "Detect thin walls," and because of this, it filters out tiny infill areas differently.
|
||||||
// So, for Arachne, we cut the pyramid model to achieve similar results.
|
// // So, for Arachne, we cut the pyramid model to achieve similar results.
|
||||||
if (config.opt_enum<PerimeterGeneratorType>("perimeter_generator") == Slic3r::PerimeterGeneratorType::Arachne) {
|
// if (config.opt_enum<PerimeterGeneratorType>("perimeter_generator") == Slic3r::PerimeterGeneratorType::Arachne) {
|
||||||
indexed_triangle_set lower{};
|
// indexed_triangle_set lower{};
|
||||||
cut_mesh(pyramid.its, 35, nullptr, &lower);
|
// cut_mesh(pyramid.its, 35, nullptr, &lower);
|
||||||
pyramid = TriangleMesh(lower);
|
// pyramid = TriangleMesh(lower);
|
||||||
}
|
// }
|
||||||
std::string gcode = Slic3r::Test::slice({ pyramid }, config);
|
// std::string gcode = Slic3r::Test::slice({ pyramid }, config);
|
||||||
THEN("gcode not empty") {
|
// THEN("gcode not empty") {
|
||||||
REQUIRE(! gcode.empty());
|
// REQUIRE(! gcode.empty());
|
||||||
}
|
// }
|
||||||
|
|
||||||
GCodeReader parser;
|
// GCodeReader parser;
|
||||||
int tool = -1;
|
// int tool = -1;
|
||||||
const int infill_extruder = config.opt_int("infill_extruder");
|
// const int infill_extruder = config.opt_int("infill_extruder");
|
||||||
Points infill_points;
|
// Points infill_points;
|
||||||
parser.parse_buffer(gcode, [&tool, &infill_points, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
// parser.parse_buffer(gcode, [&tool, &infill_points, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
||||||
{
|
// {
|
||||||
// if the command is a T command, set the the current tool
|
// // if the command is a T command, set the the current tool
|
||||||
if (boost::starts_with(line.cmd(), "T")) {
|
// if (boost::starts_with(line.cmd(), "T")) {
|
||||||
tool = atoi(line.cmd().data() + 1) + 1;
|
// tool = atoi(line.cmd().data() + 1) + 1;
|
||||||
} else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
// } else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
||||||
if (tool == infill_extruder) {
|
// if (tool == infill_extruder) {
|
||||||
infill_points.emplace_back(self.xy_scaled());
|
// infill_points.emplace_back(self.xy_scaled());
|
||||||
infill_points.emplace_back(line.new_XY_scaled(self));
|
// infill_points.emplace_back(line.new_XY_scaled(self));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
// prevent calling convex_hull() with no points
|
// // prevent calling convex_hull() with no points
|
||||||
THEN("infill not empty") {
|
// THEN("infill not empty") {
|
||||||
REQUIRE(! infill_points.empty());
|
// REQUIRE(! infill_points.empty());
|
||||||
}
|
// }
|
||||||
|
|
||||||
auto opt_width = config.opt<ConfigOptionFloatOrPercent>("infill_extrusion_width");
|
// auto opt_width = config.opt<ConfigOptionFloatOrPercent>("infill_extrusion_width");
|
||||||
REQUIRE(! opt_width->percent);
|
// REQUIRE(! opt_width->percent);
|
||||||
Polygons convex_hull = expand(Geometry::convex_hull(infill_points), scaled<float>(opt_width->value / 2));
|
// Polygons convex_hull = expand(Geometry::convex_hull(infill_points), scaled<float>(opt_width->value / 2));
|
||||||
return SCALING_FACTOR * SCALING_FACTOR * std::accumulate(convex_hull.begin(), convex_hull.end(), 0., [](double acc, const Polygon &poly){ return acc + poly.area(); });
|
// return SCALING_FACTOR * SCALING_FACTOR * std::accumulate(convex_hull.begin(), convex_hull.end(), 0., [](double acc, const Polygon &poly){ return acc + poly.area(); });
|
||||||
};
|
// };
|
||||||
|
|
||||||
double tolerance = 5; // mm^2
|
// double tolerance = 5; // mm^2
|
||||||
|
|
||||||
// GIVEN("solid_infill_below_area == 0") {
|
// // GIVEN("solid_infill_below_area == 0") {
|
||||||
// config.opt_float("solid_infill_below_area") = 0;
|
// // config.opt_float("solid_infill_below_area") = 0;
|
||||||
// WHEN("pyramid is sliced ") {
|
// // WHEN("pyramid is sliced ") {
|
||||||
// auto area = test();
|
// // auto area = test();
|
||||||
// THEN("no infill is generated when using infill_only_where_needed on a pyramid") {
|
// // THEN("no infill is generated when using infill_only_where_needed on a pyramid") {
|
||||||
// REQUIRE(area < tolerance);
|
// // REQUIRE(area < tolerance);
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
// GIVEN("solid_infill_below_area == 70") {
|
// // GIVEN("solid_infill_below_area == 70") {
|
||||||
// config.opt_float("solid_infill_below_area") = 70;
|
// // config.opt_float("solid_infill_below_area") = 70;
|
||||||
// WHEN("pyramid is sliced ") {
|
// // WHEN("pyramid is sliced ") {
|
||||||
// auto area = test();
|
// // auto area = test();
|
||||||
// THEN("infill is only generated under the forced solid shells") {
|
// // THEN("infill is only generated under the forced solid shells") {
|
||||||
// REQUIRE(std::abs(area - 70) < tolerance);
|
// // REQUIRE(std::abs(area - 70) < tolerance);
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
}
|
// }
|
||||||
|
|
||||||
SCENARIO("Combine infill", "[Fill]")
|
SCENARIO("Combine infill", "[Fill]")
|
||||||
{
|
{
|
||||||
|
@ -245,10 +245,41 @@ SCENARIO("Placeholder parser variables", "[PlaceholderParser]") {
|
|||||||
"{size(myfloats)}";
|
"{size(myfloats)}";
|
||||||
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7");
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7");
|
||||||
}
|
}
|
||||||
|
SECTION("nested if with new variables 2, mixing }{ with ;") {
|
||||||
|
std::string script =
|
||||||
|
"{if 1 == 0 then local myints = (5, 4, 3, 2, 1);else;local myfloats = (1., 2., 3., 4., 5., 6., 7.);endif}"
|
||||||
|
"{size(myfloats)}";
|
||||||
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7");
|
||||||
|
}
|
||||||
SECTION("nested if with new variables, two level") {
|
SECTION("nested if with new variables, two level") {
|
||||||
std::string script =
|
std::string script =
|
||||||
"{if 1 == 1}{if 2 == 3}{nejaka / haluz}{else}{local myints = (6, 5, 4, 3, 2, 1)}{endif}{else}{if zase * haluz}{else}{local myfloats = (1., 2., 3., 4., 5., 6., 7.)}{endif}{endif}"
|
"{if 1 == 1}{if 2 == 3}{nejaka / haluz}{else}{local myints = (6, 5, 4, 3, 2, 1)}{endif}{else}{if zase * haluz}{else}{local myfloats = (1., 2., 3., 4., 5., 6., 7.)}{endif}{endif}"
|
||||||
"{size(myints)}";
|
"{size(myints)}";
|
||||||
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6");
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6");
|
||||||
}
|
}
|
||||||
|
SECTION("if with empty block and ;") {
|
||||||
|
std::string script =
|
||||||
|
"{if false then else;local myfloats = (1., 2., 3., 4., 5., 6., 7.);endif}"
|
||||||
|
"{size(myfloats)}";
|
||||||
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "7");
|
||||||
|
}
|
||||||
|
SECTION("nested if with new variables, two level, mixing }{ with ;") {
|
||||||
|
std::string script =
|
||||||
|
"{if 1 == 1 then if 2 == 3}nejaka / haluz{else local myints = (6, 5, 4, 3, 2, 1) endif else if zase * haluz then else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif endif}"
|
||||||
|
"{size(myints)}";
|
||||||
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6");
|
||||||
|
}
|
||||||
|
SECTION("nested if with new variables, two level, mixing }{ with ; 2") {
|
||||||
|
std::string script =
|
||||||
|
"{if 1 == 1 then if 2 == 3 then nejaka / haluz else}{local myints = (6, 5, 4, 3, 2, 1)}{endif else if zase * haluz then else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif endif}"
|
||||||
|
"{size(myints)}";
|
||||||
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6");
|
||||||
|
}
|
||||||
|
SECTION("nested if with new variables, two level, mixing }{ with ; 3") {
|
||||||
|
std::string script =
|
||||||
|
"{if 1 == 1 then if 2 == 3 then nejaka / haluz else}{local myints = (6, 5, 4, 3, 2, 1)}{endif else}{if zase * haluz}{else local myfloats = (1., 2., 3., 4., 5., 6., 7.) endif}{endif}"
|
||||||
|
"{size(myints)}";
|
||||||
|
REQUIRE(parser.process(script, 0, nullptr, nullptr, nullptr) == "6");
|
||||||
|
}
|
||||||
|
SECTION("if else completely empty") { REQUIRE(parser.process("{if false then elsif false then else endif}", 0, nullptr, nullptr, nullptr) == ""); }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user