This commit is contained in:
bubnikv 2019-08-20 16:22:37 +02:00
commit 2e7d5e5bc1
17 changed files with 297 additions and 1230 deletions

View file

@ -85,13 +85,13 @@ add_executable(avrdude-conf-gen conf-generate.cpp)
# Config file embedding
add_custom_command(
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf avrdude-slic3r.conf.h
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_target(gen_conf_h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h
)
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
@ -103,6 +103,9 @@ target_link_libraries(avrdude-slic3r avrdude)
encoding_check(avrdude)
encoding_check(avrdude-slic3r)
# Make avrdude-slic3r.conf.h includable:
target_include_directories(avrdude SYSTEM PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if (WIN32)
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
if(MSVC)

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,7 @@ int main(int argc, char const *argv[])
std::cerr << "Cannot read file: " << filename_in << std::endl;
}
std::fstream output(filename_out, std::ios::out | std::ios::trunc | std::ios::binary);
std::fstream output(filename_out, std::ios::out | std::ios::trunc);
if (!output.good()) {
std::cerr << "Cannot open output file: " << filename_out << std::endl;
}

View file

@ -2887,7 +2887,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
// Set the temperature if the wipe tower didn't (not needed for non-single extruder MM)
if (m_config.single_extruder_multi_material && !m_config.wipe_tower) {
int temp = (m_layer_index == 0 ? m_config.first_layer_temperature.get_at(extruder_id) :
int temp = (m_layer_index <= 0 ? m_config.first_layer_temperature.get_at(extruder_id) :
m_config.temperature.get_at(extruder_id));
gcode += m_writer.set_temperature(temp, false);

View file

@ -2412,6 +2412,22 @@ void PrintConfigDef::init_sla_params()
def->mode = comExpert;
def->set_default_value(new ConfigOptionInt(10));
def = this->add("exposure_time_min", coFloat);
def->label = L("Minimum exposure time");
def->tooltip = L("Minimum exposure time");
def->sidetext = L("s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("exposure_time_max", coFloat);
def->label = L("Maximum exposure time");
def->tooltip = L("Maximum exposure time");
def->sidetext = L("s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(100));
def = this->add("exposure_time", coFloat);
def->label = L("Exposure time");
def->tooltip = L("Exposure time");
@ -2419,6 +2435,22 @@ void PrintConfigDef::init_sla_params()
def->min = 0;
def->set_default_value(new ConfigOptionFloat(10));
def = this->add("initial_exposure_time_min", coFloat);
def->label = L("Minimum initial exposure time");
def->tooltip = L("Minimum initial exposure time");
def->sidetext = L("s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("initial_exposure_time_max", coFloat);
def->label = L("Maximum initial exposure time");
def->tooltip = L("Maximum initial exposure time");
def->sidetext = L("s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(150));
def = this->add("initial_exposure_time", coFloat);
def->label = L("Initial exposure time");
def->tooltip = L("Initial exposure time");

View file

@ -1098,14 +1098,22 @@ class SLAMaterialConfig : public StaticPrintConfig
STATIC_PRINT_CONFIG_CACHE(SLAMaterialConfig)
public:
ConfigOptionFloat initial_layer_height;
ConfigOptionFloat exposure_time_min;
ConfigOptionFloat exposure_time_max;
ConfigOptionFloat exposure_time;
ConfigOptionFloat initial_exposure_time_min;
ConfigOptionFloat initial_exposure_time_max;
ConfigOptionFloat initial_exposure_time;
ConfigOptionFloats material_correction;
protected:
void initialize(StaticCacheBase &cache, const char *base_ptr)
{
OPT_PTR(initial_layer_height);
OPT_PTR(exposure_time_min);
OPT_PTR(exposure_time_max);
OPT_PTR(exposure_time);
OPT_PTR(initial_exposure_time_min);
OPT_PTR(initial_exposure_time_max);
OPT_PTR(initial_exposure_time);
OPT_PTR(material_correction);
}

View file

@ -692,6 +692,20 @@ std::string SLAPrint::validate() const
}
}
double expt_max = m_material_config.exposure_time_max.getFloat();
double expt_min = m_material_config.exposure_time_min.getFloat();
double expt_cur = m_material_config.exposure_time.getFloat();
if (expt_cur < expt_min || expt_cur > expt_max)
return L("Exposition time is out of predefined bounds.");
double iexpt_max = m_material_config.initial_exposure_time_max.getFloat();
double iexpt_min = m_material_config.initial_exposure_time_min.getFloat();
double iexpt_cur = m_material_config.initial_exposure_time.getFloat();
if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max)
return L("Initial exposition time is out of predefined bounds.");
return "";
}
@ -1586,7 +1600,11 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
// Cache the plenty of parameters, which influence the final rasterization only,
// or they are only notes not influencing the rasterization step.
static std::unordered_set<std::string> steps_rasterize = {
"exposure_time_min",
"exposure_time_max",
"exposure_time",
"initial_exposure_time_min",
"initial_exposure_time_max",
"initial_exposure_time",
"display_width",
"display_height",

View file

@ -25,6 +25,7 @@
#include "PresetBundle.hpp"
#include "GUI.hpp"
#include "GUI_Utils.hpp"
#include "slic3r/Config/Snapshot.hpp"
#include "slic3r/Utils/PresetUpdater.hpp"
@ -32,6 +33,10 @@ namespace Slic3r {
namespace GUI {
using Config::Snapshot;
using Config::SnapshotDB;
// Printer model picker GUI control
struct PrinterPickerEvent : public wxEvent
@ -1025,15 +1030,33 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
bool snapshot = true;
Snapshot::Reason snapshot_reason = Snapshot::SNAPSHOT_UPGRADE;
switch (run_reason) {
case ConfigWizard::RR_DATA_EMPTY: snapshot = false; break;
case ConfigWizard::RR_DATA_LEGACY: snapshot = true; break;
case ConfigWizard::RR_DATA_INCOMPAT: snapshot = false; break; // In this case snapshot is done by PresetUpdater with the appropriate reason
case ConfigWizard::RR_USER: snapshot = page_welcome->reset_user_profile(); break;
case ConfigWizard::RR_DATA_EMPTY:
snapshot = false;
break;
case ConfigWizard::RR_DATA_LEGACY:
snapshot = true;
break;
case ConfigWizard::RR_DATA_INCOMPAT:
// In this case snapshot has already been taken by
// PresetUpdater with the appropriate reason
snapshot = false;
break;
case ConfigWizard::RR_USER:
snapshot = page_welcome->reset_user_profile();
snapshot_reason = Snapshot::SNAPSHOT_USER;
break;
}
if (snapshot) {
SnapshotDB::singleton().take_snapshot(*app_config, snapshot_reason);
}
if (install_bundles.size() > 0) {
// Install bundles from resources.
updater->install_bundles_rsrc(std::move(install_bundles), snapshot);
// Don't create snapshot - we've already done that above if applicable.
updater->install_bundles_rsrc(std::move(install_bundles), false);
} else {
BOOST_LOG_TRIVIAL(info) << "No bundles need to be installed from resources";
}

View file

@ -1033,11 +1033,12 @@ void ColourPicker::BUILD()
// Validate the color
wxString clr_str(m_opt.get_default_value<ConfigOptionStrings>()->get_at(m_opt_idx));
wxColour clr(clr_str);
if (! clr.IsOk()) {
if (clr_str.IsEmpty() || !clr.IsOk()) {
clr = wxTransparentColour;
}
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
// // recast as a wxWindow to fit the calling convention
@ -1048,17 +1049,59 @@ void ColourPicker::BUILD()
temp->SetToolTip(get_tooltip_text(clr_str));
}
void ColourPicker::set_undef_value(wxColourPickerCtrl* field)
{
field->SetColour(wxTransparentColour);
wxButton* btn = dynamic_cast<wxButton*>(field->GetPickerCtrl());
wxBitmap bmp = btn->GetBitmap();
wxMemoryDC dc(bmp);
dc.SetTextForeground(*wxWHITE);
dc.SetFont(wxGetApp().normal_font());
const wxRect rect = wxRect(0, 0, bmp.GetWidth(), bmp.GetHeight());
dc.DrawLabel("undef", rect, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL);
dc.SelectObject(wxNullBitmap);
btn->SetBitmapLabel(bmp);
}
void ColourPicker::set_value(const boost::any& value, bool change_event)
{
m_disable_change_event = !change_event;
const wxString clr_str(boost::any_cast<wxString>(value));
auto field = dynamic_cast<wxColourPickerCtrl*>(window);
wxColour clr(clr_str);
if (clr_str.IsEmpty() || !clr.IsOk())
set_undef_value(field);
else
field->SetColour(clr);
m_disable_change_event = false;
}
boost::any& ColourPicker::get_value()
{
// boost::any m_value;
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
m_value = clr_str.ToStdString();
if (colour == wxTransparentColour)
m_value = std::string("");
else {
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
m_value = clr_str.ToStdString();
}
return m_value;
}
void ColourPicker::msw_rescale()
{
Field::msw_rescale();
wxColourPickerCtrl* field = dynamic_cast<wxColourPickerCtrl*>(window);
if (field->GetColour() == wxTransparentColour)
set_undef_value(field);
}
void PointCtrl::BUILD()
{
auto temp = new wxBoxSizer(wxHORIZONTAL);

View file

@ -404,6 +404,8 @@ public:
class ColourPicker : public Field {
using Field::Field;
void set_undef_value(wxColourPickerCtrl* field);
public:
ColourPicker(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
ColourPicker(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
@ -417,13 +419,9 @@ public:
dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(value);
m_disable_change_event = false;
}
void set_value(const boost::any& value, bool change_event = false) {
m_disable_change_event = !change_event;
dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(boost::any_cast<wxString>(value));
m_disable_change_event = false;
}
void set_value(const boost::any& value, bool change_event = false) override;
boost::any& get_value() override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };

View file

@ -134,7 +134,11 @@ ObjectList::ObjectList(wxWindow* parent) :
selection_changed();
#ifndef __WXMSW__
set_tooltip_for_item(get_mouse_position_in_control());
#endif //__WXMSW__
#endif //__WXMSW__
#ifndef __WXOSX__
list_manipulation();
#endif //__WXOSX__
});
#ifdef __WXOSX__
@ -169,7 +173,7 @@ ObjectList::ObjectList(wxWindow* parent) :
#ifdef __WXMSW__
GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) {
set_tooltip_for_item(/*event.GetPosition()*/get_mouse_position_in_control());
set_tooltip_for_item(get_mouse_position_in_control());
event.Skip();
});
#endif //__WXMSW__
@ -330,28 +334,34 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt)
* Just this->SetToolTip(tooltip) => has no effect.
*/
if (!item)
if (!item || GetSelectedItemsCount() > 1)
{
GetMainWindow()->SetToolTip(""); // hide tooltip
return;
}
if (col->GetTitle() == _(L("Editing")) && GetSelectedItemsCount()<2)
GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings")));
else if (col->GetTitle() == _("Name"))
{
#ifdef __WXMSW__
if (pt.x < 2 * wxGetApp().em_unit() || pt.x > 4 * wxGetApp().em_unit()) {
GetMainWindow()->SetToolTip(""); // hide tooltip
return;
}
wxString tooltip = "";
if (col->GetTitle() == _(L("Editing")))
#ifdef __WXOSX__
tooltip = _(L("Right button click the icon to change the object settings"));
#else
tooltip = _(L("Click the icon to change the object settings"));
#endif //__WXMSW__
else if (col->GetTitle() == " ")
#ifdef __WXOSX__
tooltip = _(L("Right button click the icon to change the object printable property"));
#else
tooltip = _(L("Click the icon to change the object printable property"));
#endif //__WXMSW__
else if (col->GetTitle() == _("Name") && (pt.x >= 2 * wxGetApp().em_unit() && pt.x <= 4 * wxGetApp().em_unit()))
{
int obj_idx, vol_idx;
get_selected_item_indexes(obj_idx, vol_idx, item);
GetMainWindow()->SetToolTip(get_mesh_errors_list(obj_idx, vol_idx));
tooltip = get_mesh_errors_list(obj_idx, vol_idx);
}
else
GetMainWindow()->SetToolTip(""); // hide tooltip
GetMainWindow()->SetToolTip(tooltip);
}
wxPoint ObjectList::get_mouse_position_in_control()
@ -744,6 +754,11 @@ void ObjectList::OnChar(wxKeyEvent& event)
#endif /* __WXOSX__ */
void ObjectList::OnContextMenu(wxDataViewEvent&)
{
list_manipulation();
}
void ObjectList::list_manipulation()
{
wxDataViewItem item;
wxDataViewColumn* col;
@ -2291,14 +2306,14 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed)
{
std::vector<bool> print_idicator(model_object->instances.size());
for (int i = 0; i < model_object->instances.size(); ++i)
print_idicator[i] = model_object->instances[i]->is_printable();
print_idicator[i] = model_object->instances[i]->printable;
const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
m_objects_model->AddInstanceChild(object_item, print_idicator);
Expand(m_objects_model->GetInstanceRootItem(object_item));
}
else
m_objects_model->SetPrintableState(model_object->instances[0]->is_printable() ? piPrintable : piUnprintable, obj_idx);
m_objects_model->SetPrintableState(model_object->instances[0]->printable ? piPrintable : piUnprintable, obj_idx);
// add settings to the object, if it has those
add_settings_item(item, &model_object->config);

View file

@ -358,6 +358,7 @@ private:
// void OnChar(wxKeyEvent& event);
#endif /* __WXOSX__ */
void OnContextMenu(wxDataViewEvent &event);
void list_manipulation();
void OnBeginDrag(wxDataViewEvent &event);
void OnDropPossible(wxDataViewEvent &event);

View file

@ -290,7 +290,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("extruder_colour")->clone());
wxColour clr(colors->values[extruder_idx]);
if (!clr.IsOk())
clr = wxTransparentColour;
clr = wxColour(0,0,0); // Don't set alfa to transparence
auto data = new wxColourData();
data->SetChooseFull(1);
@ -4602,6 +4602,30 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
bool update_scheduled = false;
bool bed_shape_changed = false;
for (auto opt_key : p->config->diff(config)) {
if (opt_key == "filament_colour")
{
update_scheduled = true; // update should be scheduled (for update 3DScene) #2738
/* There is a case, when we use filament_color instead of extruder_color (when extruder_color == "").
* Thus plater config option "filament_colour" should be filled with filament_presets values.
* Otherwise, on 3dScene will be used last edited filament color for all volumes with extruder_color == "".
*/
const std::vector<std::string> filament_presets = wxGetApp().preset_bundle->filament_presets;
if (filament_presets.size() > 1 &&
p->config->option<ConfigOptionStrings>(opt_key)->values.size() != config.option<ConfigOptionStrings>(opt_key)->values.size())
{
const PresetCollection& filaments = wxGetApp().preset_bundle->filaments;
std::vector<std::string> filament_colors;
filament_colors.reserve(filament_presets.size());
for (const std::string& filament_preset : filament_presets)
filament_colors.push_back(filaments.find_preset(filament_preset, true)->config.opt_string("filament_colour", (unsigned)0));
p->config->option<ConfigOptionStrings>(opt_key)->values = filament_colors;
continue;
}
}
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
if (opt_key == "printer_technology")
this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key));

View file

@ -500,7 +500,8 @@ const std::vector<std::string>& Preset::sla_material_options()
if (s_opts.empty()) {
s_opts = {
"initial_layer_height",
"exposure_time", "initial_exposure_time",
"exposure_time_min", "exposure_time_max", "exposure_time",
"initial_exposure_time_min", "initial_exposure_time_max", "initial_exposure_time",
"material_correction",
"material_notes",
"default_sla_material_profile",

View file

@ -2558,7 +2558,33 @@ void TabPrinter::build_unregular_pages()
optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx);
optgroup = page->new_optgroup(_(L("Preview")));
optgroup->append_single_option_line("extruder_colour", extruder_idx);
auto reset_to_filament_color = [this, extruder_idx](wxWindow* parent) {
add_scaled_button(parent, &m_reset_to_filament_color, "undo",
_(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT);
ScalableButton* btn = m_reset_to_filament_color;
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
btn->Bind(wxEVT_BUTTON, [this, extruder_idx](wxCommandEvent& e)
{
std::vector<std::string> colors = static_cast<const ConfigOptionStrings*>(m_config->option("extruder_colour"))->values;
colors[extruder_idx] = "";
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("extruder_colour", new ConfigOptionStrings(colors));
load_config(new_conf);
update_dirty();
update();
});
return sizer;
};
line = optgroup->create_single_option_line("extruder_colour", extruder_idx);
line.append_widget(reset_to_filament_color);
optgroup->append_line(line);
#ifdef __WXMSW__
layout_page(page);
@ -3588,7 +3614,11 @@ void TabSLAMaterial::build()
optgroup->append_single_option_line("initial_layer_height");
optgroup = page->new_optgroup(_(L("Exposure")));
optgroup->append_single_option_line("exposure_time_min");
optgroup->append_single_option_line("exposure_time_max");
optgroup->append_single_option_line("exposure_time");
optgroup->append_single_option_line("initial_exposure_time_min");
optgroup->append_single_option_line("initial_exposure_time_max");
optgroup->append_single_option_line("initial_exposure_time");
optgroup = page->new_optgroup(_(L("Corrections")));
@ -3653,11 +3683,59 @@ void TabSLAMaterial::reload_config()
Tab::reload_config();
}
namespace {
enum e_cmp {EQUAL = 1, SMALLER = 2, GREATER = 4, SMALLER_EQ = 3, GREATER_EQ = 5};
void bound_check(Tab &tb, e_cmp cmp, const char *id, const char *boundid)
{
double bound = tb.m_config->opt_float(boundid);
double value = tb.m_config->opt_float(id);
auto boundlabel = tb.m_config->def()->get(boundid)->label;
auto valuelabel = tb.m_config->def()->get(id)->label;
double ddiff = value - bound;
int diff = ddiff < 0 ? SMALLER : (std::abs(ddiff) < EPSILON ? EQUAL : GREATER);
if ((cmp | diff) != cmp) {
wxString fmt;
switch (cmp) {
case EQUAL: fmt = _(L("%s should be equal to %s")); break;
case SMALLER: fmt = _(L("%s should be smaller than %s")); break;
case GREATER: fmt = _(L("%s should be greater than %s")); break;
case SMALLER_EQ: fmt = _(L("%s should be smaller or equal to %s")); break;
case GREATER_EQ: fmt = _(L("%s should be greater or equal to %s")); break;
}
wxString msg_text = wxString::Format(fmt, valuelabel, boundlabel);
wxMessageDialog dialog(tb.parent(), msg_text,
_(L("Value outside bounds")),
wxICON_WARNING | wxOK);
DynamicPrintConfig new_conf = *tb.m_config;
if (dialog.ShowModal() == wxID_OK)
new_conf.set_key_value(id, new ConfigOptionFloat(bound));
tb.load_config(new_conf);
}
};
}
void TabSLAMaterial::update()
{
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF)
return;
bound_check(*this, e_cmp::GREATER_EQ, "exposure_time", "exposure_time_min");
bound_check(*this, e_cmp::SMALLER_EQ, "exposure_time", "exposure_time_max");
bound_check(*this, e_cmp::GREATER_EQ, "initial_exposure_time", "initial_exposure_time_min");
bound_check(*this, e_cmp::SMALLER_EQ, "initial_exposure_time", "initial_exposure_time_max");
// #ys_FIXME. Just a template for this function
// m_update_cnt++;
// ! something to update

View file

@ -371,6 +371,7 @@ public:
wxButton* m_serial_test_btn = nullptr;
ScalableButton* m_print_host_test_btn = nullptr;
ScalableButton* m_printhost_browse_btn = nullptr;
ScalableButton* m_reset_to_filament_color = nullptr;
size_t m_extruders_count;
size_t m_extruders_count_old = 0;

View file

@ -35,6 +35,10 @@ using Slic3r::GUI::Config::Snapshot;
using Slic3r::GUI::Config::SnapshotDB;
// FIXME: Incompat bundle resolution doesn't deal with inherited user presets
namespace Slic3r {
@ -624,11 +628,17 @@ PresetUpdater::UpdateResult PresetUpdater::config_update() const
const auto res = dlg.ShowModal();
if (res == wxID_REPLACE) {
BOOST_LOG_TRIVIAL(info) << "User wants to re-configure...";
// This effectively removes the incompatible bundles:
// (snapshot is taken beforehand)
p->perform_updates(std::move(updates));
GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT);
if (! wizard.run(GUI::wxGetApp().preset_bundle, this)) {
return R_INCOMPAT_EXIT;
}
GUI::wxGetApp().load_current_presets();
return R_INCOMPAT_CONFIGURED;
} else {