This commit is contained in:
enricoturri1966 2020-12-04 15:36:41 +01:00
commit 6c8b0276e6
27 changed files with 5508 additions and 3737 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -682,7 +682,8 @@ std::string CoolingBuffer::apply_layer_cooldown(
#define EXTRUDER_CONFIG(OPT) config.OPT.get_at(m_current_extruder)
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
if (layer_id >= (size_t)EXTRUDER_CONFIG(disable_fan_first_layers)) {
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
if (int(layer_id) >= disable_fan_first_layers) {
int max_fan_speed = EXTRUDER_CONFIG(max_fan_speed);
float slowdown_below_layer_time = float(EXTRUDER_CONFIG(slowdown_below_layer_time));
float fan_below_layer_time = float(EXTRUDER_CONFIG(fan_below_layer_time));
@ -698,6 +699,17 @@ std::string CoolingBuffer::apply_layer_cooldown(
}
}
bridge_fan_speed = EXTRUDER_CONFIG(bridge_fan_speed);
// Is the fan speed ramp enabled?
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
// When ramping up fan speed from disable_fan_first_layers to full_fan_speed_layer, force disable_fan_first_layers above zero,
// so there will be a zero fan speed at least at the 1st layer.
disable_fan_first_layers = std::max(disable_fan_first_layers, 1);
if (int(layer_id) >= disable_fan_first_layers && int(layer_id) + 1 < full_fan_speed_layer) {
// Ramp up the fan speed from disable_fan_first_layers to full_fan_speed_layer.
float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers);
fan_speed_new = clamp(0, 255, int(float(fan_speed_new ) * factor + 0.5f));
bridge_fan_speed = clamp(0, 255, int(float(bridge_fan_speed) * factor + 0.5f));
}
#undef EXTRUDER_CONFIG
bridge_fan_control = bridge_fan_speed > fan_speed_new;
} else {

View File

@ -9,7 +9,7 @@
#define FLAVOR_IS(val) this->config.gcode_flavor == val
#define FLAVOR_IS_NOT(val) this->config.gcode_flavor != val
#define COMMENT(comment) if (this->config.gcode_comments && !comment.empty()) gcode << " ; " << comment;
#define PRECISION(val, precision) std::fixed << std::setprecision(precision) << val
#define PRECISION(val, precision) std::fixed << std::setprecision(precision) << (val)
#define XYZF_NUM(val) PRECISION(val, 3)
#define E_NUM(val) PRECISION(val, 5)
@ -458,7 +458,7 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
gcode << "G10 ; retract\n";
} else {
gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E())
<< " F" << float(m_extruder->retract_speed() * 60.);
<< " F" << XYZF_NUM(m_extruder->retract_speed() * 60.);
COMMENT(comment);
gcode << "\n";
}
@ -488,7 +488,7 @@ std::string GCodeWriter::unretract()
} else {
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
gcode << "G1 " << m_extrusion_axis << E_NUM(m_extruder->E())
<< " F" << float(m_extruder->deretract_speed() * 60.);
<< " F" << XYZF_NUM(m_extruder->deretract_speed() * 60.);
if (this->config.gcode_comments) gcode << " ; unretract";
gcode << "\n";
}

View File

@ -443,7 +443,7 @@ const std::vector<std::string>& Preset::filament_options()
"filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves",
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower",
"temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed",
"max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed",
"max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed",
"start_filament_gcode", "end_filament_gcode",
// Retract overrides
"filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel",
@ -731,8 +731,9 @@ static bool profile_print_params_same(const DynamicPrintConfig &cfg_old, const D
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
// and select it, losing previous modifications.
// In case
Preset& PresetCollection::load_external_preset(
// Only a single profile could be edited at at the same time, which introduces complexity when loading
// filament profiles for multi-extruder printers.
std::pair<Preset*, bool> PresetCollection::load_external_preset(
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
const std::string &path,
// Name of the profile, derived from the source file name.
@ -742,14 +743,23 @@ Preset& PresetCollection::load_external_preset(
// Config to initialize the preset from.
const DynamicPrintConfig &config,
// Select the preset after loading?
bool select)
LoadAndSelect select)
{
// Load the preset over a default preset, so that the missing fields are filled in from the default preset.
DynamicPrintConfig cfg(this->default_preset_for(config).config);
cfg.apply_only(config, cfg.keys(), true);
std::string &inherits = Preset::inherits(cfg);
if (select == LoadAndSelect::Never) {
// Some filament profile has been selected and modified already.
// Check whether this profile is equal to the modified edited profile.
const Preset &edited = this->get_edited_preset();
if ((edited.name == original_name || edited.name == inherits) && profile_print_params_same(edited.config, cfg))
// Just point to that already selected and edited profile.
return std::make_pair(&(*this->find_preset_internal(edited.name)), false);
}
// Is there a preset already loaded with the name stored inside the config?
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
bool found = it != m_presets.end() && it->name == original_name;
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
bool found = it != m_presets.end() && it->name == original_name;
if (! found) {
// Try to match the original_name against the "renamed_from" profile names of loaded system profiles.
it = this->find_preset_renamed(original_name);
@ -757,19 +767,40 @@ Preset& PresetCollection::load_external_preset(
}
if (found && profile_print_params_same(it->config, cfg)) {
// The preset exists and it matches the values stored inside config.
if (select)
if (select == LoadAndSelect::Always)
this->select_preset(it - m_presets.begin());
return *it;
return std::make_pair(&(*it), false);
}
// Update the "inherits" field.
std::string &inherits = Preset::inherits(cfg);
if (found && inherits.empty()) {
// There is a profile with the same name already loaded. Should we update the "inherits" field?
if (it->vendor == nullptr)
inherits = it->inherits();
else
inherits = it->name;
if (! found && select != LoadAndSelect::Never && ! inherits.empty()) {
// Try to use a system profile as a base to select the system profile
// and override its settings with the loaded ones.
assert(it == m_presets.end());
it = this->find_preset_internal(inherits);
found = it != m_presets.end() && it->name == inherits;
if (found && profile_print_params_same(it->config, cfg)) {
// The system preset exists and it matches the values stored inside config.
if (select == LoadAndSelect::Always)
this->select_preset(it - m_presets.begin());
return std::make_pair(&(*it), false);
}
}
if (found) {
if (select != LoadAndSelect::Never) {
// Select the existing preset and override it with new values, so that
// the differences will be shown in the preset editor against the referenced profile.
this->select_preset(it - m_presets.begin());
this->get_edited_preset().config.apply(config);
this->update_dirty();
assert(this->get_edited_preset().is_dirty);
return std::make_pair(&(*it), this->get_edited_preset().is_dirty);
}
if (inherits.empty()) {
// Update the "inherits" field.
// There is a profile with the same name already loaded. Should we update the "inherits" field?
inherits = it->vendor ? it->name : it->inherits();
}
}
// The external preset does not match an internal preset, load the external preset.
std::string new_name;
for (size_t idx = 0;; ++ idx) {
@ -790,19 +821,19 @@ Preset& PresetCollection::load_external_preset(
break;
if (profile_print_params_same(it->config, cfg)) {
// The preset exists and it matches the values stored inside config.
if (select)
if (select == LoadAndSelect::Always)
this->select_preset(it - m_presets.begin());
return *it;
return std::make_pair(&(*it), false);
}
// Form another profile name.
}
// Insert a new profile.
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select);
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select == LoadAndSelect::Always);
preset.is_external = true;
if (&this->get_selected_preset() == &preset)
this->get_edited_preset().is_external = true;
return preset;
return std::make_pair(&preset, false);
}
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select)

View File

@ -287,7 +287,18 @@ public:
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true);
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true);
Preset& load_external_preset(
// Returns a loaded preset, returns true if an existing preset was selected AND modified from config.
// In that case the successive filament loaded for a multi material printer should not be modified, but
// an external preset should be created instead.
enum class LoadAndSelect {
// Never select
Never,
// Always select
Always,
// Select a profile only if it was modified.
OnlyIfModified,
};
std::pair<Preset*, bool> load_external_preset(
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
const std::string &path,
// Name of the profile, derived from the source file name.
@ -297,7 +308,7 @@ public:
// Config to initialize the preset from.
const DynamicPrintConfig &config,
// Select the preset after loading?
bool select = true);
LoadAndSelect select = LoadAndSelect::Always);
// Save the preset under a new name. If the name is different from the old one,
// a new preset is stored into the list of presets.

View File

@ -49,7 +49,7 @@ PresetBundle::PresetBundle() :
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
//
// "compatible_printers", "compatible_printers_condition", "inherits",
// "print_settings_id", "filament_settings_id", "printer_settings_id",
// "print_settings_id", "filament_settings_id", "printer_settings_id", "printer_settings_id"
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
// Create the ID config keys, as they are not part of the Static print config classes.
@ -586,6 +586,7 @@ DynamicPrintConfig PresetBundle::full_fff_config() const
out.option<ConfigOptionString >("print_settings_id", true)->value = this->prints.get_selected_preset_name();
out.option<ConfigOptionStrings>("filament_settings_id", true)->values = this->filament_presets;
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
out.option<ConfigOptionString >("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_name();
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
@ -637,6 +638,7 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
out.option<ConfigOptionString >("sla_print_settings_id", true)->value = this->sla_prints.get_selected_preset_name();
out.option<ConfigOptionString >("sla_material_settings_id", true)->value = this->sla_materials.get_selected_preset_name();
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
out.option<ConfigOptionString >("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_name();
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
@ -712,6 +714,7 @@ void PresetBundle::load_config_file(const std::string &path)
}
// Load a config file from a boost property_tree. This is a private method called from load_config_file.
// is_external == false on if called from ConfigWizard
void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config)
{
PrinterTechnology printer_technology = Preset::printer_technology(config);
@ -798,14 +801,17 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
compatible_prints_condition = compatible_prints_condition_values.front();
Preset *loaded = nullptr;
if (is_external) {
loaded = &this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
auto [aloaded, modified] = this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
loaded = aloaded;
} else {
loaded = &this->filaments.load_preset(this->filaments.path_from_name(name), name, config);
// called from Config Wizard.
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config);
loaded->save();
}
this->filament_presets.clear();
this->filament_presets.emplace_back(loaded->name);
} else {
assert(is_external);
// Split the filament presets, load each of them separately.
std::vector<DynamicPrintConfig> configs(num_extruders, this->filaments.default_preset().config);
// loop through options and scatter them into configs.
@ -826,6 +832,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// To avoid incorrect selection of the first filament preset (means a value of Preset->m_idx_selected)
// in a case when next added preset take a place of previosly selected preset,
// we should add presets from last to first
bool any_modified = false;
for (int i = (int)configs.size()-1; i >= 0; i--) {
DynamicPrintConfig &cfg = configs[i];
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
@ -833,24 +840,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
cfg.opt_string("compatible_prints_condition", true) = compatible_prints_condition_values[i];
cfg.opt_string("inherits", true) = inherits_values[i + 1];
// Load all filament presets, but only select the first one in the preset dialog.
Preset *loaded = nullptr;
if (is_external)
loaded = &this->filaments.load_external_preset(name_or_path, name,
(i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "",
std::move(cfg), i == 0);
else {
// Used by the config wizard when creating a custom setup.
// Therefore this block should only be called for a single extruder.
char suffix[64];
if (i == 0)
suffix[0] = 0;
else
sprintf(suffix, "%d", (int)i);
std::string new_name = name + suffix;
loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name),
new_name, std::move(cfg), i == 0);
loaded->save();
}
auto [loaded, modified] = this->filaments.load_external_preset(name_or_path, name,
(i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "",
std::move(cfg),
i == 0 ?
PresetCollection::LoadAndSelect::Always :
any_modified ?
PresetCollection::LoadAndSelect::Never :
PresetCollection::LoadAndSelect::OnlyIfModified);
any_modified |= modified;
this->filament_presets[i] = loaded->name;
}
}
@ -864,10 +862,23 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
load_preset(this->sla_materials, 1, "sla_material_settings_id");
load_preset(this->printers, 2, "printer_settings_id");
break;
default: break;
default:
break;
}
this->update_compatible(PresetSelectCompatibleType::Never);
const std::string &physical_printer = config.option<ConfigOptionString>("physical_printer_settings_id", true)->value;
if (this->printers.get_edited_preset().is_external || physical_printer.empty()) {
this->physical_printers.unselect_printer();
} else {
// Activate the physical printer profile if possible.
PhysicalPrinter *pp = this->physical_printers.find_printer(physical_printer, true);
if (pp != nullptr && std::find(pp->preset_names.begin(), pp->preset_names.end(), this->printers.get_edited_preset().name) != pp->preset_names.end())
this->physical_printers.select_printer(*pp);
else
this->physical_printers.unselect_printer();
}
}
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.

View File

@ -70,7 +70,7 @@ public:
// Load user configuration and store it into the user profiles.
// This method is called by the configuration wizard.
void load_config(const std::string &name, DynamicPrintConfig config)
void load_config_from_wizard(const std::string &name, DynamicPrintConfig config)
{ this->load_config_file_config(name, false, std::move(config)); }
// Load configuration that comes from a model file containing configuration, such as 3MF et al.

View File

@ -93,6 +93,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"extrusion_multiplier",
"fan_always_on",
"fan_below_layer_time",
"full_fan_speed_layer",
"filament_colour",
"filament_diameter",
"filament_density",
@ -596,9 +597,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
#endif /* _DEBUG */
// Normalize the config.
new_full_config.option("print_settings_id", true);
new_full_config.option("filament_settings_id", true);
new_full_config.option("printer_settings_id", true);
new_full_config.option("print_settings_id", true);
new_full_config.option("filament_settings_id", true);
new_full_config.option("printer_settings_id", true);
new_full_config.option("physical_printer_settings_id", true);
new_full_config.normalize_fdm();
// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
@ -627,9 +629,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
if (! full_config_diff.empty()) {
update_apply_status(this->invalidate_step(psGCodeExport));
// Set the profile aliases for the PrintBase::output_filename()
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
m_placeholder_parser.set("physical_printer_preset", new_full_config.option("physical_printer_settings_id")->clone());
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
// see "Placeholders do not respect filament overrides." GH issue #3649
m_placeholder_parser.apply_config(filament_overrides);

View File

@ -981,6 +981,17 @@ void PrintConfigDef::init_fff_params()
def->max = max_temp;
def->set_default_value(new ConfigOptionInts { 200 });
def = this->add("full_fan_speed_layer", coInts);
def->label = L("Full fan speed at layer");
def->tooltip = L("Fan speed will be ramped up linearly from zero at layer \"disable_fan_first_layers\" "
"to maximum at layer \"full_fan_speed_layer\". "
"\"full_fan_speed_layer\" will be ignored if lower than \"disable_fan_first_layers\", in which case "
"the fan will be running at maximum allowed speed at layer \"disable_fan_first_layers\" + 1.");
def->min = 0;
def->max = 1000;
def->mode = comExpert;
def->set_default_value(new ConfigOptionInts { 0 });
def = this->add("gap_fill_speed", coFloat);
def->label = L("Gap fill");
def->category = L("Speed");
@ -1680,6 +1691,10 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionString(""));
def->cli = ConfigOptionDef::nocli;
def = this->add("physical_printer_settings_id", coString);
def->set_default_value(new ConfigOptionString(""));
def->cli = ConfigOptionDef::nocli;
def = this->add("raft_layers", coInt);
def->label = L("Raft layers");
def->category = L("Support material");

View File

@ -852,6 +852,7 @@ public:
ConfigOptionFloatOrPercent first_layer_extrusion_width;
ConfigOptionFloatOrPercent first_layer_speed;
ConfigOptionInts first_layer_temperature;
ConfigOptionInts full_fan_speed_layer;
ConfigOptionFloat infill_acceleration;
ConfigOptionBool infill_first;
ConfigOptionInts max_fan_speed;
@ -925,6 +926,7 @@ protected:
OPT_PTR(first_layer_extrusion_width);
OPT_PTR(first_layer_speed);
OPT_PTR(first_layer_temperature);
OPT_PTR(full_fan_speed_layer);
OPT_PTR(infill_acceleration);
OPT_PTR(infill_first);
OPT_PTR(max_fan_speed);

View File

@ -193,9 +193,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
#endif /* _DEBUG */
// Normalize the config.
config.option("sla_print_settings_id", true);
config.option("sla_material_settings_id", true);
config.option("printer_settings_id", true);
config.option("sla_print_settings_id", true);
config.option("sla_material_settings_id", true);
config.option("printer_settings_id", true);
config.option("physical_printer_settings_id", true);
// Collect changes to print config.
t_config_option_keys print_diff = m_print_config.diff(config);
t_config_option_keys printer_diff = m_printer_config.diff(config);
@ -228,9 +229,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
// update_apply_status(this->invalidate_step(slapsRasterize));
m_placeholder_parser.apply_config(config);
// Set the profile aliases for the PrintBase::output_filename()
m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone());
m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone());
m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone());
m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone());
m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone());
m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone());
m_placeholder_parser.set("physical_printer_preset", config.option("physical_printer_settings_id")->clone());
}
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.

View File

@ -88,8 +88,9 @@
//===================
#define ENABLE_2_3_0_BETA2 1
#define ENABLE_ARROW_KEYS_WITH_SLIDERS (1 && ENABLE_2_3_0_BETA2)
#define ENABLE_ARROW_KEYS_WITH_SLIDERS (1 && ENABLE_2_3_0_BETA2)
#define ENABLE_NEW_NOTIFICATIONS_FADE_OUT (1 && ENABLE_2_3_0_BETA2)
#define ENABLE_PREVIEW_TYPE_CHANGE (1 && ENABLE_2_3_0_BETA2)
#endif // _prusaslicer_technologies_h_

View File

@ -5,6 +5,7 @@
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "format.hpp"
namespace Slic3r {
namespace GUI {
@ -150,9 +151,8 @@ wxString CopyrightsDialog::get_html_text()
, entry.link, entry.lib_name);
if (!entry.copyright.empty())
text += wxString::Format(
"%s %s"
"<br/><br/>"
text += format_wxstr(
"%1% %2%<br/><br/>"
, copyright_str, entry.copyright);
}

View File

@ -2457,7 +2457,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
page_temps->apply_custom_config(*custom_config);
const std::string profile_name = page_custom->profile_name();
preset_bundle->load_config(profile_name, *custom_config);
preset_bundle->load_config_from_wizard(profile_name, *custom_config);
}
// Update the selections from the compatibilty.

View File

@ -1217,9 +1217,11 @@ wxString Control::get_tooltip(int tick/*=-1*/)
return _L("Jump to move") + " (Shift + G)";
else
return m_mode == MultiAsSingle ?
GUI::from_u8((boost::format(_u8L("Jump to height %s Set ruler mode\n or "
"Set extruder sequence for the entire print")) % " (Shift + G)\n").str()) :
GUI::from_u8((boost::format(_u8L("Jump to height %s or Set ruler mode")) % " (Shift + G)\n").str());
GUI::from_u8((boost::format(_u8L("Jump to height %s\n"
"Set ruler mode\n"
"or Set extruder sequence for the entire print")) % "(Shift + G)").str()) :
GUI::from_u8((boost::format(_u8L("Jump to height %s\n"
"or Set ruler mode")) % "(Shift + G)").str());
}
if (m_focus == fiColorBand)
return m_mode != SingleExtruder ? "" :
@ -1844,7 +1846,7 @@ void Control::show_cog_icon_context_menu()
wxMenu* ruler_mode_menu = new wxMenu();
if (ruler_mode_menu) {
append_menu_check_item(ruler_mode_menu, wxID_ANY, _L("None"), _L("Supprese show the ruler"),
append_menu_check_item(ruler_mode_menu, wxID_ANY, _L("None"), _L("Hide ruler"),
[this](wxCommandEvent&) { if (m_extra_style != 0) m_extra_style = 0; }, ruler_mode_menu,
[]() { return true; }, [this]() { return m_extra_style == 0; }, GUI::wxGetApp().plater());

View File

@ -3996,7 +3996,7 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
imgui->text(_L("Use CTRL+left mouse key to enter text edit mode:"));
if (imgui->slider_float(_L("Clearance size"), &settings.distance, dist_min, 100.0f, "%5.2f") || dist_min > settings.distance) {
if (imgui->slider_float(_L("Spacing"), &settings.distance, dist_min, 100.0f, "%5.2f") || dist_min > settings.distance) {
settings.distance = std::max(dist_min, settings.distance);
settings_out.distance = settings.distance;
appcfg->set("arrange", dist_key.c_str(), std::to_string(settings_out.distance));

View File

@ -2189,8 +2189,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
const auto object_item = m_objects_model->GetTopParent(GetSelection());
select_item(m_objects_model->AddVolumeChild(object_item, name, type,
new_volume->get_mesh_errors_count()>0));
select_item([this, object_item, name, type, new_volume]() { return m_objects_model->AddVolumeChild(object_item, name, type,
new_volume->get_mesh_errors_count() > 0); });
//#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
selection_changed();
//#endif //no __WXOSX__ //__WXMSW__
@ -2292,19 +2292,7 @@ void ObjectList::del_subobject_item(wxDataViewItem& item)
if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0)
m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item));
// If last two Instances of object is selected, show the message about impossible action
bool show_msg = false;
if (type & itInstance) {
wxDataViewItemArray instances;
m_objects_model->GetChildren(m_objects_model->GetParent(item), instances);
if (instances.Count() == 2 && IsSelected(instances[0]) && IsSelected(instances[1]))
show_msg = true;
}
m_objects_model->Delete(item);
if (show_msg)
Slic3r::GUI::show_error(nullptr, _(L("Last instance of an object cannot be deleted.")));
}
void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item)
@ -3055,24 +3043,24 @@ void ObjectList::delete_object_from_list()
if (!item)
return;
if (m_objects_model->GetParent(item) == wxDataViewItem(nullptr))
select_item(m_objects_model->Delete(item));
select_item([this, item]() { return m_objects_model->Delete(item); });
else
select_item(m_objects_model->Delete(m_objects_model->GetParent(item)));
select_item([this, item]() { return m_objects_model->Delete(m_objects_model->GetParent(item)); });
}
void ObjectList::delete_object_from_list(const size_t obj_idx)
{
select_item(m_objects_model->Delete(m_objects_model->GetItemById(obj_idx)));
select_item([this, obj_idx]() { return m_objects_model->Delete(m_objects_model->GetItemById(obj_idx)); });
}
void ObjectList::delete_volume_from_list(const size_t obj_idx, const size_t vol_idx)
{
select_item(m_objects_model->Delete(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)));
select_item([this, obj_idx, vol_idx]() { return m_objects_model->Delete(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)); });
}
void ObjectList::delete_instance_from_list(const size_t obj_idx, const size_t inst_idx)
{
select_item(m_objects_model->Delete(m_objects_model->GetItemByInstanceId(obj_idx, inst_idx)));
select_item([this, obj_idx, inst_idx]() { return m_objects_model->Delete(m_objects_model->GetItemByInstanceId(obj_idx, inst_idx)); });
}
void ObjectList::delete_from_model_and_list(const ItemType type, const int obj_idx, const int sub_obj_idx)
@ -3099,6 +3087,7 @@ void ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
if (items_for_delete.empty())
return;
m_prevent_list_events = true;
for (std::vector<ItemForDelete>::const_reverse_iterator item = items_for_delete.rbegin(); item != items_for_delete.rend(); ++item)
{
if (!(item->type&(itObject | itVolume | itInstance)))
@ -3125,6 +3114,7 @@ void ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
m_objects_model->Delete(m_objects_model->GetItemByInstanceId(item->obj_idx, item->sub_obj_idx));
}
}
m_prevent_list_events = true;
part_selection_changed();
}
@ -3139,13 +3129,13 @@ void ObjectList::delete_all_objects_from_list()
void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num)
{
select_item(m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num));
select_item([this, obj_idx, num]() { return m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num); });
selection_changed();
}
void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t num)
{
select_item(m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num));
select_item([this, obj_idx, num]() { return m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num); });
}
void ObjectList::unselect_objects()
@ -3183,6 +3173,50 @@ void ObjectList::select_current_volume(int idx, int vol_idx)
m_prevent_list_events = false;
}
static void update_selection(wxDataViewItemArray& sels, ObjectList::SELECTION_MODE mode, ObjectDataViewModel* model)
{
if (mode == ObjectList::smInstance)
{
for (auto& item : sels)
{
ItemType type = model->GetItemType(item);
if (type == itObject)
continue;
if (type == itInstanceRoot) {
wxDataViewItem obj_item = model->GetParent(item);
sels.Remove(item);
sels.Add(obj_item);
update_selection(sels, mode, model);
return;
}
if (type == itInstance)
{
wxDataViewItemArray instances;
model->GetChildren(model->GetParent(item), instances);
assert(instances.Count() > 0);
size_t selected_instances_cnt = 0;
for (auto& inst : instances) {
if (sels.Index(inst) == wxNOT_FOUND)
break;
selected_instances_cnt++;
}
if (selected_instances_cnt == instances.Count())
{
wxDataViewItem obj_item = model->GetTopParent(item);
for (auto& inst : instances)
sels.Remove(inst);
sels.Add(obj_item);
update_selection(sels, mode, model);
return;
}
}
else
return;
}
}
}
void ObjectList::remove()
{
if (GetSelectedItemsCount() == 0)
@ -3218,6 +3252,10 @@ void ObjectList::remove()
parent = delete_item(GetSelection());
else
{
SELECTION_MODE sels_mode = m_selection_mode;
UnselectAll();
update_selection(sels, sels_mode, m_objects_model);
Plater::TakeSnapshot snapshot = Plater::TakeSnapshot(wxGetApp().plater(), _(L("Delete Selected")));
for (auto& item : sels)
@ -3780,6 +3818,23 @@ void ObjectList::select_item(const wxDataViewItem& item)
m_prevent_list_events = false;
}
void ObjectList::select_item(std::function<wxDataViewItem()> get_item)
{
if (!get_item)
return;
m_prevent_list_events = true;
wxDataViewItem item = get_item();
if (item.IsOk()) {
UnselectAll();
Select(item);
part_selection_changed();
}
m_prevent_list_events = false;
}
void ObjectList::select_items(const wxDataViewItemArray& sels)
{
m_prevent_list_events = true;
@ -4060,7 +4115,7 @@ void ObjectList::update_and_show_object_settings_item()
if (!item) return;
const wxDataViewItem& obj_item = m_objects_model->IsSettingsItem(item) ? m_objects_model->GetParent(item) : item;
select_item(add_settings_item(obj_item, &get_item_config(obj_item).get()));
select_item([this, obj_item](){ return add_settings_item(obj_item, &get_item_config(obj_item).get()); });
}
// Update settings item for item had it

View File

@ -385,6 +385,7 @@ public:
void update_selections();
void update_selections_on_canvas();
void select_item(const wxDataViewItem& item);
void select_item(std::function<wxDataViewItem()> get_item);
void select_items(const wxDataViewItemArray& sels);
void select_all();
void select_item_all_children();

View File

@ -172,7 +172,9 @@ Preview::Preview(
: m_config(config)
, m_process(process)
, m_gcode_result(gcode_result)
#if !ENABLE_PREVIEW_TYPE_CHANGE
, m_preferred_color_mode("feature")
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
, m_schedule_background_process(schedule_background_process_func)
{
if (init(parent, model))
@ -318,6 +320,7 @@ void Preview::set_as_dirty()
m_canvas->set_as_dirty();
}
#if !ENABLE_PREVIEW_TYPE_CHANGE
void Preview::set_number_extruders(unsigned int number_extruders)
{
if (m_number_extruders != number_extruders) {
@ -331,6 +334,7 @@ void Preview::set_number_extruders(unsigned int number_extruders)
m_preferred_color_mode = (type == tool_idx) ? "tool_or_feature" : "feature";
}
}
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
void Preview::bed_shape_changed()
{
@ -465,10 +469,19 @@ void Preview::on_size(wxSizeEvent& evt)
void Preview::on_choice_view_type(wxCommandEvent& evt)
{
#if !ENABLE_PREVIEW_TYPE_CHANGE
m_preferred_color_mode = (m_choice_view_type->GetStringSelection() == L("Tool")) ? "tool" : "feature";
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
int selection = m_choice_view_type->GetCurrentSelection();
#if ENABLE_PREVIEW_TYPE_CHANGE
if (0 <= selection && selection < static_cast<int>(GCodeViewer::EViewType::Count)) {
m_canvas->set_toolpath_view_type(static_cast<GCodeViewer::EViewType>(selection));
m_keep_current_preview_type = true;
}
#else
if (0 <= selection && selection < static_cast<int>(GCodeViewer::EViewType::Count))
m_canvas->set_toolpath_view_type(static_cast<GCodeViewer::EViewType>(selection));
#endif // ENABLE_PREVIEW_TYPE_CHANGE
refresh_print();
}
@ -505,6 +518,7 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt)
m_canvas->set_as_dirty();
}
#if !ENABLE_PREVIEW_TYPE_CHANGE
void Preview::update_view_type(bool keep_volumes)
{
const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config;
@ -526,6 +540,7 @@ void Preview::update_view_type(bool keep_volumes)
reload_print(keep_volumes);
}
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
void Preview::update_bottom_toolbar()
{
@ -582,7 +597,12 @@ wxBoxSizer* Preview::create_layers_slider_sizer()
model.custom_gcode_per_print_z = m_layers_slider->GetTicksValues();
m_schedule_background_process();
#if ENABLE_PREVIEW_TYPE_CHANGE
m_keep_current_preview_type = false;
reload_print(false);
#else
update_view_type(false);
#endif // ENABLE_PREVIEW_TYPE_CHANGE
});
return sizer;
@ -848,6 +868,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
return;
}
#if !ENABLE_PREVIEW_TYPE_CHANGE
if (m_preferred_color_mode == "tool_or_feature") {
// It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature.
// Color by feature if it is a single extruder print.
@ -860,6 +881,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
// If the->SetSelection changed the following line, revert it to "decide yourself".
m_preferred_color_mode = "tool_or_feature";
}
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
GCodeViewer::EViewType gcode_view_type = m_canvas->get_gcode_view_preview_type();
bool gcode_preview_data_valid = !m_gcode_result->moves.empty();
@ -908,6 +930,24 @@ void Preview::load_print_as_fff(bool keep_z_range)
} else
update_layers_slider(zs, keep_z_range);
}
#if ENABLE_PREVIEW_TYPE_CHANGE
unsigned int number_extruders = (unsigned int)print->extruders().size();
if (!m_keep_current_preview_type) {
const wxString choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes.empty() ?
_L("Color Print") :
(number_extruders > 1) ? _L("Tool") : _L("Feature type");
int type = m_choice_view_type->FindString(choice);
if (m_choice_view_type->GetSelection() != type) {
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count)) {
m_choice_view_type->SetSelection(type);
m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
}
}
}
#endif // ENABLE_PREVIEW_TYPE_CHANGE
}
void Preview::load_print_as_sla()

View File

@ -102,7 +102,11 @@ class Preview : public wxPanel
std::function<void()> m_schedule_background_process;
unsigned int m_number_extruders { 1 };
#if ENABLE_PREVIEW_TYPE_CHANGE
bool m_keep_current_preview_type{ false };
#else
std::string m_preferred_color_mode;
#endif // ENABLE_PREVIEW_TYPE_CHANGE
bool m_loaded { false };
@ -136,7 +140,9 @@ public:
void set_as_dirty();
#if !ENABLE_PREVIEW_TYPE_CHANGE
void set_number_extruders(unsigned int number_extruders);
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
void bed_shape_changed();
void select_view(const std::string& direction);
void set_drop_target(wxDropTarget* target);
@ -150,7 +156,9 @@ public:
void move_layers_slider(wxKeyEvent& evt);
void edit_layers_slider(wxKeyEvent& evt);
#if !ENABLE_PREVIEW_TYPE_CHANGE
void update_view_type(bool keep_volumes);
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
bool is_loaded() const { return m_loaded; }

View File

@ -204,15 +204,15 @@ void KBShortcutsDialog::fill_shortcuts()
Shortcuts preview_shortcuts = {
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
{ L("Arrow Up"), L("Move vertical slider current thumb Up") },
{ L("Arrow Down"), L("Move vertical slider current thumb Down") },
{ L("Arrow Left"), L("Move horizontal slider current thumb Left") },
{ L("Arrow Right"), L("Move horizontal slider current thumb Right") },
{ "W", L("Move vertical slider current thumb Up") },
{ "S", L("Move vertical slider current thumb Down") },
{ "A", L("Move horizontal slider current thumb Left") },
{ "D", L("Move horizontal slider current thumb Right") },
{ "X", L("Toggle vertical slider one layer mode ON/OFF") },
{ L("Arrow Up"), L("Vertical slider - Move active thumb Up") },
{ L("Arrow Down"), L("Vertical slider - Move active thumb Down") },
{ L("Arrow Left"), L("Horizontal slider - Move active thumb Left") },
{ L("Arrow Right"), L("Horizontal slider - Move active thumb Right") },
{ "W", L("Vertical slider - Move active thumb Up") },
{ "S", L("Vertical slider - Move active thumb Down") },
{ "A", L("Horizontal slider - Move active thumb Left") },
{ "D", L("Horizontal slider - Move active thumb Right") },
{ "X", L("On/Off one layer mode of the vertical slider") },
{ "L", L("Show/Hide Legend and Estimated printing time") },
#else
{ L("Arrow Up"), L("Upper layer") },
@ -227,16 +227,16 @@ void KBShortcutsDialog::fill_shortcuts()
Shortcuts layers_slider_shortcuts = {
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
{ L("Arrow Up"), L("Vertical slider - Move current thumb Up") },
{ L("Arrow Down"), L("Vertical slider - Move current thumb Down") },
{ L("Arrow Left"), L("Vertical slider - Set upper thumb to current thumb") },
{ L("Arrow Right"), L("Vertical slider - Set lower thumb to current thumb") },
{ L("Arrow Up"), L("Vertical slider - Move active thumb Up") },
{ L("Arrow Down"), L("Vertical slider - Move active thumb Down") },
{ L("Arrow Left"), L("Vertical slider - Set upper thumb as active") },
{ L("Arrow Right"), L("Vertical slider - Set lower thumb as active") },
{ "+", L("Vertical slider - Add color change marker for current layer") },
{ "-", L("Vertical slider - Delete color change marker for current layer") },
{ L("Arrow Up"), L("Horizontal slider - Set left thumb to current thumb") },
{ L("Arrow Down"), L("Horizontal slider - Set right thumb to current thumb") },
{ L("Arrow Left"), L("Horizontal slider - Move current thumb Left") },
{ L("Arrow Right"), L("Horizontal slider - Move current thumb Right") },
{ L("Arrow Up"), L("Horizontal slider - Set left thumb as active") },
{ L("Arrow Down"), L("Horizontal slider - Set right thumb as active") },
{ L("Arrow Left"), L("Horizontal slider - Move active thumb Left") },
{ L("Arrow Right"), L("Horizontal slider - Move active thumb Right") },
#else
{ L("Arrow Up"), L("Move current slider thumb Up") },
{ L("Arrow Down"), L("Move current slider thumb Down") },
@ -252,8 +252,8 @@ void KBShortcutsDialog::fill_shortcuts()
m_full_shortcuts.push_back(std::make_pair(_L("Layers Slider"), layers_slider_shortcuts));
Shortcuts sequential_slider_shortcuts = {
{ L("Arrow Left"), L("Move current slider thumb Left") },
{ L("Arrow Right"), L("Move current slider thumb Right") },
{ L("Arrow Left"), L("Move active slider thumb Left") },
{ L("Arrow Right"), L("Move active slider thumb Right") },
{ "Shift+", L("Press to speed up 5 times while moving thumb\nwith arrow keys or mouse wheel") },
{ ctrl, L("Press to speed up 5 times while moving thumb\nwith arrow keys or mouse wheel") },
};

View File

@ -623,7 +623,7 @@ void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer)
{
if (m_presets.size() == 1) {
wxString msg_text = _L("It's not possible to delete the last related preset for the printer.");
wxMessageDialog dialog(nullptr, msg_text, _L("Infornation"), wxICON_INFORMATION | wxOK);
wxMessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK);
dialog.ShowModal();
return;
}

View File

@ -1192,7 +1192,7 @@ void Sidebar::update_sliced_info_sizer()
double spool_weight = filament_preset->config.opt_float("filament_spool_weight", 0);
if (spool_weight != 0.0) {
new_label += "\n " + _L("(weight with spool)");
new_label += "\n " + _L("(including spool)");
info_text += wxString::Format(" (%.2f)\n", filament_weight + spool_weight);
}
}
@ -2056,8 +2056,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
// Preview events:
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
if (wxGetApp().is_editor()) {
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
}
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_JUMP_TO, [this](wxKeyEvent& evt) { preview->jump_layers_slider(evt); });
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_SLIDERS, [this](wxKeyEvent& evt) {
@ -5533,8 +5535,12 @@ void Plater::reslice()
if (clean_gcode_toolpaths)
reset_gcode_toolpaths();
#if ENABLE_PREVIEW_TYPE_CHANGE
p->preview->reload_print(!clean_gcode_toolpaths);
#else
// update type of preview
p->preview->update_view_type(!clean_gcode_toolpaths);
#endif // ENABLE_PREVIEW_TYPE_CHANGE
}
void Plater::reslice_SLA_supports(const ModelObject &object, bool postpone_error_messages)
@ -5773,7 +5779,9 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
}
else if(opt_key == "extruder_colour") {
update_scheduled = true;
#if !ENABLE_PREVIEW_TYPE_CHANGE
p->preview->set_number_extruders(p->config->option<ConfigOptionStrings>(opt_key)->values.size());
#endif // !ENABLE_PREVIEW_TYPE_CHANGE
p->sidebar->obj_list()->update_extruder_colors();
} else if(opt_key == "max_print_height") {
update_scheduled = true;

View File

@ -9,6 +9,7 @@
#include <wx/intl.h>
#include "GUI.hpp"
#include "format.hpp"
#include "I18N.hpp"
namespace Slic3r {
@ -18,40 +19,43 @@ std::string PresetHints::cooling_description(const Preset &preset)
{
std::string out;
if (preset.config.opt_bool("cooling", 0)) {
bool cooling = preset.config.opt_bool("cooling", 0);
int fan_below_layer_time = preset.config.opt_int("fan_below_layer_time", 0);
int full_fan_speed_layer = preset.config.opt_int("full_fan_speed_layer", 0);
if (cooling) {
int slowdown_below_layer_time = preset.config.opt_int("slowdown_below_layer_time", 0);
int min_fan_speed = preset.config.opt_int("min_fan_speed", 0);
int max_fan_speed = preset.config.opt_int("max_fan_speed", 0);
int min_print_speed = int(preset.config.opt_float("min_print_speed", 0) + 0.5);
int fan_below_layer_time = preset.config.opt_int("fan_below_layer_time", 0);
out += (boost::format(_utf8(L("If estimated layer time is below ~%1%s, "
"fan will run at %2%%% and print speed will be reduced "
"so that no less than %3%s are spent on that layer "
"(however, speed will never be reduced below %4%mm/s).")))
% slowdown_below_layer_time % max_fan_speed % slowdown_below_layer_time % min_print_speed).str();
if (fan_below_layer_time > slowdown_below_layer_time) {
out += "\n" + (boost::format(_utf8(L("If estimated layer time is greater, but still below ~%1%s, "
"fan will run at a proportionally decreasing speed between %2%%% and %3%%%.")))
% fan_below_layer_time % max_fan_speed % min_fan_speed).str();
}
out += "\n" + _utf8(L("During the other layers, fan")) + " ";
} else {
out = _utf8(L("Fan")) + " ";
out += GUI::format(_L("If estimated layer time is below ~%1%s, "
"fan will run at %2%%% and print speed will be reduced "
"so that no less than %3%s are spent on that layer "
"(however, speed will never be reduced below %4%mm/s)."),
slowdown_below_layer_time, max_fan_speed, slowdown_below_layer_time, min_print_speed);
if (fan_below_layer_time > slowdown_below_layer_time)
out += "\n" +
GUI::format(_L("If estimated layer time is greater, but still below ~%1%s, "
"fan will run at a proportionally decreasing speed between %2%%% and %3%%%."),
fan_below_layer_time, max_fan_speed, min_fan_speed);
out += "\n";
}
if (preset.config.opt_bool("fan_always_on", 0)) {
int disable_fan_first_layers = preset.config.opt_int("disable_fan_first_layers", 0);
int min_fan_speed = preset.config.opt_int("min_fan_speed", 0);
out += (boost::format(_utf8(L("will always run at %1%%%"))) % min_fan_speed).str() + " ";
if (disable_fan_first_layers > 1)
out += (boost::format(_utf8(L("except for the first %1% layers."))) % disable_fan_first_layers).str();
else if (disable_fan_first_layers == 1)
out += _utf8(L("except for the first layer."));
if (full_fan_speed_layer > disable_fan_first_layers + 1)
out += GUI::format(_L("Fan speed will be ramped from zero at layer %1% to %2%%% at layer %3%."), disable_fan_first_layers, min_fan_speed, full_fan_speed_layer);
else {
out += GUI::format(cooling ? _L("During the other layers, fan will always run at %1%%%") : _L("Fan will always run at %1%%%"), min_fan_speed) + " ";
if (disable_fan_first_layers > 1)
out += GUI::format(_L("except for the first %1% layers."), disable_fan_first_layers);
else if (disable_fan_first_layers == 1)
out += GUI::format(_L("except for the first layer."));
}
} else
out += _utf8(L("will be turned off."));
out += cooling ? _u8L("During the other layers, fan will be turned off.") : _u8L("Fan will be turned off.");
return out;
}

View File

@ -19,6 +19,7 @@
#include "I18N.hpp"
#include "../Utils/PrintHost.hpp"
#include "wxExtensions.hpp"
#include "MainFrame.hpp"
#include "libslic3r/AppConfig.hpp"
namespace fs = boost::filesystem;
@ -31,7 +32,7 @@ static const char *CONFIG_KEY_PRINT = "printhost_print";
static const char *CONFIG_KEY_GROUP = "printhost_group";
PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_print, const wxArrayString &groups)
: MsgDialog(nullptr, _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"), wxID_NONE)
: MsgDialog(static_cast<wxWindow*>(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"), wxID_NONE)
, txt_filename(new wxTextCtrl(this, wxID_ANY))
, box_print(can_start_print ? new wxCheckBox(this, wxID_ANY, _L("Start printing after upload")) : nullptr)
, combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr)
@ -77,6 +78,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr
txt_filename->SetFocus();
Fit();
CenterOnParent();
Bind(wxEVT_SHOW, [=](const wxShowEvent &) {
// Another similar case where the function only works with EVT_SHOW + CallAfter,

View File

@ -1586,7 +1586,7 @@ void TabPrint::build()
page = add_options_page(L("Output options"), "output+page_white");
optgroup = page->new_optgroup(L("Sequential printing"));
optgroup->append_single_option_line("complete_objects", "sequential-printing_124589");
line = { L("Extruder clearance (mm)"), "" };
line = { L("Extruder clearance"), "" };
line.append_option(optgroup->get_option("extruder_clearance_radius"));
line.append_option(optgroup->get_option("extruder_clearance_height"));
optgroup->append_line(line);
@ -1847,6 +1847,7 @@ void TabFilament::build()
optgroup->append_single_option_line("bridge_fan_speed", category_path + "fan-settings");
optgroup->append_single_option_line("disable_fan_first_layers", category_path + "fan-settings");
optgroup->append_single_option_line("full_fan_speed_layer", category_path + "fan-settings");
optgroup = page->new_optgroup(L("Cooling thresholds"), 25);
optgroup->append_single_option_line("fan_below_layer_time", category_path + "cooling-thresholds");
@ -1999,7 +2000,7 @@ void TabFilament::toggle_options()
for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" })
toggle_option(el, cooling);
for (auto el : { "min_fan_speed", "disable_fan_first_layers" })
for (auto el : { "min_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer" })
toggle_option(el, fan_always_on);
}