Fixed conflits after merge with master
This commit is contained in:
commit
7a54c4fdfe
20 changed files with 556 additions and 160 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#define ENABLE_2_3_0_BETA2 1
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -636,9 +636,9 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
|
|||
auto ¬ification_manager = *wxGetApp().plater()->get_notification_manager();
|
||||
if (state) {
|
||||
if(error)
|
||||
notification_manager.push_plater_error_notification(text,*(wxGetApp().plater()->get_current_canvas3D()));
|
||||
notification_manager.push_plater_error_notification(text);
|
||||
else
|
||||
notification_manager.push_plater_warning_notification(text, *(wxGetApp().plater()->get_current_canvas3D()));
|
||||
notification_manager.push_plater_warning_notification(text);
|
||||
} else {
|
||||
if (error)
|
||||
notification_manager.close_plater_error_notification(text);
|
||||
|
@ -1728,8 +1728,7 @@ void GLCanvas3D::render()
|
|||
m_tooltip.render(m_mouse.position, *this);
|
||||
|
||||
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
|
||||
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width());
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(get_overlay_window_width());
|
||||
|
||||
wxGetApp().imgui()->render();
|
||||
|
||||
|
@ -2384,6 +2383,14 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
NotificationManager* notification_mgr = wxGetApp().plater()->get_notification_manager();
|
||||
if (notification_mgr->requires_update())
|
||||
notification_mgr->update_notifications();
|
||||
|
||||
m_dirty |= notification_mgr->requires_render();
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
m_dirty |= m_main_toolbar.update_items_state();
|
||||
m_dirty |= m_undoredo_toolbar.update_items_state();
|
||||
m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
|
||||
|
@ -2391,12 +2398,24 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
|
||||
m_dirty |= mouse3d_controller_applied;
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
if (!m_dirty) {
|
||||
if (notification_mgr->requires_update())
|
||||
evt.RequestMore();
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!m_dirty)
|
||||
return;
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
_refresh_if_shown_on_screen();
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
if (m_extra_frame_requested || mouse3d_controller_applied || notification_mgr->requires_update()) {
|
||||
#else
|
||||
if (m_extra_frame_requested || mouse3d_controller_applied) {
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
m_dirty = true;
|
||||
m_extra_frame_requested = false;
|
||||
evt.RequestMore();
|
||||
|
@ -2531,7 +2550,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
case WXK_BACK:
|
||||
case WXK_DELETE:
|
||||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); break;
|
||||
default: evt.Skip();
|
||||
default: evt.Skip();
|
||||
}
|
||||
}
|
||||
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
||||
|
|
|
@ -820,7 +820,7 @@ bool GUI_App::on_init_inner()
|
|||
app_config->save();
|
||||
if (this->plater_ != nullptr) {
|
||||
if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
|
||||
this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable, *(this->plater_->get_current_canvas3D()));
|
||||
this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -602,7 +602,7 @@ void Mouse3DController::disconnected()
|
|||
m_params_by_device[m_device_str] = m_params_ui;
|
||||
m_device_str.clear();
|
||||
m_connected = false;
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::Mouse3dDisconnected, *(wxGetApp().plater()->get_current_canvas3D()));
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::Mouse3dDisconnected);
|
||||
|
||||
wxGetApp().plater()->CallAfter([]() {
|
||||
Plater *plater = wxGetApp().plater();
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
static constexpr float GAP_WIDTH = 10.0f;
|
||||
static constexpr float SPACE_RIGHT_PANEL = 10.0f;
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
static constexpr float FADING_OUT_DURATION = 2.0f;
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -134,6 +137,96 @@ NotificationManager::PopNotification::PopNotification(const NotificationData &n,
|
|||
{
|
||||
//init();
|
||||
}
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width)
|
||||
{
|
||||
if (m_hidden) {
|
||||
m_top_y = initial_y - GAP_WIDTH;
|
||||
return;
|
||||
}
|
||||
|
||||
Size cnv_size = canvas.get_canvas_size();
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
|
||||
|
||||
if (m_line_height != ImGui::CalcTextSize("A").y)
|
||||
init();
|
||||
|
||||
set_next_window_size(imgui);
|
||||
|
||||
// top y of window
|
||||
m_top_y = initial_y + m_window_height;
|
||||
|
||||
ImVec2 win_pos(1.0f * (float)cnv_size.get_width() - right_gap, 1.0f * (float)cnv_size.get_height() - m_top_y);
|
||||
imgui.set_next_window_pos(win_pos.x, win_pos.y, ImGuiCond_Always, 1.0f, 0.0f);
|
||||
imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always);
|
||||
|
||||
// find if hovered
|
||||
m_hovered = false;
|
||||
if (mouse_pos.x < win_pos.x && mouse_pos.x > win_pos.x - m_window_width && mouse_pos.y > win_pos.y && mouse_pos.y < win_pos.y + m_window_height) {
|
||||
ImGui::SetNextWindowFocus();
|
||||
m_hovered = true;
|
||||
}
|
||||
|
||||
// color change based on fading out
|
||||
bool fading_pop = false;
|
||||
if (m_fading_out) {
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), m_fading_out, m_current_fade_opacity);
|
||||
fading_pop = true;
|
||||
}
|
||||
|
||||
// background color
|
||||
if (m_is_gray) {
|
||||
ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
}
|
||||
else if (m_data.level == NotificationLevel::ErrorNotification) {
|
||||
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
backcolor.x += 0.3f;
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
}
|
||||
else if (m_data.level == NotificationLevel::WarningNotification) {
|
||||
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
backcolor.x += 0.3f;
|
||||
backcolor.y += 0.15f;
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
}
|
||||
|
||||
// name of window - probably indentifies window and is shown so last_end add whitespaces according to id
|
||||
if (m_id == 0)
|
||||
m_id = m_id_provider.allocate_id();
|
||||
std::string name = "!!Ntfctn" + std::to_string(m_id);
|
||||
if (imgui.begin(name, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar)) {
|
||||
ImVec2 win_size = ImGui::GetWindowSize();
|
||||
|
||||
//FIXME: dont forget to us this for texts
|
||||
//GUI::format(_utf8(L()));
|
||||
|
||||
/*
|
||||
//countdown numbers
|
||||
ImGui::SetCursorPosX(15);
|
||||
ImGui::SetCursorPosY(15);
|
||||
imgui.text(std::to_string(m_remaining_time).c_str());
|
||||
*/
|
||||
|
||||
render_left_sign(imgui);
|
||||
render_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
|
||||
render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
|
||||
m_minimize_b_visible = false;
|
||||
if (m_multiline && m_lines_count > 3)
|
||||
render_minimize_button(imgui, win_pos.x, win_pos.y);
|
||||
}
|
||||
imgui.end();
|
||||
|
||||
if (m_is_gray || m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (fading_pop)
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
#else
|
||||
NotificationManager::PopNotification::RenderResult NotificationManager::PopNotification::render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width)
|
||||
{
|
||||
if (!m_initialized) {
|
||||
|
@ -268,6 +361,7 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
|||
ImGui::PopStyleColor();
|
||||
return ret_val;
|
||||
}
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::PopNotification::count_spaces()
|
||||
{
|
||||
//determine line width
|
||||
|
@ -528,6 +622,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
#if !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::PopNotification::render_countdown(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
/*
|
||||
|
@ -575,6 +670,7 @@ void NotificationManager::PopNotification::render_countdown(ImGuiWrapper& imgui,
|
|||
m_countdown_frame++;
|
||||
*/
|
||||
}
|
||||
#endif // !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::PopNotification::render_left_sign(ImGuiWrapper& imgui)
|
||||
{
|
||||
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
|
||||
|
@ -643,6 +739,52 @@ bool NotificationManager::PopNotification::compare_text(const std::string& text)
|
|||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::PopNotification::update_state()
|
||||
{
|
||||
if (!m_initialized)
|
||||
init();
|
||||
|
||||
if (m_hidden) {
|
||||
m_state = EState::Static;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_hovered) {
|
||||
// reset fading
|
||||
m_fading_out = false;
|
||||
m_current_fade_opacity = 1.0f;
|
||||
m_remaining_time = m_data.duration;
|
||||
}
|
||||
|
||||
if (m_counting_down) {
|
||||
if (m_fading_out && m_current_fade_opacity <= 0.0f)
|
||||
m_finished = true;
|
||||
else if (!m_fading_out && m_remaining_time == 0) {
|
||||
m_fading_out = true;
|
||||
m_fading_start = wxGetLocalTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_finished) {
|
||||
m_state = EState::Finished;
|
||||
return;
|
||||
}
|
||||
if (m_close_pending) {
|
||||
m_finished = true;
|
||||
m_state = EState::ClosePending;
|
||||
return;
|
||||
}
|
||||
if (m_fading_out) {
|
||||
if (!m_paused) {
|
||||
wxMilliClock_t curr_time = wxGetLocalTimeMillis() - m_fading_start;
|
||||
m_current_fade_opacity = std::clamp(1.0f - 0.001f * static_cast<float>(curr_time.GetValue()) / FADING_OUT_DURATION, 0.0f, 1.0f);
|
||||
}
|
||||
m_state = EState::FadingOut;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
|
||||
NotificationManager::PopNotification(n, id_provider, evt_handler)
|
||||
{
|
||||
|
@ -849,19 +991,19 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
|||
m_evt_handler(evt_handler)
|
||||
{
|
||||
}
|
||||
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp)
|
||||
void NotificationManager::push_notification(const NotificationType type, int timestamp)
|
||||
{
|
||||
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(),
|
||||
boost::bind(&NotificationData::type, boost::placeholders::_1) == type);
|
||||
assert(it != basic_notifications.end());
|
||||
if (it != basic_notifications.end())
|
||||
push_notification_data( *it, canvas, timestamp);
|
||||
push_notification_data(*it, timestamp);
|
||||
}
|
||||
void NotificationManager::push_notification(const std::string& text, GLCanvas3D& canvas, int timestamp)
|
||||
void NotificationManager::push_notification(const std::string& text, int timestamp)
|
||||
{
|
||||
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotification, 10, text }, canvas, timestamp );
|
||||
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotification, 10, text }, timestamp);
|
||||
}
|
||||
void NotificationManager::push_notification(const std::string& text, NotificationManager::NotificationLevel level, GLCanvas3D& canvas, int timestamp)
|
||||
void NotificationManager::push_notification(const std::string& text, NotificationManager::NotificationLevel level, int timestamp)
|
||||
{
|
||||
int duration = 0;
|
||||
switch (level) {
|
||||
|
@ -872,32 +1014,32 @@ void NotificationManager::push_notification(const std::string& text, Notificatio
|
|||
assert(false);
|
||||
return;
|
||||
}
|
||||
push_notification_data({ NotificationType::CustomNotification, level, duration, text }, canvas, timestamp);
|
||||
push_notification_data({ NotificationType::CustomNotification, level, duration, text }, timestamp);
|
||||
}
|
||||
void NotificationManager::push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas)
|
||||
void NotificationManager::push_slicing_error_notification(const std::string& text)
|
||||
{
|
||||
set_all_slicing_errors_gray(false);
|
||||
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, canvas, 0);
|
||||
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
|
||||
close_notification_of_type(NotificationType::SlicingComplete);
|
||||
}
|
||||
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, ObjectID oid, int warning_step)
|
||||
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ObjectID oid, int warning_step)
|
||||
{
|
||||
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text };
|
||||
|
||||
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
|
||||
notification->object_id = oid;
|
||||
notification->warning_step = warning_step;
|
||||
if (push_notification_data(std::move(notification), canvas, 0)) {
|
||||
if (push_notification_data(std::move(notification), 0)) {
|
||||
m_pop_notifications.back()->set_gray(gray);
|
||||
}
|
||||
}
|
||||
void NotificationManager::push_plater_error_notification(const std::string& text, GLCanvas3D& canvas)
|
||||
void NotificationManager::push_plater_error_notification(const std::string& text)
|
||||
{
|
||||
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, canvas, 0);
|
||||
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
|
||||
}
|
||||
void NotificationManager::push_plater_warning_notification(const std::string& text, GLCanvas3D& canvas)
|
||||
void NotificationManager::push_plater_warning_notification(const std::string& text)
|
||||
{
|
||||
push_notification_data({ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text }, canvas, 0);
|
||||
push_notification_data({ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text }, 0);
|
||||
// dissaper if in preview
|
||||
set_in_preview(m_in_preview);
|
||||
}
|
||||
|
@ -951,7 +1093,7 @@ void NotificationManager::close_slicing_errors_and_warnings()
|
|||
}
|
||||
}
|
||||
}
|
||||
void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large)
|
||||
void NotificationManager::push_slicing_complete_notification(int timestamp, bool large)
|
||||
{
|
||||
std::string hypertext;
|
||||
int time = 10;
|
||||
|
@ -963,8 +1105,7 @@ void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas,
|
|||
}
|
||||
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext, [](wxEvtHandler* evnthndlr){
|
||||
if (evnthndlr != nullptr) wxPostEvent(evnthndlr, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED)); return true; } };
|
||||
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large),
|
||||
canvas, timestamp);
|
||||
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large), timestamp);
|
||||
}
|
||||
void NotificationManager::set_slicing_complete_print_time(const std::string &info)
|
||||
{
|
||||
|
@ -1001,38 +1142,41 @@ void NotificationManager::remove_slicing_warnings_of_released_objects(const std:
|
|||
notification->close();
|
||||
}
|
||||
}
|
||||
void NotificationManager::push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable)
|
||||
void NotificationManager::push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable)
|
||||
{
|
||||
close_notification_of_type(NotificationType::ExportFinished);
|
||||
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0, _u8L("Exporting finished.") +"\n"+ path };
|
||||
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path),
|
||||
canvas, 0);
|
||||
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0, _u8L("Exporting finished.") + "\n" + path };
|
||||
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
|
||||
}
|
||||
void NotificationManager::push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage)
|
||||
void NotificationManager::push_progress_bar_notification(const std::string& text, float percentage)
|
||||
{
|
||||
NotificationData data{ NotificationType::ProgressBar, NotificationLevel::ProgressBarNotification, 0, text };
|
||||
push_notification_data(std::make_unique<NotificationManager::ProgressBarNotification>(data, m_id_provider, m_evt_handler, 0),canvas, 0);
|
||||
push_notification_data(std::make_unique<NotificationManager::ProgressBarNotification>(data, m_id_provider, m_evt_handler, 0), 0);
|
||||
}
|
||||
void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas)
|
||||
void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage)
|
||||
{
|
||||
bool found = false;
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) {
|
||||
dynamic_cast<ProgressBarNotification*>(notification.get())->set_percentage(percentage);
|
||||
canvas.request_extra_frame();
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
push_progress_bar_notification(text, canvas, percentage);
|
||||
push_progress_bar_notification(text, percentage);
|
||||
}
|
||||
}
|
||||
bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp)
|
||||
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp)
|
||||
{
|
||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), canvas, timestamp);
|
||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), timestamp);
|
||||
}
|
||||
bool NotificationManager::push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, GLCanvas3D& canvas, int timestamp)
|
||||
bool NotificationManager::push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp)
|
||||
{
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
m_requires_update = true;
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
// if timestamped notif, push only new one
|
||||
if (timestamp != 0) {
|
||||
if (m_used_timestamps.find(timestamp) == m_used_timestamps.end()) {
|
||||
|
@ -1041,6 +1185,9 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||
|
||||
if (this->activate_existing(notification.get())) {
|
||||
m_pop_notifications.back()->update(notification->get_data());
|
||||
canvas.request_extra_frame();
|
||||
|
@ -1051,7 +1198,22 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||
return true;
|
||||
}
|
||||
}
|
||||
void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width)
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::render_notifications(float overlay_width)
|
||||
{
|
||||
sort_notifications();
|
||||
|
||||
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||
float last_y = 0.0f;
|
||||
|
||||
for (const auto& notification : m_pop_notifications) {
|
||||
notification->render(canvas, last_y, m_move_from_overlay && !m_in_preview, overlay_width);
|
||||
if (notification->get_state() != PopNotification::EState::Finished)
|
||||
last_y = notification->get_top() + GAP_WIDTH;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void NotificationManager::render_notifications(float overlay_width)
|
||||
{
|
||||
float last_x = 0.0f;
|
||||
float current_height = 0.0f;
|
||||
|
@ -1059,9 +1221,12 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||
bool render_main = false;
|
||||
bool hovered = false;
|
||||
sort_notifications();
|
||||
// iterate thru notifications and render them / erease them
|
||||
|
||||
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||
|
||||
// iterate thru notifications and render them / erase them
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||
if ((*it)->get_finished()) {
|
||||
if ((*it)->is_finished()) {
|
||||
it = m_pop_notifications.erase(it);
|
||||
} else {
|
||||
(*it)->set_paused(m_hovered);
|
||||
|
@ -1111,6 +1276,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||
// If any of the notifications is fading out, 100% of the CPU/GPU is consumed.
|
||||
canvas.request_extra_frame();
|
||||
}
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
void NotificationManager::sort_notifications()
|
||||
{
|
||||
|
@ -1118,7 +1284,7 @@ void NotificationManager::sort_notifications()
|
|||
std::stable_sort(m_pop_notifications.begin(), m_pop_notifications.end(), [](const std::unique_ptr<PopNotification> &n1, const std::unique_ptr<PopNotification> &n2) {
|
||||
int n1l = (int)n1->get_data().level;
|
||||
int n2l = (int)n2->get_data().level;
|
||||
if (n1l == n2l && n1->get_is_gray() && !n2->get_is_gray())
|
||||
if (n1l == n2l && n1->is_gray() && !n2->is_gray())
|
||||
return true;
|
||||
return (n1l < n2l);
|
||||
});
|
||||
|
@ -1129,7 +1295,7 @@ bool NotificationManager::activate_existing(const NotificationManager::PopNotifi
|
|||
NotificationType new_type = notification->get_type();
|
||||
const std::string &new_text = notification->get_data().text1;
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end(); ++it) {
|
||||
if ((*it)->get_type() == new_type && !(*it)->get_finished()) {
|
||||
if ((*it)->get_type() == new_type && !(*it)->is_finished()) {
|
||||
if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) {
|
||||
if (!(*it)->compare_text(new_text))
|
||||
continue;
|
||||
|
@ -1162,6 +1328,78 @@ void NotificationManager::set_in_preview(bool preview)
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void NotificationManager::update_notifications()
|
||||
{
|
||||
static size_t last_size = 0;
|
||||
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||
std::unique_ptr<PopNotification>& notification = *it;
|
||||
if (notification->get_state() == PopNotification::EState::Finished)
|
||||
it = m_pop_notifications.erase(it);
|
||||
else {
|
||||
notification->set_paused(m_hovered);
|
||||
notification->update_state();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
m_requires_update = false;
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->requires_update()) {
|
||||
m_requires_update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// update hovering state
|
||||
m_hovered = false;
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->is_hovered()) {
|
||||
m_hovered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t curr_size = m_pop_notifications.size();
|
||||
m_requires_render = m_hovered || (last_size != curr_size);
|
||||
last_size = curr_size;
|
||||
|
||||
if (!m_requires_render) {
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->requires_render()) {
|
||||
m_requires_render = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actualizate timers
|
||||
wxWindow* p = dynamic_cast<wxWindow*>(wxGetApp().plater());
|
||||
while (p->GetParent() != nullptr)
|
||||
p = p->GetParent();
|
||||
wxTopLevelWindow* top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
||||
if (!top_level_wnd->IsActive())
|
||||
return;
|
||||
|
||||
{
|
||||
// Control the fade-out.
|
||||
// time in seconds
|
||||
long now = wxGetLocalTime();
|
||||
// Pausing fade-out when the mouse is over some notification.
|
||||
if (!m_hovered && m_last_time < now) {
|
||||
if (now - m_last_time >= 1) {
|
||||
for (auto& notification : m_pop_notifications) {
|
||||
if (notification->get_state() != PopNotification::EState::Static)
|
||||
notification->substract_remaining_time();
|
||||
}
|
||||
}
|
||||
m_last_time = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
bool NotificationManager::has_slicing_error_notification()
|
||||
{
|
||||
return std::any_of(m_pop_notifications.begin(), m_pop_notifications.end(), [](auto &n) {
|
||||
|
|
|
@ -87,16 +87,16 @@ public:
|
|||
NotificationManager(wxEvtHandler* evt_handler);
|
||||
|
||||
// Push a prefabricated notification from basic_notifications (see the table at the end of this file).
|
||||
void push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp = 0);
|
||||
void push_notification(const NotificationType type, int timestamp = 0);
|
||||
// Push a NotificationType::CustomNotification with NotificationLevel::RegularNotification and 10s fade out interval.
|
||||
void push_notification(const std::string& text, GLCanvas3D& canvas, int timestamp = 0);
|
||||
void push_notification(const std::string& text, int timestamp = 0);
|
||||
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotification.
|
||||
// ErrorNotification and ImportantNotification are never faded out.
|
||||
void push_notification(const std::string& text, NotificationLevel level, GLCanvas3D& canvas, int timestamp = 0);
|
||||
void push_notification(const std::string& text, NotificationLevel level, int timestamp = 0);
|
||||
// Creates Slicing Error notification with a custom text and no fade out.
|
||||
void push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas);
|
||||
void push_slicing_error_notification(const std::string& text);
|
||||
// Creates Slicing Warning notification with a custom text and no fade out.
|
||||
void push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, ObjectID oid, int warning_step);
|
||||
void push_slicing_warning_notification(const std::string& text, bool gray, ObjectID oid, int warning_step);
|
||||
// marks slicing errors as gray
|
||||
void set_all_slicing_errors_gray(bool g);
|
||||
// marks slicing warings as gray
|
||||
|
@ -108,39 +108,45 @@ public:
|
|||
// living_oids is expected to be sorted.
|
||||
void remove_slicing_warnings_of_released_objects(const std::vector<ObjectID>& living_oids);
|
||||
// Object partially outside of the printer working space, cannot print. No fade out.
|
||||
void push_plater_error_notification(const std::string& text, GLCanvas3D& canvas);
|
||||
void push_plater_error_notification(const std::string& text);
|
||||
// Object fully out of the printer working space and such. No fade out.
|
||||
void push_plater_warning_notification(const std::string& text, GLCanvas3D& canvas);
|
||||
void push_plater_warning_notification(const std::string& text);
|
||||
// Closes error or warning of the same text
|
||||
void close_plater_error_notification(const std::string& text);
|
||||
void close_plater_warning_notification(const std::string& text);
|
||||
// Creates special notification slicing complete.
|
||||
// If large = true (Plater side bar is closed), then printing time and export button is shown
|
||||
// at the notification and fade-out is disabled. Otherwise the fade out time is set to 10s.
|
||||
void push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large);
|
||||
void push_slicing_complete_notification(int timestamp, bool large);
|
||||
// Add a print time estimate to an existing SlicingComplete notification.
|
||||
void set_slicing_complete_print_time(const std::string &info);
|
||||
// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
|
||||
// the "slicing info" normally shown at the side bar.
|
||||
void set_slicing_complete_large(bool large);
|
||||
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
|
||||
void push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable);
|
||||
void push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable);
|
||||
// notification with progress bar
|
||||
void push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage = 0);
|
||||
void set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas);
|
||||
void push_progress_bar_notification(const std::string& text, float percentage = 0);
|
||||
void set_progress_bar_percentage(const std::string& text, float percentage);
|
||||
// Close old notification ExportFinished.
|
||||
void new_export_began(bool on_removable);
|
||||
// finds ExportFinished notification and closes it if it was to removable device
|
||||
void device_ejected();
|
||||
// renders notifications in queue and deletes expired ones
|
||||
void render_notifications(GLCanvas3D& canvas, float overlay_width);
|
||||
void render_notifications(float overlay_width);
|
||||
// finds and closes all notifications of given type
|
||||
void close_notification_of_type(const NotificationType type);
|
||||
// Which view is active? Plater or G-code preview? Hide warnings in G-code preview.
|
||||
void set_in_preview(bool preview);
|
||||
// Move to left to avoid colision with variable layer height gizmo.
|
||||
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
|
||||
|
||||
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void update_notifications();
|
||||
bool requires_update() const { return m_requires_update; }
|
||||
bool requires_render() const { return m_requires_render; }
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
private:
|
||||
// duration 0 means not disapearing
|
||||
struct NotificationData {
|
||||
|
@ -175,6 +181,17 @@ private:
|
|||
class PopNotification
|
||||
{
|
||||
public:
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
enum class EState
|
||||
{
|
||||
Unknown,
|
||||
Static,
|
||||
Countdown,
|
||||
FadingOut,
|
||||
ClosePending,
|
||||
Finished
|
||||
};
|
||||
#else
|
||||
enum class RenderResult
|
||||
{
|
||||
Finished,
|
||||
|
@ -183,27 +200,41 @@ private:
|
|||
Countdown,
|
||||
Hovered
|
||||
};
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
||||
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width);
|
||||
#else
|
||||
RenderResult render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width);
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
// close will dissapear notification on next render
|
||||
void close() { m_close_pending = true; }
|
||||
// data from newer notification of same type
|
||||
void update(const NotificationData& n);
|
||||
bool get_finished() const { return m_finished || m_close_pending; }
|
||||
bool is_finished() const { return m_finished || m_close_pending; }
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
bool is_hovered() const { return m_hovered; }
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
// returns top after movement
|
||||
float get_top() const { return m_top_y; }
|
||||
//returns top in actual frame
|
||||
float get_current_top() const { return m_top_y; }
|
||||
const NotificationType get_type() const { return m_data.type; }
|
||||
const NotificationData get_data() const { return m_data; }
|
||||
const bool get_is_gray() const { return m_is_gray; }
|
||||
const NotificationData get_data() const { return m_data; }
|
||||
const bool is_gray() const { return m_is_gray; }
|
||||
// Call equals one second down
|
||||
void substract_remaining_time() { m_remaining_time--; }
|
||||
void set_gray(bool g) { m_is_gray = g; }
|
||||
void set_paused(bool p) { m_paused = p; }
|
||||
bool compare_text(const std::string& text);
|
||||
void hide(bool h) { m_hidden = h; }
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void update_state();
|
||||
bool requires_render() const { return m_fading_out || m_close_pending || m_finished; }
|
||||
bool requires_update() const { return m_state != EState::Static; }
|
||||
EState get_state() const { return m_state; }
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
protected:
|
||||
// Call after every size change
|
||||
|
@ -218,9 +249,11 @@ private:
|
|||
virtual void render_close_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x , const float win_pos_y);
|
||||
#if !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
void render_countdown(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x , const float win_pos_y);
|
||||
#endif // !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
virtual void render_hypertext(ImGuiWrapper& imgui,
|
||||
const float text_x, const float text_y,
|
||||
const std::string text,
|
||||
|
@ -237,7 +270,10 @@ private:
|
|||
|
||||
// For reusing ImGUI windows.
|
||||
NotificationIDProvider &m_id_provider;
|
||||
int m_id { 0 };
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
EState m_state { EState::Unknown };
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
int m_id { 0 };
|
||||
bool m_initialized { false };
|
||||
// Main text
|
||||
std::string m_text1;
|
||||
|
@ -252,15 +288,22 @@ private:
|
|||
bool m_paused { false };
|
||||
int m_countdown_frame { 0 };
|
||||
bool m_fading_out { false };
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
wxMilliClock_t m_fading_start { 0LL };
|
||||
#else
|
||||
// total time left when fading beggins
|
||||
float m_fading_time { 0.0f };
|
||||
float m_current_fade_opacity { 1.f };
|
||||
float m_fading_time{ 0.0f };
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
float m_current_fade_opacity { 1.0f };
|
||||
// If hidden the notif is alive but not visible to user
|
||||
bool m_hidden { false };
|
||||
// m_finished = true - does not render, marked to delete
|
||||
bool m_finished { false };
|
||||
// Will go to m_finished next render
|
||||
bool m_close_pending { false };
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
bool m_hovered { false };
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
// variables to count positions correctly
|
||||
// all space without text
|
||||
float m_window_width_offset;
|
||||
|
@ -366,8 +409,8 @@ private:
|
|||
|
||||
//pushes notification into the queue of notifications that are rendered
|
||||
//can be used to create custom notification
|
||||
bool push_notification_data(const NotificationData& notification_data, GLCanvas3D& canvas, int timestamp);
|
||||
bool push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, GLCanvas3D& canvas, int timestamp);
|
||||
bool push_notification_data(const NotificationData& notification_data, int timestamp);
|
||||
bool push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp);
|
||||
//finds older notification of same type and moves it to the end of queue. returns true if found
|
||||
bool activate_existing(const NotificationManager::PopNotification* notification);
|
||||
// Put the more important notifications to the bottom of the list.
|
||||
|
@ -390,6 +433,10 @@ private:
|
|||
bool m_in_preview { false };
|
||||
// True if the layer editing is enabled in Plater, so that the notifications are shifted left of it.
|
||||
bool m_move_from_overlay { false };
|
||||
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
bool m_requires_update{ false };
|
||||
bool m_requires_render{ false };
|
||||
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||
|
||||
//prepared (basic) notifications
|
||||
const std::vector<NotificationData> basic_notifications = {
|
||||
|
|
|
@ -2115,12 +2115,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
if (evt.data.second) {
|
||||
this->show_action_buttons(this->ready_to_slice);
|
||||
notification_manager->close_notification_of_type(NotificationType::ExportFinished);
|
||||
notification_manager->push_notification(format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."),evt.data.first.name, evt.data.first.path),
|
||||
NotificationManager::NotificationLevel::RegularNotification, *q->get_current_canvas3D());
|
||||
} else {
|
||||
notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
|
||||
NotificationManager::NotificationLevel::ErrorNotification, *q->get_current_canvas3D());
|
||||
}
|
||||
notification_manager->push_notification(format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path),
|
||||
NotificationManager::NotificationLevel::RegularNotification);
|
||||
} else {
|
||||
notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
|
||||
NotificationManager::NotificationLevel::ErrorNotification);
|
||||
}
|
||||
});
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
|
||||
this->show_action_buttons(this->ready_to_slice);
|
||||
|
@ -2948,7 +2948,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||
} else {
|
||||
// The print is not valid.
|
||||
// Show error as notification.
|
||||
notification_manager->push_slicing_error_notification(err, *q->get_current_canvas3D());
|
||||
notification_manager->push_slicing_error_notification(err);
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
}
|
||||
} else if (! this->delayed_error_message.empty()) {
|
||||
|
@ -3509,7 +3509,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||
|
||||
this->statusbar()->set_progress(evt.status.percent);
|
||||
this->statusbar()->set_status_text(_(evt.status.text) + wxString::FromUTF8("…"));
|
||||
//notification_manager->set_progress_bar_percentage("Slicing progress", (float)evt.status.percent / 100.0f, *q->get_current_canvas3D());
|
||||
//notification_manager->set_progress_bar_percentage("Slicing progress", (float)evt.status.percent / 100.0f);
|
||||
}
|
||||
if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE | PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) {
|
||||
switch (this->printer_technology) {
|
||||
|
@ -3551,8 +3551,8 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||
// Now process state.warnings.
|
||||
for (auto const& warning : state.warnings) {
|
||||
if (warning.current) {
|
||||
notification_manager->push_slicing_warning_notification(warning.message, false, *q->get_current_canvas3D(), object_id, warning_step);
|
||||
add_warning(warning, object_id.id);
|
||||
notification_manager->push_slicing_warning_notification(warning.message, false, object_id, warning_step);
|
||||
add_warning(warning, object_id.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3560,7 +3560,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||
|
||||
void Plater::priv::on_slicing_completed(wxCommandEvent & evt)
|
||||
{
|
||||
notification_manager->push_slicing_complete_notification(*q->get_current_canvas3D(), evt.GetInt(), is_sidebar_collapsed());
|
||||
notification_manager->push_slicing_complete_notification(evt.GetInt(), is_sidebar_collapsed());
|
||||
switch (this->printer_technology) {
|
||||
case ptFFF:
|
||||
this->update_fff_scene();
|
||||
|
@ -3655,7 +3655,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
else
|
||||
show_error(q, message.first, message.second);
|
||||
} else
|
||||
notification_manager->push_slicing_error_notification(message.first, *q->get_current_canvas3D());
|
||||
notification_manager->push_slicing_error_notification(message.first);
|
||||
this->statusbar()->set_status_text(from_u8(message.first));
|
||||
if (evt.invalidate_plater())
|
||||
{
|
||||
|
@ -3701,10 +3701,10 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
// If writing to removable drive was scheduled, show notification with eject button
|
||||
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
|
||||
show_action_buttons(false);
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, true);
|
||||
notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, true);
|
||||
wxGetApp().removable_drive_manager()->set_exporting_finished(true);
|
||||
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, false);
|
||||
notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, false);
|
||||
}
|
||||
exporting_status = ExportingStatus::NOT_EXPORTING;
|
||||
}
|
||||
|
|
|
@ -18,40 +18,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 > fan_below_layer_time + 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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -827,7 +827,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3
|
|||
}
|
||||
} else {
|
||||
p->set_waiting_updates(updates);
|
||||
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable, *(GUI::wxGetApp().plater()->get_current_canvas3D()));
|
||||
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable);
|
||||
}
|
||||
|
||||
// MsgUpdateConfig will show after the notificaation is clicked
|
||||
|
|
Loading…
Reference in a new issue