Merge branch 'master' of https://github.com/Prusa3D/PrusaSlicer
This commit is contained in:
commit
b028e169c8
@ -1554,14 +1554,16 @@ namespace rotcalip {
|
||||
using int256_t = boost::multiprecision::int256_t;
|
||||
using int128_t = boost::multiprecision::int128_t;
|
||||
|
||||
inline int128_t magnsq(const Point &p)
|
||||
template<class Scalar = int64_t>
|
||||
inline Scalar magnsq(const Point &p)
|
||||
{
|
||||
return int128_t(p.x()) * p.x() + int64_t(p.y()) * p.y();
|
||||
return Scalar(p.x()) * p.x() + Scalar(p.y()) * p.y();
|
||||
}
|
||||
|
||||
inline int128_t dot(const Point &a, const Point &b)
|
||||
template<class Scalar = int64_t>
|
||||
inline Scalar dot(const Point &a, const Point &b)
|
||||
{
|
||||
return int128_t(a.x()) * b.x() + int64_t(a.y()) * b.y();
|
||||
return Scalar(a.x()) * b.x() + Scalar(a.y()) * b.y();
|
||||
}
|
||||
|
||||
template<class Scalar = int64_t>
|
||||
@ -1667,7 +1669,6 @@ bool intersects(const Polygon &A, const Polygon &B)
|
||||
// Establish starting antipodals as extremes in XY plane. Use the
|
||||
// easily obtainable bounding boxes to check if A and B is disjoint
|
||||
// and return false if the are.
|
||||
|
||||
struct BB
|
||||
{
|
||||
size_t xmin = 0, xmax = 0, ymin = 0, ymax = 0;
|
||||
@ -1724,24 +1725,18 @@ bool intersects(const Polygon &A, const Polygon &B)
|
||||
bool is_left_a = dotperp( dir, ref_a - A[ia]) > 0;
|
||||
bool is_left_b = dotperp(-dir, ref_b - B[ib]) > 0;
|
||||
|
||||
// If both reference points are on the left (or right) of the
|
||||
// support line and the opposite support line is to the righ (or
|
||||
// left), the divisor line is found. We only test the reference
|
||||
// point, as by definition, if that is on one side, all the other
|
||||
// points must be on the same side of a support line.
|
||||
// If both reference points are on the left (or right) of their
|
||||
// respective support lines and the opposite support line is to
|
||||
// the right (or left), the divisor line is found. We only test
|
||||
// the reference point, as by definition, if that is on one side,
|
||||
// all the other points must be on the same side of a support
|
||||
// line. If the support lines are collinear, the polygons must be
|
||||
// on the same side of their respective support lines.
|
||||
|
||||
auto d = dotperp(dir, B[ib] - A[ia]);
|
||||
if (d == 0 && ((is_left_a && is_left_b) || (!is_left_a && !is_left_b))) {
|
||||
if (d == 0) {
|
||||
// The caliper lines are collinear, not just parallel
|
||||
|
||||
// Check if the lines are overlapping and if they do ignore the divisor
|
||||
Point a = A[ia], b = A[(ia + 1) % A.size()];
|
||||
if (b < a) std::swap(a, b);
|
||||
Point c = B[ib], d = B[(ib + 1) % B.size()];
|
||||
if (d < c) std::swap(c, d);
|
||||
|
||||
found_divisor = b < c;
|
||||
|
||||
found_divisor = (is_left_a && is_left_b) || (!is_left_a && !is_left_b);
|
||||
} else if (d > 0) { // B is to the left of (A, A+1)
|
||||
found_divisor = !is_left_a && !is_left_b;
|
||||
} else { // B is to the right of (A, A+1)
|
||||
|
@ -532,7 +532,9 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation)
|
||||
return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z());
|
||||
}
|
||||
|
||||
bool intersects(const Polygon &convex_poly1, const Polygon &convex_poly2);
|
||||
// Returns true if the intersection of the two convex polygons A and B
|
||||
// is not an empty set.
|
||||
bool intersects(const Polygon &A, const Polygon &B);
|
||||
|
||||
} } // namespace Slicer::Geometry
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "libslic3r/Platform.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
@ -40,7 +42,6 @@
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
#include "format.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "UnsavedChangesDialog.hpp"
|
||||
|
||||
#if defined(__linux__) && defined(__WXGTK3__)
|
||||
@ -2477,6 +2478,46 @@ static std::string get_first_added_preset(const std::map<std::string, std::strin
|
||||
bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater, bool& apply_keeped_changes)
|
||||
{
|
||||
wxString header, caption = _L("Configuration is editing from ConfigWizard");
|
||||
const auto enabled_vendors = appconfig_new.vendors();
|
||||
|
||||
bool suppress_sla_printer = model_has_multi_part_objects(wxGetApp().model());
|
||||
PrinterTechnology preferred_pt = ptAny;
|
||||
auto get_preferred_printer_technology = [enabled_vendors, suppress_sla_printer](const std::string& bundle_name, const Bundle& bundle) {
|
||||
const auto config = enabled_vendors.find(bundle_name);
|
||||
PrinterTechnology pt = ptAny;
|
||||
if (config != enabled_vendors.end()) {
|
||||
for (const auto& model : bundle.vendor_profile->models) {
|
||||
if (const auto model_it = config->second.find(model.id);
|
||||
model_it != config->second.end() && model_it->second.size() > 0) {
|
||||
if (pt == ptAny)
|
||||
pt = model.technology;
|
||||
// if preferred printer model has SLA printer technology it's important to check the model for multypart state
|
||||
if (pt == ptSLA && suppress_sla_printer)
|
||||
continue;
|
||||
else
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pt;
|
||||
};
|
||||
// Prusa printers are considered first, then 3rd party.
|
||||
if (preferred_pt = get_preferred_printer_technology("PrusaResearch", bundles.prusa_bundle());
|
||||
preferred_pt == ptAny || (preferred_pt == ptSLA && suppress_sla_printer)) {
|
||||
for (const auto& bundle : bundles) {
|
||||
if (bundle.second.is_prusa_bundle) { continue; }
|
||||
if (PrinterTechnology pt = get_preferred_printer_technology(bundle.first, bundle.second); pt == ptAny)
|
||||
continue;
|
||||
else if (preferred_pt == ptAny)
|
||||
preferred_pt = pt;
|
||||
if(!(preferred_pt == ptAny || (preferred_pt == ptSLA && suppress_sla_printer)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (preferred_pt == ptSLA && !wxGetApp().may_switch_to_SLA_preset(caption))
|
||||
return false;
|
||||
|
||||
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
||||
if (check_unsaved_preset_changes)
|
||||
header = _L("All user presets will be deleted.");
|
||||
@ -2484,8 +2525,6 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
if (!check_unsaved_preset_changes)
|
||||
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
|
||||
|
||||
const auto enabled_vendors = appconfig_new.vendors();
|
||||
|
||||
// Install bundles from resources if needed:
|
||||
std::vector<std::string> install_bundles;
|
||||
for (const auto &pair : bundles) {
|
||||
@ -2564,13 +2603,14 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
std::string preferred_model;
|
||||
std::string preferred_variant;
|
||||
const auto enabled_vendors_old = app_config->vendors();
|
||||
auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old](const std::string& bundle_name, const Bundle& bundle, std::string& variant) {
|
||||
auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old, preferred_pt](const std::string& bundle_name, const Bundle& bundle, std::string& variant) {
|
||||
const auto config = enabled_vendors.find(bundle_name);
|
||||
if (config == enabled_vendors.end())
|
||||
return std::string();
|
||||
for (const auto& model : bundle.vendor_profile->models) {
|
||||
if (const auto model_it = config->second.find(model.id);
|
||||
model_it != config->second.end() && model_it->second.size() > 0) {
|
||||
model_it != config->second.end() && model_it->second.size() > 0 &&
|
||||
preferred_pt == model.technology) {
|
||||
variant = *model_it->second.begin();
|
||||
const auto config_old = enabled_vendors_old.find(bundle_name);
|
||||
if (config_old == enabled_vendors_old.end())
|
||||
|
@ -2432,6 +2432,20 @@ void GUI_App::open_web_page_localized(const std::string &http_address)
|
||||
open_browser_with_warning_dialog(http_address + "&lng=" + this->current_language_code_safe());
|
||||
}
|
||||
|
||||
// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s).
|
||||
// Because of we can't to print the multi-part objects with SLA technology.
|
||||
bool GUI_App::may_switch_to_SLA_preset(const wxString& caption)
|
||||
{
|
||||
if (model_has_multi_part_objects(model())) {
|
||||
show_info(nullptr,
|
||||
_L("It's impossible to print multi-part object(s) with SLA technology.") + "\n\n" +
|
||||
_L("Please check your object list before preset changing."),
|
||||
caption);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page)
|
||||
{
|
||||
wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null");
|
||||
@ -2447,13 +2461,9 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
||||
if (res) {
|
||||
load_current_presets();
|
||||
|
||||
if (preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA
|
||||
&& Slic3r::model_has_multi_part_objects(wxGetApp().model())) {
|
||||
GUI::show_info(nullptr,
|
||||
_L("It's impossible to print multi-part object(s) with SLA technology.") + "\n\n" +
|
||||
_L("Please check and fix your object list."),
|
||||
_L("Attention!"));
|
||||
}
|
||||
// #ysFIXME - delete after testing: This part of code looks redundant. All checks are inside ConfigWizard::priv::apply_config()
|
||||
if (preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA)
|
||||
may_switch_to_SLA_preset(_L("Configuration is editing from ConfigWizard"));
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -309,6 +309,7 @@ public:
|
||||
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
|
||||
|
||||
void open_web_page_localized(const std::string &http_address);
|
||||
bool may_switch_to_SLA_preset(const wxString& caption);
|
||||
bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME);
|
||||
void show_desktop_integration_dialog();
|
||||
|
||||
|
@ -497,14 +497,19 @@ void ObjectManipulation::update_ui_from_settings()
|
||||
int axis_id = 0;
|
||||
for (ManipulationEditor* editor : m_editors) {
|
||||
// editor->SetForegroundColour(m_use_colors ? wxColour(axes_color_text[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
#ifdef _WIN32
|
||||
if (m_use_colors)
|
||||
if (m_use_colors) {
|
||||
editor->SetBackgroundColour(wxColour(axes_color_back[axis_id]));
|
||||
else
|
||||
if (wxGetApp().dark_mode())
|
||||
editor->SetForegroundColour(*wxBLACK);
|
||||
}
|
||||
else {
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDarkUI(editor);
|
||||
#else
|
||||
editor->SetBackgroundColour(m_use_colors ? wxColour(axes_color_back[axis_id]) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
editor->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
editor->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
editor->Refresh();
|
||||
if (++axis_id == 3)
|
||||
axis_id = 0;
|
||||
@ -1009,10 +1014,10 @@ void ObjectManipulation::sys_color_changed()
|
||||
get_og()->sys_color_changed();
|
||||
wxGetApp().UpdateDarkUI(m_word_local_combo);
|
||||
wxGetApp().UpdateDarkUI(m_check_inch);
|
||||
|
||||
#endif
|
||||
for (ManipulationEditor* editor : m_editors)
|
||||
editor->sys_color_changed(this);
|
||||
#endif
|
||||
|
||||
// btn...->msw_rescale() updates icon on button, so use it
|
||||
m_mirror_bitmap_on.msw_rescale();
|
||||
m_mirror_bitmap_off.msw_rescale();
|
||||
@ -1045,6 +1050,7 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
||||
#endif // __WXOSX__
|
||||
if (parent->use_colors()) {
|
||||
this->SetBackgroundColour(wxColour(axes_color_back[axis]));
|
||||
this->SetForegroundColour(*wxBLACK);
|
||||
} else {
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
}
|
||||
@ -1097,10 +1103,14 @@ void ManipulationEditor::msw_rescale()
|
||||
|
||||
void ManipulationEditor::sys_color_changed(ObjectManipulation* parent)
|
||||
{
|
||||
if (!parent->use_colors())
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
else
|
||||
if (parent->use_colors())
|
||||
SetForegroundColour(*wxBLACK);
|
||||
else
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
#else
|
||||
SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
double ManipulationEditor::get_value()
|
||||
|
@ -182,7 +182,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
|
||||
double cut_z = m_cut_z;
|
||||
if (imperial_units)
|
||||
cut_z *= ObjectManipulation::mm_to_in;
|
||||
ImGui::InputDouble("", &cut_z, 0.0f, 0.0f, "%.2f");
|
||||
ImGui::InputDouble("", &cut_z, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
|
||||
|
||||
ImGui::SameLine();
|
||||
m_imgui->text(imperial_units ? _L("in") : _L("mm"));
|
||||
|
@ -60,8 +60,9 @@ void GLGizmoSimplify::on_render_for_picking() {}
|
||||
void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
create_gui_cfg();
|
||||
int obj_index;
|
||||
ModelVolume *act_volume = get_selected_volume(&obj_index);
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
int obj_index = selection.get_object_idx();
|
||||
ModelVolume *act_volume = get_volume(selection, wxGetApp().plater()->model());
|
||||
if (act_volume == nullptr) {
|
||||
switch (m_state) {
|
||||
case State::settings: close(); break;
|
||||
@ -427,17 +428,34 @@ bool GLGizmoSimplify::exist_volume(ModelVolume *volume) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelVolume *GLGizmoSimplify::get_selected_volume(int *object_idx_ptr) const
|
||||
ModelVolume * GLGizmoSimplify::get_volume(const Selection &selection, Model &model)
|
||||
{
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
int object_idx = selection.get_object_idx();
|
||||
if (object_idx_ptr != nullptr) *object_idx_ptr = object_idx;
|
||||
if (object_idx < 0) return nullptr;
|
||||
ModelObjectPtrs &objs = wxGetApp().plater()->model().objects;
|
||||
if (static_cast<int>(objs.size()) <= object_idx) return nullptr;
|
||||
ModelObject *obj = objs[object_idx];
|
||||
if (obj->volumes.empty()) return nullptr;
|
||||
return obj->volumes.front();
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
if (idxs.empty()) return nullptr;
|
||||
// only one selected volume
|
||||
if (idxs.size() != 1) return nullptr;
|
||||
const GLVolume *selected_volume = selection.get_volume(*idxs.begin());
|
||||
if (selected_volume == nullptr) return nullptr;
|
||||
|
||||
const GLVolume::CompositeID &cid = selected_volume->composite_id;
|
||||
const ModelObjectPtrs& objs = model.objects;
|
||||
if (cid.object_id < 0 || objs.size() <= static_cast<size_t>(cid.object_id))
|
||||
return nullptr;
|
||||
const ModelObject* obj = objs[cid.object_id];
|
||||
if (cid.volume_id < 0 || obj->volumes.size() <= static_cast<size_t>(cid.volume_id))
|
||||
return nullptr;
|
||||
return obj->volumes[cid.volume_id];
|
||||
}
|
||||
|
||||
const ModelVolume *GLGizmoSimplify::get_volume(const GLVolume::CompositeID &cid, const Model &model)
|
||||
{
|
||||
const ModelObjectPtrs &objs = model.objects;
|
||||
if (cid.object_id < 0 || objs.size() <= static_cast<size_t>(cid.object_id))
|
||||
return nullptr;
|
||||
const ModelObject *obj = objs[cid.object_id];
|
||||
if (cid.volume_id < 0 || obj->volumes.size() <= static_cast<size_t>(cid.volume_id))
|
||||
return nullptr;
|
||||
return obj->volumes[cid.volume_id];
|
||||
}
|
||||
|
||||
void GLGizmoSimplify::init_wireframe()
|
||||
@ -479,14 +497,16 @@ void GLGizmoSimplify::render_wireframe() const
|
||||
if (m_wireframe_VBO_id == 0 || m_wireframe_IBO_id == 0) return;
|
||||
if (!m_show_wireframe) return;
|
||||
|
||||
const GLVolume *selected_volume = m_parent.get_selection().get_volume(0);
|
||||
const auto& selection = m_parent.get_selection();
|
||||
const auto& volume_idxs = selection.get_volume_idxs();
|
||||
if (volume_idxs.empty() || volume_idxs.size() != 1) return;
|
||||
const GLVolume *selected_volume = selection.get_volume(*volume_idxs.begin());
|
||||
|
||||
// check selected_volume == m_volume
|
||||
const auto& cid = selected_volume->composite_id;
|
||||
assert(wxGetApp().plater()->model().objects[cid.object_id]->volumes[cid.volume_id] == m_volume);
|
||||
|
||||
const Transform3d trafo_matrix = m_parent.get_selection().get_volume(0)->world_matrix();
|
||||
// check that selected model is wireframe initialized
|
||||
if (m_volume != get_volume(selected_volume->composite_id, *m_parent.get_model()))
|
||||
return;
|
||||
|
||||
const Transform3d trafo_matrix = selected_volume->world_matrix();
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixd(trafo_matrix.data()));
|
||||
|
||||
|
@ -43,7 +43,9 @@ private:
|
||||
void set_its(indexed_triangle_set &its);
|
||||
void create_gui_cfg();
|
||||
void request_rerender();
|
||||
ModelVolume *get_selected_volume(int *object_idx = nullptr) const;
|
||||
// move to global functions
|
||||
static ModelVolume *get_volume(const Selection &selection, Model &model);
|
||||
static const ModelVolume *get_volume(const GLVolume::CompositeID &cid, const Model &model);
|
||||
|
||||
// return false when volume was deleted
|
||||
static bool exist_volume(ModelVolume *volume);
|
||||
|
@ -359,7 +359,7 @@ bool ImGuiWrapper::image_button()
|
||||
|
||||
bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format)
|
||||
{
|
||||
return ImGui::InputDouble(label.c_str(), const_cast<double*>(&value), 0.0f, 0.0f, format.c_str());
|
||||
return ImGui::InputDouble(label.c_str(), const_cast<double*>(&value), 0.0f, 0.0f, format.c_str(), ImGuiInputTextFlags_CharsDecimal);
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::input_double(const wxString &label, const double &value, const std::string &format)
|
||||
|
@ -228,7 +228,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||
return;
|
||||
}
|
||||
// check unsaved changes only if project wasn't saved
|
||||
else if (saved_project == wxID_NO && event.CanVeto() &&
|
||||
else if (plater()->is_project_dirty() && saved_project == wxID_NO && event.CanVeto() &&
|
||||
!wxGetApp().check_and_save_current_preset_changes(_L("PrusaSlicer is closing"), _L("Closing PrusaSlicer while some presets are modified."))) {
|
||||
event.Veto();
|
||||
return;
|
||||
|
@ -2109,13 +2109,14 @@ void Plater::priv::update(unsigned int flags)
|
||||
}
|
||||
|
||||
unsigned int update_status = 0;
|
||||
if (this->printer_technology == ptSLA || (flags & (unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE))
|
||||
const bool force_background_processing_restart = this->printer_technology == ptSLA || (flags & (unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE);
|
||||
if (force_background_processing_restart)
|
||||
// Update the SLAPrint from the current Model, so that the reload_scene()
|
||||
// pulls the correct data.
|
||||
update_status = this->update_background_process(false, flags & (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE);
|
||||
this->view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH);
|
||||
this->preview->reload_print();
|
||||
if (this->printer_technology == ptSLA)
|
||||
if (force_background_processing_restart)
|
||||
this->restart_background_process(update_status);
|
||||
else
|
||||
this->schedule_background_process();
|
||||
@ -4172,12 +4173,14 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
||||
if (printer_technology == ptSLA)
|
||||
menu = menus.sla_object_menu();
|
||||
else {
|
||||
const Selection& selection = get_selection();
|
||||
// show "Object menu" for each one or several FullInstance instead of FullObject
|
||||
const bool is_some_full_instances = get_selection().is_single_full_instance() ||
|
||||
get_selection().is_single_full_object() ||
|
||||
get_selection().is_multiple_full_instance();
|
||||
const bool is_some_full_instances = selection.is_single_full_instance() ||
|
||||
selection.is_single_full_object() ||
|
||||
selection.is_multiple_full_instance();
|
||||
const bool is_part = selection.is_single_volume() || selection.is_single_modifier();
|
||||
menu = is_some_full_instances ? menus.object_menu() :
|
||||
get_selection().is_single_volume() ? menus.part_menu() : menus.multi_selection_menu();
|
||||
is_part ? menus.part_menu() : menus.multi_selection_menu();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3236,7 +3236,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/,
|
||||
const PresetWithVendorProfile new_printer_preset_with_vendor_profile = m_presets->get_preset_with_vendor_profile(new_printer_preset);
|
||||
PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology();
|
||||
PrinterTechnology new_printer_technology = new_printer_preset.printer_technology();
|
||||
if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !may_switch_to_SLA_preset())
|
||||
if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !wxGetApp().may_switch_to_SLA_preset(_L("New printer preset is selecting")))
|
||||
canceled = true;
|
||||
else {
|
||||
struct PresetUpdate {
|
||||
@ -3409,21 +3409,6 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s).
|
||||
// Because of we can't to print the multi-part objects with SLA technology.
|
||||
bool Tab::may_switch_to_SLA_preset()
|
||||
{
|
||||
if (model_has_multi_part_objects(wxGetApp().model()))
|
||||
{
|
||||
show_info( parent(),
|
||||
_(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" +
|
||||
_(L("Please check your object list before preset changing.")),
|
||||
_(L("Attention!")) );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tab::clear_pages()
|
||||
{
|
||||
// invalidated highlighter, if any exists
|
||||
|
@ -282,7 +282,6 @@ public:
|
||||
// Select a new preset, possibly delete the current one.
|
||||
void select_preset(std::string preset_name = "", bool delete_current = false, const std::string& last_selected_ph_printer_name = "");
|
||||
bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "");
|
||||
bool may_switch_to_SLA_preset();
|
||||
|
||||
virtual void clear_pages();
|
||||
virtual void update_description_lines();
|
||||
|
@ -470,7 +470,7 @@ TEST_CASE("Convex polygon intersection on two disjoint squares", "[Geometry][Rot
|
||||
|
||||
bool is_inters = Geometry::intersects(A, B);
|
||||
|
||||
REQUIRE(is_inters != true);
|
||||
REQUIRE(is_inters == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Convex polygon intersection on two intersecting squares", "[Geometry][Rotcalip]") {
|
||||
@ -494,7 +494,7 @@ TEST_CASE("Convex polygon intersection on two squares touching one edge", "[Geom
|
||||
|
||||
bool is_inters = Geometry::intersects(A, B);
|
||||
|
||||
REQUIRE(is_inters == true);
|
||||
REQUIRE(is_inters == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Geometry][Rotcalip]") {
|
||||
@ -502,11 +502,16 @@ TEST_CASE("Convex polygon intersection on two squares touching one vertex", "[Ge
|
||||
A.scale(1. / SCALING_FACTOR);
|
||||
|
||||
Polygon B = A;
|
||||
B.translate(10 / SCALING_FACTOR, 10);
|
||||
B.translate(10 / SCALING_FACTOR, 10 / SCALING_FACTOR);
|
||||
|
||||
SVG svg{std::string("one_vertex_touch") + ".svg"};
|
||||
svg.draw(A, "blue");
|
||||
svg.draw(B, "green");
|
||||
svg.Close();
|
||||
|
||||
bool is_inters = Geometry::intersects(A, B);
|
||||
|
||||
REQUIRE(is_inters == true);
|
||||
REQUIRE(is_inters == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][Rotcalip]") {
|
||||
@ -520,7 +525,7 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][
|
||||
REQUIRE(is_inters == true);
|
||||
}
|
||||
|
||||
// Only for benchmarking
|
||||
//// Only for benchmarking
|
||||
//static Polygon gen_convex_poly(std::mt19937_64 &rg, size_t point_cnt)
|
||||
//{
|
||||
// std::uniform_int_distribution<coord_t> dist(0, 100);
|
||||
@ -540,7 +545,9 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][
|
||||
// constexpr size_t TEST_CNT = 1000;
|
||||
// constexpr size_t POINT_CNT = 1000;
|
||||
|
||||
// std::mt19937_64 rg{std::random_device{}()};
|
||||
// auto seed = std::random_device{}();
|
||||
//// unsigned long seed = 2525634386;
|
||||
// std::mt19937_64 rg{seed};
|
||||
// Benchmark bench;
|
||||
|
||||
// auto tests = reserve_vector<std::pair<Polygon, Polygon>>(TEST_CNT);
|
||||
@ -567,11 +574,12 @@ TEST_CASE("Convex polygon intersection on two overlapping squares", "[Geometry][
|
||||
|
||||
// REQUIRE(results.size() == expects.size());
|
||||
|
||||
// auto seedstr = std::to_string(seed);
|
||||
// for (size_t i = 0; i < results.size(); ++i) {
|
||||
// // std::cout << expects[i] << " ";
|
||||
|
||||
// if (results[i] != expects[i]) {
|
||||
// SVG svg{std::string("fail") + std::to_string(i) + ".svg"};
|
||||
// SVG svg{std::string("fail_seed") + seedstr + "_" + std::to_string(i) + ".svg"};
|
||||
// svg.draw(tests[i].first, "blue");
|
||||
// svg.draw(tests[i].second, "green");
|
||||
// svg.Close();
|
||||
|
Loading…
Reference in New Issue
Block a user