Fixed conflicts after merge with master

This commit is contained in:
Enrico Turri 2020-03-09 16:03:15 +01:00
commit 5693545d15
71 changed files with 3265 additions and 2634 deletions

View file

@ -301,15 +301,20 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
if (preset_type == Slic3r::Preset::TYPE_FILAMENT)
{
Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
int shifl_Left = 0;
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
const Preset* selected_preset = preset_bundle->filaments.find_preset(preset_bundle->filament_presets[extruder_idx]);
// Wide icons are shown if the currently selected preset is not compatible with the current printer,
// and red flag is drown in front of the selected preset.
bool wide_icons = selected_preset != nullptr && !selected_preset->is_compatible;
float scale = m_em_unit*0.1f;
int shifl_Left = wide_icons ? int(scale * 16 + 0.5) : 0;
#if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
shifl_Left = int(scale * 4 + 0.5f); // IMAGE_SPACING_RIGHT = 4 for wxBitmapComboBox -> Space left of image
shifl_Left += int(scale * 4 + 0.5f); // IMAGE_SPACING_RIGHT = 4 for wxBitmapComboBox -> Space left of image
#endif
int icon_right_pos = int(scale * (24+4) + 0.5);
int icon_right_pos = shifl_Left + int(scale * (24+4) + 0.5);
int mouse_pos = event.GetLogicalPosition(wxClientDC(this)).x;
// if (extruder_idx < 0 || event.GetLogicalPosition(wxClientDC(this)).x > 24) {
if ( extruder_idx < 0 || mouse_pos < shifl_Left || mouse_pos > icon_right_pos ) {
if (mouse_pos < shifl_Left || mouse_pos > icon_right_pos ) {
// Let the combo box process the mouse click.
event.Skip();
return;
@ -338,7 +343,7 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
cfg_new.set_key_value("extruder_colour", colors);
wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
wxGetApp().preset_bundle->update_plater_filament_ui(extruder_idx, this);
preset_bundle->update_plater_filament_ui(extruder_idx, this);
wxGetApp().plater()->on_config_change(cfg_new);
}
});
@ -881,8 +886,8 @@ Sidebar::Sidebar(Plater *parent)
};
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _(L("Send to printer")) + "\tCtrl+Shift+G");
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _(L("Remove device")));
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _(L("Export to SD card / Flash drive")));
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _(L("Remove device")) + "\tCtrl+T");
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _(L("Export to SD card / Flash drive")) + "\tCtrl+U");
// regular buttons "Slice now" and "Export G-code"
@ -1509,6 +1514,7 @@ struct Plater::priv
ret.poly.contour = std::move(p);
ret.translation = scaled(m_pos);
ret.rotation = m_rotation;
ret.priority++;
return ret;
}
} wipetower;
@ -1572,18 +1578,23 @@ struct Plater::priv
// the current bed width.
static const constexpr double LOGICAL_BED_GAP = 1. / 5.;
ArrangePolygons m_selected, m_unselected;
ArrangePolygons m_selected, m_unselected, m_unprintable;
// clear m_selected and m_unselected, reserve space for next usage
void clear_input() {
const Model &model = plater().model;
size_t count = 0; // To know how much space to reserve
for (auto obj : model.objects) count += obj->instances.size();
size_t count = 0, cunprint = 0; // To know how much space to reserve
for (auto obj : model.objects)
for (auto mi : obj->instances)
mi->printable ? count++ : cunprint++;
m_selected.clear();
m_unselected.clear();
m_unprintable.clear();
m_selected.reserve(count + 1 /* for optional wti */);
m_unselected.reserve(count + 1 /* for optional wti */);
m_unprintable.reserve(cunprint /* for optional wti */);
}
// Stride between logical beds
@ -1612,8 +1623,10 @@ struct Plater::priv
clear_input();
for (ModelObject *obj: plater().model.objects)
for (ModelInstance *mi : obj->instances)
m_selected.emplace_back(get_arrange_poly(mi));
for (ModelInstance *mi : obj->instances) {
ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable;
cont.emplace_back(get_arrange_poly(mi));
}
auto& wti = plater().updated_wipe_tower();
if (wti) m_selected.emplace_back(get_arrange_poly(&wti));
@ -1648,9 +1661,12 @@ struct Plater::priv
for (size_t i = 0; i < inst_sel.size(); ++i) {
ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]);
inst_sel[i] ?
m_selected.emplace_back(std::move(ap)) :
m_unselected.emplace_back(std::move(ap));
ArrangePolygons &cont = mo->instances[i]->printable ?
(inst_sel[i] ? m_selected :
m_unselected) :
m_unprintable;
cont.emplace_back(std::move(ap));
}
}
@ -1682,16 +1698,35 @@ struct Plater::priv
public:
using PlaterJob::PlaterJob;
int status_range() const override { return int(m_selected.size()); }
int status_range() const override
{
return int(m_selected.size() + m_unprintable.size());
}
void process() override;
void finalize() override {
// Ignore the arrange result if aborted.
if (was_canceled()) return;
// Unprintable items go to the last virtual bed
int beds = 0;
// Apply the arrange result to all selected objects
for (ArrangePolygon &ap : m_selected) ap.apply();
for (ArrangePolygon &ap : m_selected) {
beds = std::max(ap.bed_idx, beds);
ap.apply();
}
// Get the virtual beds from the unselected items
for (ArrangePolygon &ap : m_unselected)
beds = std::max(ap.bed_idx, beds);
// Move the unprintable items to the last virtual bed.
for (ArrangePolygon &ap : m_unprintable) {
ap.bed_idx += beds + 1;
ap.apply();
}
plater().update();
}
@ -1961,6 +1996,11 @@ struct Plater::priv
wxString get_project_filename(const wxString& extension = wxEmptyString) const;
void set_project_filename(const wxString& filename);
// Caching last value of show_action_buttons parameter for show_action_buttons(), so that a callback which does not know this state will not override it.
mutable bool ready_to_slice = { false };
// Flag indicating that the G-code export targets a removable device, therefore the show_action_buttons() needs to be called at any case when the background processing finishes.
bool writing_to_removable_device = { false };
private:
bool init_object_menu();
bool init_common_menu(wxMenu* menu, const bool is_part = false);
@ -1986,8 +2026,8 @@ private:
* we should call tack_snapshot just ones
* instead of calls for each action separately
* */
std::string m_last_fff_printer_profile_name;
std::string m_last_sla_printer_profile_name;
std::string m_last_fff_printer_profile_name;
std::string m_last_sla_printer_profile_name;
};
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase);
@ -2171,11 +2211,17 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
// Connect to a 3DConnextion driver (OSX).
mouse3d_controller.init();
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
this->show_action_buttons(this->ready_to_slice);
Slic3r::GUI::show_info(this->q, (boost::format(_utf8(L("Unmounting successful. The device %s(%s) can now be safely removed from the computer.")))
% evt.data.name % evt.data.path).str());
});
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) { this->show_action_buttons(this->ready_to_slice); });
// Start the background thread and register this window as a target for update events.
wxGetApp().removable_drive_manager()->init(this->q);
// Initialize the Undo / Redo stack with a first snapshot.
this->take_snapshot(_(L("New Project")));
//void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const
RemovableDriveManager::get_instance().set_drive_count_changed_callback(std::bind(&Plater::priv::show_action_buttons, this, std::placeholders::_1));
}
Plater::priv::~priv()
@ -2249,6 +2295,14 @@ void Plater::priv::update_ui_from_settings()
// $self->{buttons_sizer}->Layout;
// }
camera.set_type(wxGetApp().app_config->get("use_perspective_camera"));
if (wxGetApp().app_config->get("use_free_camera") != "1")
{
// forces camera right vector to be parallel to XY plane
if (std::abs(camera.get_dir_right()(2)) > EPSILON)
camera.look_at(camera.get_position(), camera.get_target(), Vec3d::UnitZ());
}
view3D->get_canvas3d()->update_ui_from_settings();
preview->get_canvas3d()->update_ui_from_settings();
}
@ -2842,16 +2896,21 @@ void Plater::priv::ArrangeJob::process() {
}
coord_t min_d = scaled(dist);
auto count = unsigned(m_selected.size());
auto count = unsigned(m_selected.size() + m_unprintable.size());
arrangement::BedShapeHint bedshape = plater().get_bed_shape_hint();
auto stopfn = [this]() { return was_canceled(); };
try {
arrangement::arrange(m_selected, m_unselected, min_d, bedshape,
[this, count](unsigned st) {
if (st > 0) // will not finalize after last one
update_status(int(count - st), arrangestr);
},
[this]() { return was_canceled(); });
[this, count](unsigned st) {
st += m_unprintable.size();
if (st > 0) update_status(int(count - st), arrangestr);
}, stopfn);
arrangement::arrange(m_unprintable, {}, min_d, bedshape,
[this, count](unsigned st) {
if (st > 0) update_status(int(count - st), arrangestr);
}, stopfn);
} catch (std::exception & /*e*/) {
GUI::show_error(plater().q,
_(L("Could not arrange model objects! "
@ -3717,14 +3776,9 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
sidebar->set_btn_label(ActionButtonType::abReslice, "Slice now");
show_action_buttons(true);
}
else if (wxGetApp().get_mode() == comSimple)
show_action_buttons(false);
if(!canceled && RemovableDriveManager::get_instance().get_is_writing())
{
RemovableDriveManager::get_instance().set_is_writing(false);
show_action_buttons(false);
}
else if (this->writing_to_removable_device || wxGetApp().get_mode() == comSimple)
show_action_buttons(false);
this->writing_to_removable_device = false;
}
void Plater::priv::on_layer_editing_toggled(bool enable)
@ -4295,32 +4349,36 @@ void Plater::priv::update_object_menu()
sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
}
void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const
void Plater::priv::show_action_buttons(const bool ready_to_slice) const
{
RemovableDriveManager::get_instance().set_plater_ready_to_slice(is_ready_to_slice);
// Cache this value, so that the callbacks from the RemovableDriveManager may repeat that value when calling show_action_buttons().
this->ready_to_slice = ready_to_slice;
wxWindowUpdateLocker noUpdater(sidebar);
const auto prin_host_opt = config->option<ConfigOptionString>("print_host");
const bool send_gcode_shown = prin_host_opt != nullptr && !prin_host_opt->value.empty();
bool disconnect_shown = !RemovableDriveManager::get_instance().is_last_drive_removed();
bool export_removable_shown = RemovableDriveManager::get_instance().get_drives_count() > 0;
// when a background processing is ON, export_btn and/or send_btn are showing
if (wxGetApp().app_config->get("background_processing") == "1")
{
RemovableDriveManager::RemovableDrivesStatus removable_media_status = wxGetApp().removable_drive_manager()->status();
if (sidebar->show_reslice(false) |
sidebar->show_export(true) |
sidebar->show_send(send_gcode_shown) |
sidebar->show_export_removable(export_removable_shown) |
sidebar->show_disconnect(disconnect_shown))
sidebar->show_export_removable(removable_media_status.has_removable_drives) |
sidebar->show_disconnect(removable_media_status.has_eject))
sidebar->Layout();
}
else
{
if (sidebar->show_reslice(is_ready_to_slice) |
sidebar->show_export(!is_ready_to_slice) |
sidebar->show_send(send_gcode_shown && !is_ready_to_slice) |
sidebar->show_export_removable(export_removable_shown && !is_ready_to_slice) |
sidebar->show_disconnect(disconnect_shown && !is_ready_to_slice))
RemovableDriveManager::RemovableDrivesStatus removable_media_status;
if (! ready_to_slice)
removable_media_status = wxGetApp().removable_drive_manager()->status();
if (sidebar->show_reslice(ready_to_slice) |
sidebar->show_export(!ready_to_slice) |
sidebar->show_send(send_gcode_shown && !ready_to_slice) |
sidebar->show_export_removable(!ready_to_slice && removable_media_status.has_removable_drives) |
sidebar->show_disconnect(!ready_to_slice && removable_media_status.has_eject))
sidebar->Layout();
}
}
@ -4854,51 +4912,38 @@ void Plater::export_gcode(bool prefer_removable)
return;
}
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
bool removable_drives_connected = GUI::RemovableDriveManager::get_instance().update();
if(prefer_removable)
{
if(removable_drives_connected)
{
auto start_dir_removable = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string(), true);
if (RemovableDriveManager::get_instance().is_path_on_removable_drive(start_dir_removable))
{
start_dir = start_dir_removable;
}else
{
start_dir = RemovableDriveManager::get_instance().get_drive_path();
}
}
AppConfig &appconfig = *wxGetApp().app_config;
RemovableDriveManager &removable_drive_manager = *wxGetApp().removable_drive_manager();
// Get a last save path, either to removable media or to an internal media.
std::string start_dir = appconfig.get_last_output_dir(default_output_file.parent_path().string(), prefer_removable);
if (prefer_removable) {
// Returns a path to a removable media if it exists, prefering start_dir. Update the internal removable drives database.
start_dir = removable_drive_manager.get_removable_drive_path(start_dir);
if (start_dir.empty())
// Direct user to the last internal media.
start_dir = appconfig.get_last_output_dir(default_output_file.parent_path().string(), false);
}
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
start_dir,
from_path(default_output_file.filename()),
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
);
fs::path output_path;
if (dlg.ShowModal() == wxID_OK) {
fs::path path = into_path(dlg.GetPath());
wxGetApp().app_config->update_last_output_dir(path.parent_path().string(), RemovableDriveManager::get_instance().is_path_on_removable_drive(path.parent_path().string()));
output_path = std::move(path);
{
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
start_dir,
from_path(default_output_file.filename()),
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
);
if (dlg.ShowModal() == wxID_OK)
output_path = into_path(dlg.GetPath());
}
if (! output_path.empty())
{
std::string path = output_path.string();
p->export_gcode(std::move(output_path), PrintHostJob());
RemovableDriveManager::get_instance().update(0, false);
RemovableDriveManager::get_instance().set_last_save_path(path);
RemovableDriveManager::get_instance().verify_last_save_path();
if(!RemovableDriveManager::get_instance().is_last_drive_removed())
{
RemovableDriveManager::get_instance().set_is_writing(true);
RemovableDriveManager::get_instance().erase_callbacks();
RemovableDriveManager::get_instance().add_remove_callback(std::bind(&Plater::drive_ejected_callback, this));
}
if (! output_path.empty()) {
p->export_gcode(output_path, PrintHostJob());
bool path_on_removable_media = removable_drive_manager.set_and_verify_last_save_path(output_path.string());
// Storing a path to AppConfig either as path to removable media or a path to internal media.
// is_path_on_removable_drive() is called with the "true" parameter to update its internal database as the user may have shuffled the external drives
// while the dialog was open.
appconfig.update_last_output_dir(output_path.parent_path().string(), path_on_removable_media);
p->writing_to_removable_device = path_on_removable_media;
}
}
@ -5220,28 +5265,11 @@ void Plater::send_gcode()
}
}
// Called when the Eject button is pressed.
void Plater::eject_drive()
{
RemovableDriveManager::get_instance().update(0, true);
RemovableDriveManager::get_instance().erase_callbacks();
RemovableDriveManager::get_instance().add_remove_callback(std::bind(&Plater::drive_ejected_callback, this));
RemovableDriveManager::get_instance().eject_drive(RemovableDriveManager::get_instance().get_last_save_path());
wxGetApp().removable_drive_manager()->eject_drive();
}
void Plater::drive_ejected_callback()
{
if (RemovableDriveManager::get_instance().get_did_eject())
{
RemovableDriveManager::get_instance().set_did_eject(false);
show_info(this,
(boost::format(_utf8(L("Unmounting successful. The device %s(%s) can now be safely removed from the computer.")))
% RemovableDriveManager::get_instance().get_ejected_name()
% RemovableDriveManager::get_instance().get_ejected_path()).str());
}
p->show_action_buttons(false);
}
void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(snapshot_name); }
void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); }
@ -5631,7 +5659,7 @@ void Plater::suppress_background_process(const bool stop_background_process)
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
void Plater::update_object_menu() { p->update_object_menu(); }
void Plater::show_action_buttons(const bool is_ready_to_slice) const { p->show_action_buttons(is_ready_to_slice); }
void Plater::show_action_buttons(const bool ready_to_slice) const { p->show_action_buttons(ready_to_slice); }
void Plater::copy_selection_to_clipboard()
{