mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 16:57:53 -06:00
Fixed conflicts after merge with master
This commit is contained in:
commit
5693545d15
71 changed files with 3265 additions and 2634 deletions
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue