mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-18 01:25:58 +08:00
Merge branch 'master' into fs_CenterSupportForIsland
This commit is contained in:
commit
0a761fd649
@ -1313,6 +1313,7 @@ public:
|
|||||||
ConfigOptionEnum<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
ConfigOptionEnum<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||||
bool operator==(const ConfigOptionEnum<T> &rhs) const { return this->value == rhs.value; }
|
bool operator==(const ConfigOptionEnum<T> &rhs) const { return this->value == rhs.value; }
|
||||||
int getInt() const override { return (int)this->value; }
|
int getInt() const override { return (int)this->value; }
|
||||||
|
void setInt(int val) override { this->value = T(val); }
|
||||||
|
|
||||||
bool operator==(const ConfigOption &rhs) const override
|
bool operator==(const ConfigOption &rhs) const override
|
||||||
{
|
{
|
||||||
|
@ -667,6 +667,14 @@ namespace DoExport {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ret.size() < MAX_TAGS_COUNT) {
|
||||||
|
const CustomGCode::Info& custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
|
||||||
|
for (const auto& gcode : custom_gcode_per_print_z.gcodes) {
|
||||||
|
check(_(L("Custom G-code")), gcode.extra);
|
||||||
|
if (ret.size() == MAX_TAGS_COUNT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -429,7 +429,7 @@ const std::vector<std::string>& Preset::print_options()
|
|||||||
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
||||||
"support_material_pattern", "support_material_with_sheath", "support_material_spacing",
|
"support_material_pattern", "support_material_with_sheath", "support_material_spacing",
|
||||||
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers",
|
"support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers",
|
||||||
"support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance",
|
"support_material_interface_pattern", "support_material_interface_spacing", "support_material_interface_contact_loops", "support_material_contact_distance",
|
||||||
"support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius",
|
"support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "extruder_clearance_radius",
|
||||||
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder",
|
"extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder",
|
||||||
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
"infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder",
|
||||||
|
@ -2341,6 +2341,22 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
|
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
|
||||||
|
|
||||||
|
def = this->add("support_material_interface_pattern", coEnum);
|
||||||
|
def->label = L("Interface pattern");
|
||||||
|
def->category = L("Support material");
|
||||||
|
def->tooltip = L("Pattern used to generate support material interface. "
|
||||||
|
"Default pattern for non-soluble support interface is Rectilinear, "
|
||||||
|
"while default pattern for soluble support interface is Concentric.");
|
||||||
|
def->enum_keys_map = &ConfigOptionEnum<SupportMaterialInterfacePattern>::get_enum_values();
|
||||||
|
def->enum_values.push_back("auto");
|
||||||
|
def->enum_values.push_back("rectilinear");
|
||||||
|
def->enum_values.push_back("concentric");
|
||||||
|
def->enum_labels.push_back(L("Default"));
|
||||||
|
def->enum_labels.push_back(L("Rectilinear"));
|
||||||
|
def->enum_labels.push_back(L("Concentric"));
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
|
||||||
|
|
||||||
def = this->add("support_material_spacing", coFloat);
|
def = this->add("support_material_spacing", coFloat);
|
||||||
def->label = L("Pattern spacing");
|
def->label = L("Pattern spacing");
|
||||||
def->category = L("Support material");
|
def->category = L("Support material");
|
||||||
|
@ -65,6 +65,10 @@ enum SupportMaterialPattern {
|
|||||||
smpRectilinear, smpRectilinearGrid, smpHoneycomb,
|
smpRectilinear, smpRectilinearGrid, smpHoneycomb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SupportMaterialInterfacePattern {
|
||||||
|
smipAuto, smipRectilinear, smipConcentric,
|
||||||
|
};
|
||||||
|
|
||||||
enum SeamPosition {
|
enum SeamPosition {
|
||||||
spRandom, spNearest, spAligned, spRear
|
spRandom, spNearest, spAligned, spRear
|
||||||
};
|
};
|
||||||
@ -207,6 +211,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialPa
|
|||||||
return keys_map;
|
return keys_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialInterfacePattern>::get_enum_values() {
|
||||||
|
static t_config_enum_values keys_map;
|
||||||
|
if (keys_map.empty()) {
|
||||||
|
keys_map["auto"] = smipAuto;
|
||||||
|
keys_map["rectilinear"] = smipRectilinear;
|
||||||
|
keys_map["concentric"] = smipConcentric;
|
||||||
|
}
|
||||||
|
return keys_map;
|
||||||
|
}
|
||||||
|
|
||||||
template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
|
template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
|
||||||
static t_config_enum_values keys_map;
|
static t_config_enum_values keys_map;
|
||||||
if (keys_map.empty()) {
|
if (keys_map.empty()) {
|
||||||
@ -499,6 +513,7 @@ public:
|
|||||||
ConfigOptionFloat support_material_interface_spacing;
|
ConfigOptionFloat support_material_interface_spacing;
|
||||||
ConfigOptionFloatOrPercent support_material_interface_speed;
|
ConfigOptionFloatOrPercent support_material_interface_speed;
|
||||||
ConfigOptionEnum<SupportMaterialPattern> support_material_pattern;
|
ConfigOptionEnum<SupportMaterialPattern> support_material_pattern;
|
||||||
|
ConfigOptionEnum<SupportMaterialInterfacePattern> support_material_interface_pattern;
|
||||||
// Spacing between support material lines (the hatching distance).
|
// Spacing between support material lines (the hatching distance).
|
||||||
ConfigOptionFloat support_material_spacing;
|
ConfigOptionFloat support_material_spacing;
|
||||||
ConfigOptionFloat support_material_speed;
|
ConfigOptionFloat support_material_speed;
|
||||||
@ -547,6 +562,7 @@ protected:
|
|||||||
OPT_PTR(support_material_interface_spacing);
|
OPT_PTR(support_material_interface_spacing);
|
||||||
OPT_PTR(support_material_interface_speed);
|
OPT_PTR(support_material_interface_speed);
|
||||||
OPT_PTR(support_material_pattern);
|
OPT_PTR(support_material_pattern);
|
||||||
|
OPT_PTR(support_material_interface_pattern);
|
||||||
OPT_PTR(support_material_spacing);
|
OPT_PTR(support_material_spacing);
|
||||||
OPT_PTR(support_material_speed);
|
OPT_PTR(support_material_speed);
|
||||||
OPT_PTR(support_material_synchronize_layers);
|
OPT_PTR(support_material_synchronize_layers);
|
||||||
|
@ -568,6 +568,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||||||
|| opt_key == "support_material_extruder"
|
|| opt_key == "support_material_extruder"
|
||||||
|| opt_key == "support_material_extrusion_width"
|
|| opt_key == "support_material_extrusion_width"
|
||||||
|| opt_key == "support_material_interface_layers"
|
|| opt_key == "support_material_interface_layers"
|
||||||
|
|| opt_key == "support_material_interface_pattern"
|
||||||
|| opt_key == "support_material_interface_contact_loops"
|
|| opt_key == "support_material_interface_contact_loops"
|
||||||
|| opt_key == "support_material_interface_extruder"
|
|| opt_key == "support_material_interface_extruder"
|
||||||
|| opt_key == "support_material_interface_spacing"
|
|| opt_key == "support_material_interface_spacing"
|
||||||
|
@ -572,6 +572,33 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
|||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths";
|
BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths";
|
||||||
|
|
||||||
|
#if 0 // #ifdef SLIC3R_DEBUG
|
||||||
|
{
|
||||||
|
size_t layer_id = 0;
|
||||||
|
for (int i = 0; i < int(layers_sorted.size());) {
|
||||||
|
// Find the last layer with roughly the same print_z, find the minimum layer height of all.
|
||||||
|
// Due to the floating point inaccuracies, the print_z may not be the same even if in theory they should.
|
||||||
|
int j = i + 1;
|
||||||
|
coordf_t zmax = layers_sorted[i]->print_z + EPSILON;
|
||||||
|
bool empty = true;
|
||||||
|
for (; j < layers_sorted.size() && layers_sorted[j]->print_z <= zmax; ++j)
|
||||||
|
if (!layers_sorted[j]->polygons.empty())
|
||||||
|
empty = false;
|
||||||
|
if (!empty) {
|
||||||
|
export_print_z_polygons_to_svg(
|
||||||
|
debug_out_path("support-%d-%lf-before.svg", iRun, layers_sorted[i]->print_z).c_str(),
|
||||||
|
layers_sorted.data() + i, j - i);
|
||||||
|
export_print_z_polygons_and_extrusions_to_svg(
|
||||||
|
debug_out_path("support-w-fills-%d-%lf-before.svg", iRun, layers_sorted[i]->print_z).c_str(),
|
||||||
|
layers_sorted.data() + i, j - i,
|
||||||
|
*object.support_layers()[layer_id]);
|
||||||
|
++layer_id;
|
||||||
|
}
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SLIC3R_DEBUG */
|
||||||
|
|
||||||
// Generate the actual toolpaths and save them into each layer.
|
// Generate the actual toolpaths and save them into each layer.
|
||||||
this->generate_toolpaths(object.support_layers(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
|
this->generate_toolpaths(object.support_layers(), raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers, base_interface_layers);
|
||||||
|
|
||||||
@ -1344,8 +1371,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
if (layer_id == 0) {
|
if (layer_id == 0) {
|
||||||
// This is the first object layer, so the object is being printed on a raft and
|
// This is the first object layer, so the object is being printed on a raft and
|
||||||
// we're here just to get the object footprint for the raft.
|
// we're here just to get the object footprint for the raft.
|
||||||
// We only consider contours and discard holes to get a more continuous raft.
|
#if 0
|
||||||
|
// The following line was filling excessive holes in the raft, see GH #430
|
||||||
overhang_polygons = collect_slices_outer(layer);
|
overhang_polygons = collect_slices_outer(layer);
|
||||||
|
#else
|
||||||
|
// Don't fill in the holes. The user may apply a higher raft_expansion if one wants a better 1st layer adhesion.
|
||||||
|
overhang_polygons = to_polygons(layer.lslices);
|
||||||
|
#endif
|
||||||
// Expand for better stability.
|
// Expand for better stability.
|
||||||
contact_polygons = offset(overhang_polygons, scaled<float>(m_object_config->raft_expansion.value));
|
contact_polygons = offset(overhang_polygons, scaled<float>(m_object_config->raft_expansion.value));
|
||||||
} else {
|
} else {
|
||||||
@ -2611,9 +2643,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
|||||||
}
|
}
|
||||||
} else if (columns_base != nullptr) {
|
} else if (columns_base != nullptr) {
|
||||||
// Expand the bases of the support columns in the 1st layer.
|
// Expand the bases of the support columns in the 1st layer.
|
||||||
columns_base->polygons = diff(
|
{
|
||||||
inflate_factor_1st_layer > 0 ? offset(columns_base->polygons, inflate_factor_1st_layer) : columns_base->polygons,
|
Polygons &raft = columns_base->polygons;
|
||||||
offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
Polygons trimming = offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
|
if (inflate_factor_1st_layer > SCALED_EPSILON) {
|
||||||
|
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
|
||||||
|
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / m_first_layer_flow.scaled_width())));
|
||||||
|
float step = inflate_factor_1st_layer / nsteps;
|
||||||
|
for (int i = 0; i < nsteps; ++ i)
|
||||||
|
raft = diff(offset(raft, step), trimming);
|
||||||
|
} else
|
||||||
|
raft = diff(raft, trimming);
|
||||||
|
}
|
||||||
if (contacts != nullptr)
|
if (contacts != nullptr)
|
||||||
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
||||||
if (! brim.empty()) {
|
if (! brim.empty()) {
|
||||||
@ -3573,9 +3614,15 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
};
|
};
|
||||||
std::vector<LayerCache> layer_caches(support_layers.size(), LayerCache());
|
std::vector<LayerCache> layer_caches(support_layers.size(), LayerCache());
|
||||||
|
|
||||||
|
|
||||||
|
const auto fill_type_interface =
|
||||||
|
(m_object_config->support_material_interface_pattern == smipAuto && m_slicing_params.soluble_interface) ||
|
||||||
|
m_object_config->support_material_interface_pattern == smipConcentric ?
|
||||||
|
ipConcentric : ipRectilinear;
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
|
||||||
[this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor,
|
[this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor,
|
||||||
infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
|
infill_pattern, &bbox_object, support_density, fill_type_interface, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
|
||||||
(const tbb::blocked_range<size_t>& range) {
|
(const tbb::blocked_range<size_t>& range) {
|
||||||
// Indices of the 1st layer in their respective container at the support layer height.
|
// Indices of the 1st layer in their respective container at the support layer height.
|
||||||
size_t idx_layer_bottom_contact = size_t(-1);
|
size_t idx_layer_bottom_contact = size_t(-1);
|
||||||
@ -3583,7 +3630,6 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
size_t idx_layer_intermediate = size_t(-1);
|
size_t idx_layer_intermediate = size_t(-1);
|
||||||
size_t idx_layer_interface = size_t(-1);
|
size_t idx_layer_interface = size_t(-1);
|
||||||
size_t idx_layer_base_interface = size_t(-1);
|
size_t idx_layer_base_interface = size_t(-1);
|
||||||
const auto fill_type_interface = m_slicing_params.soluble_interface ? ipConcentric : ipRectilinear;
|
|
||||||
const auto fill_type_first_layer = ipRectilinear;
|
const auto fill_type_first_layer = ipRectilinear;
|
||||||
auto filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(fill_type_interface));
|
auto filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(fill_type_interface));
|
||||||
// Filler for the 1st layer interface, if different from filler_interface.
|
// Filler for the 1st layer interface, if different from filler_interface.
|
||||||
@ -3652,21 +3698,23 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||||||
top_contact_layer.merge(std::move(interface_layer));
|
top_contact_layer.merge(std::move(interface_layer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if ( ! interface_layer.empty() && ! base_layer.empty()) {
|
if ( ! interface_layer.empty() && ! base_layer.empty()) {
|
||||||
// turn base support into interface when it's contained in our holes
|
// turn base support into interface when it's contained in our holes
|
||||||
// (this way we get wider interface anchoring)
|
// (this way we get wider interface anchoring)
|
||||||
//FIXME one wants to fill in the inner most holes of the interfaces, not all the holes.
|
//FIXME The intention of the code below is unclear. One likely wanted to just merge small islands of base layers filling in the holes
|
||||||
|
// inside interface layers, but the code below fills just too much, see GH #4570
|
||||||
Polygons islands = top_level_islands(interface_layer.layer->polygons);
|
Polygons islands = top_level_islands(interface_layer.layer->polygons);
|
||||||
polygons_append(interface_layer.layer->polygons, intersection(base_layer.layer->polygons, islands));
|
polygons_append(interface_layer.layer->polygons, intersection(base_layer.layer->polygons, islands));
|
||||||
base_layer.layer->polygons = diff(base_layer.layer->polygons, islands);
|
base_layer.layer->polygons = diff(base_layer.layer->polygons, islands);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Top and bottom contacts, interface layers.
|
// Top and bottom contacts, interface layers.
|
||||||
for (size_t i = 0; i < 3; ++ i) {
|
for (size_t i = 0; i < 3; ++ i) {
|
||||||
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
||||||
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
if (layer_ex.empty() || layer_ex.polygons_to_extrude().empty())
|
||||||
continue;
|
continue;
|
||||||
//FIXME When paralellizing, each thread shall have its own copy of the fillers.
|
|
||||||
bool interface_as_base = (&layer_ex == &interface_layer) && m_object_config->support_material_interface_layers.value == 0;
|
bool interface_as_base = (&layer_ex == &interface_layer) && m_object_config->support_material_interface_layers.value == 0;
|
||||||
//FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
|
//FIXME Bottom interfaces are extruded with the briding flow. Some bridging layers have its height slightly reduced, therefore
|
||||||
// the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
|
// the bridging flow does not quite apply. Reduce the flow to area of an ellipse? (A = pi * a * b)
|
||||||
|
@ -279,7 +279,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||||||
bool have_support_interface = config->opt_int("support_material_interface_layers") > 0;
|
bool have_support_interface = config->opt_int("support_material_interface_layers") > 0;
|
||||||
bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0;
|
bool have_support_soluble = have_support_material && config->opt_float("support_material_contact_distance") == 0;
|
||||||
for (auto el : { "support_material_pattern", "support_material_with_sheath",
|
for (auto el : { "support_material_pattern", "support_material_with_sheath",
|
||||||
"support_material_spacing", "support_material_angle", "support_material_interface_layers",
|
"support_material_spacing", "support_material_angle",
|
||||||
|
"support_material_interface_pattern", "support_material_interface_layers",
|
||||||
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
|
"dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
|
||||||
"support_material_xy_spacing" })
|
"support_material_xy_spacing" })
|
||||||
toggle_field(el, have_support_material);
|
toggle_field(el, have_support_material);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
|
#include "Tab.hpp"
|
||||||
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
@ -2033,27 +2034,6 @@ static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg, double min = -1.0,
|
|||||||
}, btn_OK->GetId());
|
}, btn_OK->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
static bool validate_custom_gcode(const std::string& gcode, const wxString& title)
|
|
||||||
{
|
|
||||||
std::vector<std::string> tags;
|
|
||||||
bool invalid = GCodeProcessor::contains_reserved_tags(gcode, 5, tags);
|
|
||||||
if (invalid) {
|
|
||||||
wxString reports = _L_PLURAL("The following line", "The following lines", tags.size());
|
|
||||||
reports += ":\n";
|
|
||||||
for (const std::string& keyword : tags) {
|
|
||||||
reports += ";" + keyword + "\n";
|
|
||||||
}
|
|
||||||
reports += _L("contain reserved keywords.") + "\n";
|
|
||||||
reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation.");
|
|
||||||
|
|
||||||
wxMessageDialog dialog(nullptr, reports, _L("Found reserved keywords in") + " " + title, wxICON_WARNING | wxOK);
|
|
||||||
dialog.ShowModal();
|
|
||||||
}
|
|
||||||
return !invalid;
|
|
||||||
}
|
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
|
|
||||||
static std::string get_custom_code(const std::string& code_in, double height)
|
static std::string get_custom_code(const std::string& code_in, double height)
|
||||||
{
|
{
|
||||||
wxString msg_text = _L("Enter custom G-code used on current layer") + ":";
|
wxString msg_text = _L("Enter custom G-code used on current layer") + ":";
|
||||||
@ -2072,7 +2052,7 @@ static std::string get_custom_code(const std::string& code_in, double height)
|
|||||||
return "";
|
return "";
|
||||||
|
|
||||||
value = dlg.GetValue().ToStdString();
|
value = dlg.GetValue().ToStdString();
|
||||||
valid = validate_custom_gcode(value, _L("Custom G-code"));
|
valid = GUI::Tab::validate_custom_gcode("Custom G-code", value);
|
||||||
} while (!valid);
|
} while (!valid);
|
||||||
return value;
|
return value;
|
||||||
#else
|
#else
|
||||||
|
@ -1210,6 +1210,8 @@ boost::any& Choice::get_value()
|
|||||||
m_value = static_cast<MachineLimitsUsage>(ret_enum);
|
m_value = static_cast<MachineLimitsUsage>(ret_enum);
|
||||||
else if (m_opt_id.compare("support_material_pattern") == 0)
|
else if (m_opt_id.compare("support_material_pattern") == 0)
|
||||||
m_value = static_cast<SupportMaterialPattern>(ret_enum);
|
m_value = static_cast<SupportMaterialPattern>(ret_enum);
|
||||||
|
else if (m_opt_id.compare("support_material_interface_pattern") == 0)
|
||||||
|
m_value = static_cast<SupportMaterialInterfacePattern>(ret_enum);
|
||||||
else if (m_opt_id.compare("seam_position") == 0)
|
else if (m_opt_id.compare("seam_position") == 0)
|
||||||
m_value = static_cast<SeamPosition>(ret_enum);
|
m_value = static_cast<SeamPosition>(ret_enum);
|
||||||
else if (m_opt_id.compare("host_type") == 0)
|
else if (m_opt_id.compare("host_type") == 0)
|
||||||
|
@ -104,7 +104,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (config.def()->get(opt_key)->type) {
|
const ConfigOptionDef *opt_def = config.def()->get(opt_key);
|
||||||
|
switch (opt_def->type) {
|
||||||
case coFloatOrPercent:{
|
case coFloatOrPercent:{
|
||||||
std::string str = boost::any_cast<std::string>(value);
|
std::string str = boost::any_cast<std::string>(value);
|
||||||
bool percent = false;
|
bool percent = false;
|
||||||
@ -176,6 +177,11 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case coEnum:{
|
case coEnum:{
|
||||||
|
#if 0
|
||||||
|
auto *opt = opt_def->default_value.get()->clone();
|
||||||
|
opt->setInt(0);
|
||||||
|
config.set_key_value(opt_key, opt);
|
||||||
|
#else
|
||||||
if (opt_key == "top_fill_pattern" ||
|
if (opt_key == "top_fill_pattern" ||
|
||||||
opt_key == "bottom_fill_pattern" ||
|
opt_key == "bottom_fill_pattern" ||
|
||||||
opt_key == "fill_pattern")
|
opt_key == "fill_pattern")
|
||||||
@ -190,6 +196,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
config.set_key_value(opt_key, new ConfigOptionEnum<MachineLimitsUsage>(boost::any_cast<MachineLimitsUsage>(value)));
|
config.set_key_value(opt_key, new ConfigOptionEnum<MachineLimitsUsage>(boost::any_cast<MachineLimitsUsage>(value)));
|
||||||
else if (opt_key.compare("support_material_pattern") == 0)
|
else if (opt_key.compare("support_material_pattern") == 0)
|
||||||
config.set_key_value(opt_key, new ConfigOptionEnum<SupportMaterialPattern>(boost::any_cast<SupportMaterialPattern>(value)));
|
config.set_key_value(opt_key, new ConfigOptionEnum<SupportMaterialPattern>(boost::any_cast<SupportMaterialPattern>(value)));
|
||||||
|
else if (opt_key.compare("support_material_interface_pattern") == 0)
|
||||||
|
config.set_key_value(opt_key, new ConfigOptionEnum<SupportMaterialInterfacePattern>(boost::any_cast<SupportMaterialInterfacePattern>(value)));
|
||||||
else if (opt_key.compare("seam_position") == 0)
|
else if (opt_key.compare("seam_position") == 0)
|
||||||
config.set_key_value(opt_key, new ConfigOptionEnum<SeamPosition>(boost::any_cast<SeamPosition>(value)));
|
config.set_key_value(opt_key, new ConfigOptionEnum<SeamPosition>(boost::any_cast<SeamPosition>(value)));
|
||||||
else if (opt_key.compare("host_type") == 0)
|
else if (opt_key.compare("host_type") == 0)
|
||||||
@ -203,6 +211,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
else if(opt_key == "brim_type")
|
else if(opt_key == "brim_type")
|
||||||
config.set_key_value(opt_key, new ConfigOptionEnum<BrimType>(boost::any_cast<BrimType>(value)));
|
config.set_key_value(opt_key, new ConfigOptionEnum<BrimType>(boost::any_cast<BrimType>(value)));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case coPoints:{
|
case coPoints:{
|
||||||
if (opt_key == "bed_shape" || opt_key == "thumbnails") {
|
if (opt_key == "bed_shape" || opt_key == "thumbnails") {
|
||||||
|
@ -35,7 +35,7 @@ static SettingsBundle FREQ_SETTINGS_BUNDLE_FFF =
|
|||||||
{ L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } },
|
{ L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } },
|
||||||
{ L("Infill") , { "fill_density", "fill_pattern" } },
|
{ L("Infill") , { "fill_density", "fill_pattern" } },
|
||||||
{ L("Support material") , { "support_material", "support_material_auto", "support_material_threshold",
|
{ L("Support material") , { "support_material", "support_material_auto", "support_material_threshold",
|
||||||
"support_material_pattern", "support_material_buildplate_only",
|
"support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only",
|
||||||
"support_material_spacing" } },
|
"support_material_spacing" } },
|
||||||
{ L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } }
|
{ L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } }
|
||||||
};
|
};
|
||||||
|
@ -548,18 +548,10 @@ void MainFrame::init_tabpanel()
|
|||||||
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, [this](wxBookCtrlEvent& evt) {
|
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, [this](wxBookCtrlEvent& evt) {
|
||||||
wxWindow* panel = m_tabpanel->GetCurrentPage();
|
wxWindow* panel = m_tabpanel->GetCurrentPage();
|
||||||
if (panel != nullptr) {
|
if (panel != nullptr) {
|
||||||
TabPrinter* printer_tab = dynamic_cast<TabPrinter*>(panel);
|
Tab* tab = dynamic_cast<Tab*>(panel);
|
||||||
if (printer_tab != nullptr) {
|
if (tab && (tab->type() == Preset::TYPE_FILAMENT || tab->type() == Preset::TYPE_PRINTER))
|
||||||
if (!printer_tab->validate_custom_gcodes())
|
if (!tab->validate_custom_gcodes())
|
||||||
evt.Veto();
|
evt.Veto();
|
||||||
return;
|
|
||||||
}
|
|
||||||
TabFilament* filament_tab = dynamic_cast<TabFilament*>(panel);
|
|
||||||
if (filament_tab != nullptr) {
|
|
||||||
if (!filament_tab->validate_custom_gcodes())
|
|
||||||
evt.Veto();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
|
@ -860,46 +860,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||||||
case coInts:
|
case coInts:
|
||||||
ret = config.opt_int(opt_key, idx);
|
ret = config.opt_int(opt_key, idx);
|
||||||
break;
|
break;
|
||||||
case coEnum:{
|
case coEnum:
|
||||||
if (opt_key == "top_fill_pattern" ||
|
ret = config.option(opt_key)->getInt();
|
||||||
opt_key == "bottom_fill_pattern" ||
|
|
||||||
opt_key == "fill_pattern" ) {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "ironing_type") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<IroningType>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "fuzzy_skin") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<FuzzySkinType>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "gcode_flavor") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<GCodeFlavor>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "machine_limits_usage") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<MachineLimitsUsage>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "support_material_pattern") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SupportMaterialPattern>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "seam_position") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "host_type") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<PrintHostType>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "display_orientation") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SLADisplayOrientation>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "support_pillar_connection_mode") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SLAPillarConnectionMode>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "printhost_authorization_type") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<AuthorizationType>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
else if (opt_key == "brim_type") {
|
|
||||||
ret = static_cast<int>(config.option<ConfigOptionEnum<BrimType>>(opt_key)->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case coPoints:
|
case coPoints:
|
||||||
if (opt_key == "bed_shape")
|
if (opt_key == "bed_shape")
|
||||||
|
@ -1511,6 +1511,7 @@ void TabPrint::build()
|
|||||||
optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf");
|
optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf");
|
||||||
optgroup->append_single_option_line("support_material_angle", category_path + "pattern-angle");
|
optgroup->append_single_option_line("support_material_angle", category_path + "pattern-angle");
|
||||||
optgroup->append_single_option_line("support_material_interface_layers", category_path + "interface-layers");
|
optgroup->append_single_option_line("support_material_interface_layers", category_path + "interface-layers");
|
||||||
|
optgroup->append_single_option_line("support_material_interface_pattern", category_path + "interface-pattern");
|
||||||
optgroup->append_single_option_line("support_material_interface_spacing", category_path + "interface-pattern-spacing");
|
optgroup->append_single_option_line("support_material_interface_spacing", category_path + "interface-pattern-spacing");
|
||||||
optgroup->append_single_option_line("support_material_interface_contact_loops", category_path + "interface-loops");
|
optgroup->append_single_option_line("support_material_interface_contact_loops", category_path + "interface-loops");
|
||||||
optgroup->append_single_option_line("support_material_buildplate_only", category_path + "support-on-build-plate-only");
|
optgroup->append_single_option_line("support_material_buildplate_only", category_path + "support-on-build-plate-only");
|
||||||
@ -1712,11 +1713,11 @@ void TabPrint::clear_pages()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
static bool validate_custom_gcode(wxWindow* parent, const wxString& title, const std::string& gcode)
|
bool Tab::validate_custom_gcode(const wxString& title, const std::string& gcode)
|
||||||
{
|
{
|
||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags;
|
||||||
bool invalid = GCodeProcessor::contains_reserved_tags(gcode, 5, tags);
|
bool invalid = GCodeProcessor::contains_reserved_tags(gcode, 5, tags);
|
||||||
if (parent != nullptr && invalid) {
|
if (invalid) {
|
||||||
wxString reports = _L_PLURAL("The following line", "The following lines", tags.size());
|
wxString reports = _L_PLURAL("The following line", "The following lines", tags.size());
|
||||||
reports += ":\n";
|
reports += ":\n";
|
||||||
for (const std::string& keyword : tags) {
|
for (const std::string& keyword : tags) {
|
||||||
@ -1725,11 +1726,17 @@ static bool validate_custom_gcode(wxWindow* parent, const wxString& title, const
|
|||||||
reports += _L("contain reserved keywords.") + "\n";
|
reports += _L("contain reserved keywords.") + "\n";
|
||||||
reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation.");
|
reports += _L("Please remove them, as they may cause problems in g-code visualization and printing time estimation.");
|
||||||
|
|
||||||
wxMessageDialog dialog(parent, reports, _L("Found reserved keywords in") + " " + title, wxICON_WARNING | wxOK);
|
wxMessageDialog dialog(wxGetApp().mainframe, reports, _L("Found reserved keywords in") + " " + _(title), wxICON_WARNING | wxOK);
|
||||||
dialog.ShowModal();
|
dialog.ShowModal();
|
||||||
}
|
}
|
||||||
return !invalid;
|
return !invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void validate_custom_gcode_cb(Tab* tab, ConfigOptionsGroupShp opt_group, const boost::any& value) {
|
||||||
|
Tab::validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(value));
|
||||||
|
tab->update_dirty();
|
||||||
|
tab->update();
|
||||||
|
}
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
|
|
||||||
void TabFilament::add_filament_overrides_page()
|
void TabFilament::add_filament_overrides_page()
|
||||||
@ -1957,7 +1964,7 @@ void TabFilament::build()
|
|||||||
optgroup = page->new_optgroup(L("Start G-code"), 0);
|
optgroup = page->new_optgroup(L("Start G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Start G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, value);
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("start_filament_gcode");
|
option = optgroup->get_option("start_filament_gcode");
|
||||||
@ -1969,7 +1976,7 @@ void TabFilament::build()
|
|||||||
optgroup = page->new_optgroup(L("End G-code"), 0);
|
optgroup = page->new_optgroup(L("End G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("End G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, value);
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("end_filament_gcode");
|
option = optgroup->get_option("end_filament_gcode");
|
||||||
@ -2086,25 +2093,6 @@ void TabFilament::clear_pages()
|
|||||||
m_cooling_description_line = nullptr;
|
m_cooling_description_line = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
bool TabFilament::validate_custom_gcodes() const
|
|
||||||
{
|
|
||||||
auto check_optgroup = [this](const wxString& title, const Slic3r::t_config_option_key& key) {
|
|
||||||
const ConfigOptionsGroupShp opt_group = m_active_page->get_optgroup(title);
|
|
||||||
return (opt_group != nullptr) ?
|
|
||||||
validate_custom_gcode((wxWindow*)this, title, boost::any_cast<std::string>(opt_group->get_value(key))) :
|
|
||||||
true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool valid = true;
|
|
||||||
if (m_active_page->title() == L("Custom G-code")) {
|
|
||||||
valid &= check_optgroup(L("Start G-code"), "start_filament_gcode");
|
|
||||||
valid &= check_optgroup(L("End G-code"), "end_filament_gcode");
|
|
||||||
}
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
|
|
||||||
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText, wxString text /*= wxEmptyString*/)
|
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText, wxString text /*= wxEmptyString*/)
|
||||||
{
|
{
|
||||||
*StaticText = new ogStaticText(parent, text);
|
*StaticText = new ogStaticText(parent, text);
|
||||||
@ -2295,7 +2283,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Start G-code"), 0);
|
optgroup = page->new_optgroup(L("Start G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Start G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("start_gcode");
|
option = optgroup->get_option("start_gcode");
|
||||||
@ -2307,7 +2295,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("End G-code"), 0);
|
optgroup = page->new_optgroup(L("End G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("End G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("end_gcode");
|
option = optgroup->get_option("end_gcode");
|
||||||
@ -2319,7 +2307,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Before layer change G-code"), 0);
|
optgroup = page->new_optgroup(L("Before layer change G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Before layer change G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("before_layer_gcode");
|
option = optgroup->get_option("before_layer_gcode");
|
||||||
@ -2331,7 +2319,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("After layer change G-code"), 0);
|
optgroup = page->new_optgroup(L("After layer change G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("After layer change G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("layer_gcode");
|
option = optgroup->get_option("layer_gcode");
|
||||||
@ -2343,7 +2331,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Tool change G-code"), 0);
|
optgroup = page->new_optgroup(L("Tool change G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Tool change G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("toolchange_gcode");
|
option = optgroup->get_option("toolchange_gcode");
|
||||||
@ -2355,7 +2343,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0);
|
optgroup = page->new_optgroup(L("Between objects G-code (for sequential printing)"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Between objects G-code (for sequential printing)"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("between_objects_gcode");
|
option = optgroup->get_option("between_objects_gcode");
|
||||||
@ -2367,7 +2355,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Color Change G-code"), 0);
|
optgroup = page->new_optgroup(L("Color Change G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Color Change G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("color_change_gcode");
|
option = optgroup->get_option("color_change_gcode");
|
||||||
@ -2378,7 +2366,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Pause Print G-code"), 0);
|
optgroup = page->new_optgroup(L("Pause Print G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Pause Print G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("pause_print_gcode");
|
option = optgroup->get_option("pause_print_gcode");
|
||||||
@ -2389,7 +2377,7 @@ void TabPrinter::build_fff()
|
|||||||
optgroup = page->new_optgroup(L("Template Custom G-code"), 0);
|
optgroup = page->new_optgroup(L("Template Custom G-code"), 0);
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||||
validate_custom_gcode(this, L("Template Custom G-code"), boost::any_cast<std::string>(value));
|
validate_custom_gcode_cb(this, optgroup, boost::any_cast<std::string>(value));
|
||||||
};
|
};
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
option = optgroup->get_option("template_custom_gcode");
|
option = optgroup->get_option("template_custom_gcode");
|
||||||
@ -3842,27 +3830,16 @@ void TabPrinter::apply_extruder_cnt_from_cache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
bool TabPrinter::validate_custom_gcodes() const
|
bool Tab::validate_custom_gcodes()
|
||||||
{
|
{
|
||||||
auto check_optgroup = [this](const wxString& title, const Slic3r::t_config_option_key& key) {
|
|
||||||
const ConfigOptionsGroupShp opt_group = m_active_page->get_optgroup(title);
|
|
||||||
return (opt_group != nullptr) ?
|
|
||||||
validate_custom_gcode((wxWindow*)this, title, boost::any_cast<std::string>(opt_group->get_value(key))) :
|
|
||||||
true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
if (m_printer_technology == ptFFF) {
|
if ((m_type == Preset::TYPE_FILAMENT ||
|
||||||
if (m_active_page->title() == L("Custom G-code")) {
|
(m_type == Preset::TYPE_PRINTER && static_cast<TabPrinter*>(this)->m_printer_technology == ptFFF)) &&
|
||||||
valid &= check_optgroup(L("Start G-code"), "start_gcode");
|
m_active_page->title() == "Custom G-code") {
|
||||||
valid &= check_optgroup(L("End G-code"), "end_gcode");
|
for (auto opt_group : m_active_page->m_optgroups) {
|
||||||
valid &= check_optgroup(L("Before layer change G-code"), "before_layer_gcode");
|
assert(opt_group->opt_map().size() == 1);
|
||||||
valid &= check_optgroup(L("After layer change G-code"), "layer_gcode");
|
std::string key = opt_group->opt_map().begin()->first;
|
||||||
valid &= check_optgroup(L("Tool change G-code"), "toolchange_gcode");
|
valid &= validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(opt_group->get_value(key)));
|
||||||
valid &= check_optgroup(L("Between objects G-code (for sequential printing)"), "between_objects_gcode");
|
|
||||||
valid &= check_optgroup(L("Color Change G-code"), "color_change_gcode");
|
|
||||||
valid &= check_optgroup(L("Pause Print G-code"), "pause_print_gcode");
|
|
||||||
valid &= check_optgroup(L("Template Custom G-code"), "template_custom_gcode");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
@ -348,6 +348,11 @@ public:
|
|||||||
|
|
||||||
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
|
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
|
||||||
|
|
||||||
|
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
|
static bool validate_custom_gcode(const wxString& title, const std::string& gcode);
|
||||||
|
bool validate_custom_gcodes();
|
||||||
|
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const wxString& path, widget_t widget);
|
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const wxString& path, widget_t widget);
|
||||||
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
|
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
|
||||||
@ -412,10 +417,6 @@ public:
|
|||||||
void update() override;
|
void update() override;
|
||||||
void clear_pages() override;
|
void clear_pages() override;
|
||||||
bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptFFF; }
|
bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptFFF; }
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
bool validate_custom_gcodes() const;
|
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TabPrinter : public Tab
|
class TabPrinter : public Tab
|
||||||
@ -474,10 +475,6 @@ public:
|
|||||||
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||||
void cache_extruder_cnt();
|
void cache_extruder_cnt();
|
||||||
void apply_extruder_cnt_from_cache();
|
void apply_extruder_cnt_from_cache();
|
||||||
|
|
||||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
bool validate_custom_gcodes() const;
|
|
||||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TabSLAMaterial : public Tab
|
class TabSLAMaterial : public Tab
|
||||||
|
@ -986,18 +986,17 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
|
||||||
wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConfig& config, bool is_infill = false)
|
wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConfig& config, bool is_infill = false)
|
||||||
{
|
{
|
||||||
const ConfigOptionDef& def = config.def()->options.at(opt_key);
|
const ConfigOptionDef& def = config.def()->options.at(opt_key);
|
||||||
const std::vector<std::string>& names = def.enum_labels;//ConfigOptionEnum<T>::get_enum_names();
|
const std::vector<std::string>& names = def.enum_labels;//ConfigOptionEnum<T>::get_enum_names();
|
||||||
T val = config.option<ConfigOptionEnum<T>>(opt_key)->value;
|
int val = config.option(opt_key)->getInt();
|
||||||
|
|
||||||
// Each infill doesn't use all list of infill declared in PrintConfig.hpp.
|
// Each infill doesn't use all list of infill declared in PrintConfig.hpp.
|
||||||
// So we should "convert" val to the correct one
|
// So we should "convert" val to the correct one
|
||||||
if (is_infill) {
|
if (is_infill) {
|
||||||
for (auto key_val : *def.enum_keys_map)
|
for (auto key_val : *def.enum_keys_map)
|
||||||
if ((int)key_val.second == (int)val) {
|
if (int(key_val.second) == val) {
|
||||||
auto it = std::find(def.enum_values.begin(), def.enum_values.end(), key_val.first);
|
auto it = std::find(def.enum_values.begin(), def.enum_values.end(), key_val.first);
|
||||||
if (it == def.enum_values.end())
|
if (it == def.enum_values.end())
|
||||||
return "";
|
return "";
|
||||||
@ -1005,7 +1004,7 @@ wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConf
|
|||||||
}
|
}
|
||||||
return _L("Undef");
|
return _L("Undef");
|
||||||
}
|
}
|
||||||
return from_u8(_utf8(names[static_cast<int>(val)]));
|
return from_u8(_utf8(names[val]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t get_id_from_opt_key(std::string opt_key)
|
static size_t get_id_from_opt_key(std::string opt_key)
|
||||||
@ -1128,27 +1127,10 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
case coEnum: {
|
case coEnum: {
|
||||||
if (opt_key == "top_fill_pattern" ||
|
return get_string_from_enum(opt_key, config,
|
||||||
|
opt_key == "top_fill_pattern" ||
|
||||||
opt_key == "bottom_fill_pattern" ||
|
opt_key == "bottom_fill_pattern" ||
|
||||||
opt_key == "fill_pattern")
|
opt_key == "fill_pattern");
|
||||||
return get_string_from_enum<InfillPattern>(opt_key, config, true);
|
|
||||||
if (opt_key == "gcode_flavor")
|
|
||||||
return get_string_from_enum<GCodeFlavor>(opt_key, config);
|
|
||||||
if (opt_key == "machine_limits_usage")
|
|
||||||
return get_string_from_enum<MachineLimitsUsage>(opt_key, config);
|
|
||||||
if (opt_key == "ironing_type")
|
|
||||||
return get_string_from_enum<IroningType>(opt_key, config);
|
|
||||||
if (opt_key == "support_material_pattern")
|
|
||||||
return get_string_from_enum<SupportMaterialPattern>(opt_key, config);
|
|
||||||
if (opt_key == "seam_position")
|
|
||||||
return get_string_from_enum<SeamPosition>(opt_key, config);
|
|
||||||
if (opt_key == "display_orientation")
|
|
||||||
return get_string_from_enum<SLADisplayOrientation>(opt_key, config);
|
|
||||||
if (opt_key == "support_pillar_connection_mode")
|
|
||||||
return get_string_from_enum<SLAPillarConnectionMode>(opt_key, config);
|
|
||||||
if (opt_key == "brim_type")
|
|
||||||
return get_string_from_enum<BrimType>(opt_key, config);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case coPoints: {
|
case coPoints: {
|
||||||
if (opt_key == "bed_shape") {
|
if (opt_key == "bed_shape") {
|
||||||
|
@ -43,9 +43,11 @@ plan tests => 8;
|
|||||||
my $layers_with_infill = grep $_ > 0, values %layer_infill;
|
my $layers_with_infill = grep $_ > 0, values %layer_infill;
|
||||||
is scalar(keys %layers), $layers_with_perimeters+$config->raft_layers, 'expected number of layers';
|
is scalar(keys %layers), $layers_with_perimeters+$config->raft_layers, 'expected number of layers';
|
||||||
|
|
||||||
# first infill layer is never combined, so we don't consider it
|
if ($config->raft_layers == 0) {
|
||||||
|
# first infill layer printed directly on print bed is not combined, so we don't consider it.
|
||||||
$layers_with_infill--;
|
$layers_with_infill--;
|
||||||
$layers_with_perimeters--;
|
$layers_with_perimeters--;
|
||||||
|
}
|
||||||
|
|
||||||
# we expect that infill is generated for half the number of combined layers
|
# we expect that infill is generated for half the number of combined layers
|
||||||
# plus for each single layer that was not combined (remainder)
|
# plus for each single layer that was not combined (remainder)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user