This commit is contained in:
bubnikv 2019-01-14 19:59:33 +01:00
commit 366e8422a7
12 changed files with 108 additions and 19 deletions

View File

@ -1477,6 +1477,7 @@ namespace Slic3r {
stl_get_size(&stl); stl_get_size(&stl);
volume->mesh.repair(); volume->mesh.repair();
volume->center_geometry();
volume->calculate_convex_hull(); volume->calculate_convex_hull();
// apply volume's name and config data // apply volume's name and config data

View File

@ -819,14 +819,27 @@ TriangleMesh ModelObject::full_raw_mesh() const
BoundingBoxf3 ModelObject::raw_bounding_box() const BoundingBoxf3 ModelObject::raw_bounding_box() const
{ {
BoundingBoxf3 bb; BoundingBoxf3 bb;
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
for (const ModelVolume *v : this->volumes) for (const ModelVolume *v : this->volumes)
if (v->is_model_part()) { if (v->is_model_part()) {
#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
if (this->instances.empty()) if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
TriangleMesh vol_mesh(v->mesh); TriangleMesh vol_mesh(v->mesh);
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
vol_mesh.transform(inst_matrix * v->get_matrix());
bb.merge(vol_mesh.bounding_box());
#else
vol_mesh.transform(v->get_matrix()); vol_mesh.transform(v->get_matrix());
bb.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true)); bb.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true));
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
} }
return bb; return bb;
} }
@ -835,13 +848,21 @@ BoundingBoxf3 ModelObject::raw_bounding_box() const
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
{ {
BoundingBoxf3 bb; BoundingBoxf3 bb;
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
for (ModelVolume *v : this->volumes) for (ModelVolume *v : this->volumes)
{ {
if (v->is_model_part()) if (v->is_model_part())
{ {
TriangleMesh mesh(v->mesh); TriangleMesh mesh(v->mesh);
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
mesh.transform(inst_matrix * v->get_matrix());
bb.merge(mesh.bounding_box());
#else
mesh.transform(v->get_matrix()); mesh.transform(v->get_matrix());
bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(mesh, dont_translate)); bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(mesh, dont_translate));
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
} }
} }
return bb; return bb;

View File

@ -223,6 +223,9 @@ struct Head {
// If there is a pillar connecting to this head, then the id will be set. // If there is a pillar connecting to this head, then the id will be set.
long pillar_id = -1; long pillar_id = -1;
inline void invalidate() { id = -1; }
inline bool is_valid() const { return id >= 0; }
Head(double r_big_mm, Head(double r_big_mm,
double r_small_mm, double r_small_mm,
double length_mm, double length_mm,
@ -739,8 +742,10 @@ public:
for(auto& head : heads()) { for(auto& head : heads()) {
if(m_ctl.stopcondition()) break; if(m_ctl.stopcondition()) break;
auto&& m = mesh(head.mesh); if(head.is_valid()) {
meshcache.merge(m); auto&& m = mesh(head.mesh);
meshcache.merge(m);
}
} }
for(auto& stick : pillars()) { for(auto& stick : pillars()) {
@ -1533,8 +1538,19 @@ bool SLASupportTree::generate(const PointSet &points,
// In this case there is no room for the base pinhead. // In this case there is no room for the base pinhead.
if(gh < head.fullwidth()) { if(gh < head.fullwidth()) {
base_width = gh - 2 * cfg.head_front_radius_mm - double min_l =
2*cfg.head_back_radius_mm + cfg.head_penetration_mm; 2 * cfg.head_front_radius_mm +
2 * cfg.head_back_radius_mm - cfg.head_penetration_mm;
base_width = gh - min_l;
}
if(base_width < 0) {
// There is really no space for even a reduced size head. We
// have to replace that with a small half sphere that touches
// the model surface. (TODO)
head.invalidate();
continue;
} }
head.transform(); head.transform();
@ -1555,6 +1571,7 @@ bool SLASupportTree::generate(const PointSet &points,
// This should not happen it is against all assumptions // This should not happen it is against all assumptions
BOOST_LOG_TRIVIAL(warning) BOOST_LOG_TRIVIAL(warning)
<< "Ignoring invalid supports connecting to model body"; << "Ignoring invalid supports connecting to model body";
head.invalidate();
continue; continue;
} }

View File

@ -58,3 +58,5 @@
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4) #define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
// Added minimum threshold for click and drag movements // Added minimum threshold for click and drag movements
#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4) #define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
// Modified initial default placement of generic subparts
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)

View File

@ -436,7 +436,7 @@ void SpinCtrl::BUILD() {
propagate_value(); propagate_value();
}), temp->GetId()); }), temp->GetId());
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { propagate_value(); }), temp->GetId());
temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e)
{ {
@ -472,7 +472,7 @@ void SpinCtrl::propagate_value()
{ {
if (tmp_value < 0) if (tmp_value < 0)
on_kill_focus(); on_kill_focus();
else else if (boost::any_cast<int>(m_value) != tmp_value)
on_change_field(); on_change_field();
} }

View File

@ -325,6 +325,7 @@ public:
void set_value(const boost::any& value, bool change_event = false) { void set_value(const boost::any& value, bool change_event = false) {
m_disable_change_event = !change_event; m_disable_change_event = !change_event;
tmp_value = boost::any_cast<int>(value); tmp_value = boost::any_cast<int>(value);
m_value = value;
dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value);
m_disable_change_event = false; m_disable_change_event = false;
} }

View File

@ -4662,11 +4662,19 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_camera.set_scene_box(scene_bounding_box(), *this); m_camera.set_scene_box(scene_bounding_box(), *this);
m_camera.set_target(m_camera.get_target(), *this); m_camera.set_target(m_camera.get_target(), *this);
// if no object is selected, deactivate active gizmo, if any
// otherwise it will be shown after cleaning the scene (while it is active)
if (m_selection.is_empty()) if (m_selection.is_empty())
{
// If no object is selected, deactivate the active gizmo, if any
// Otherwise it may be shown after cleaning the scene (if it was active while the objects were deleted)
m_gizmos.reset_all_states(); m_gizmos.reset_all_states();
// If no object is selected, reset the objects manipulator on the sidebar
// to force a reset of its cache
auto manip = wxGetApp().obj_manipul();
if (manip != nullptr)
manip->update_settings_value(m_selection);
}
// and force this canvas to be redrawn. // and force this canvas to be redrawn.
m_dirty = true; m_dirty = true;
} }

View File

@ -760,7 +760,8 @@ Sidebar& GUI_App::sidebar()
ObjectManipulation* GUI_App::obj_manipul() ObjectManipulation* GUI_App::obj_manipul()
{ {
return sidebar().obj_manipul(); // If this method is called before plater_ has been initialized, return nullptr (to avoid a crash)
return (plater_ != nullptr) ? sidebar().obj_manipul() : nullptr;
} }
ObjectSettings* GUI_App::obj_settings() ObjectSettings* GUI_App::obj_settings()

View File

@ -895,9 +895,29 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
auto new_volume = (*m_objects)[obj_idx]->add_volume(mesh); auto new_volume = (*m_objects)[obj_idx]->add_volume(mesh);
new_volume->set_type(static_cast<ModelVolume::Type>(type)); new_volume->set_type(static_cast<ModelVolume::Type>(type));
#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
new_volume->set_offset(Vec3d(0.0, 0.0, (*m_objects)[obj_idx]->origin_translation(2) - mesh.stl.stats.min(2))); new_volume->set_offset(Vec3d(0.0, 0.0, (*m_objects)[obj_idx]->origin_translation(2) - mesh.stl.stats.min(2)));
#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
new_volume->center_geometry(); new_volume->center_geometry();
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
int instance_idx = selection.get_instance_idx();
if (instance_idx != -1)
{
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
const Transform3d& inst_m = v->get_instance_transformation().get_matrix(true);
TriangleMesh vol_mesh(mesh);
vol_mesh.transform(inst_m);
Vec3d vol_shift = -vol_mesh.bounding_box().center();
vol_mesh.translate((float)vol_shift(0), (float)vol_shift(1), (float)vol_shift(2));
Vec3d world_mesh_bb_size = vol_mesh.bounding_box().size();
BoundingBoxf3 inst_bb = (*m_objects)[obj_idx]->instance_bounding_box(instance_idx);
Vec3d world_target = Vec3d(inst_bb.max(0), inst_bb.min(1), inst_bb.min(2)) + 0.5 * world_mesh_bb_size;
new_volume->set_offset(inst_m.inverse() * (world_target - v->get_instance_offset()));
}
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
new_volume->name = name; new_volume->name = name;
// set a default extruder value, since user can't add it manually // set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));

View File

@ -428,17 +428,25 @@ void MainFrame::init_menubar()
// menubar // menubar
// assign menubar to frame after appending items, otherwise special items // assign menubar to frame after appending items, otherwise special items
// will not be handled correctly // will not be handled correctly
{ auto menubar = new wxMenuBar();
auto menubar = new wxMenuBar(); menubar->Append(fileMenu, L("&File"));
menubar->Append(fileMenu, L("&File")); if (editMenu) menubar->Append(editMenu, L("&Edit"));
if (editMenu) menubar->Append(editMenu, L("&Edit")); menubar->Append(windowMenu, L("&Window"));
menubar->Append(windowMenu, L("&Window")); if (viewMenu) menubar->Append(viewMenu, L("&View"));
if (viewMenu) menubar->Append(viewMenu, L("&View")); // Add additional menus from C++
// Add additional menus from C++ wxGetApp().add_config_menu(menubar);
wxGetApp().add_config_menu(menubar); menubar->Append(helpMenu, L("&Help"));
menubar->Append(helpMenu, L("&Help")); SetMenuBar(menubar);
SetMenuBar(menubar);
#ifdef __APPLE__
// This fixes a bug (?) on Mac OS where the quit command doesn't emit window close events
wxMenu *apple_menu = menubar->OSXGetAppleMenu();
if (apple_menu != nullptr) {
apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) {
Close();
}, wxID_EXIT);
} }
#endif
} }
// To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG". // To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".

View File

@ -1132,6 +1132,13 @@ void TabPrint::update()
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA)
return; // ys_FIXME return; // ys_FIXME
//! Temporary workaround for the correct updates of the SpinCtrl (like "perimeters"):
// KillFocus() for the wxSpinCtrl use CallAfter function. So,
// to except the duplicate call of the update() after dialog->ShowModal(),
// let check if this process is already started.
if (is_msg_dlg_already_exist)
return;
Freeze(); Freeze();
double fill_density = m_config->option<ConfigOptionPercent>("fill_density")->value; double fill_density = m_config->option<ConfigOptionPercent>("fill_density")->value;
@ -1147,6 +1154,7 @@ void TabPrint::update()
"- no ensure_vertical_shell_thickness\n" "- no ensure_vertical_shell_thickness\n"
"\nShall I adjust those settings in order to enable Spiral Vase?")); "\nShall I adjust those settings in order to enable Spiral Vase?"));
auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO); auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO);
is_msg_dlg_already_exist = true;
DynamicPrintConfig new_conf = *m_config; DynamicPrintConfig new_conf = *m_config;
if (dialog->ShowModal() == wxID_YES) { if (dialog->ShowModal() == wxID_YES) {
new_conf.set_key_value("perimeters", new ConfigOptionInt(1)); new_conf.set_key_value("perimeters", new ConfigOptionInt(1));
@ -1162,6 +1170,7 @@ void TabPrint::update()
} }
load_config(new_conf); load_config(new_conf);
on_value_change("fill_density", fill_density); on_value_change("fill_density", fill_density);
is_msg_dlg_already_exist = false;
} }
if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") &&

View File

@ -287,6 +287,7 @@ protected:
class TabPrint : public Tab class TabPrint : public Tab
{ {
bool is_msg_dlg_already_exist {false};
public: public:
TabPrint(wxNotebook* parent) : TabPrint(wxNotebook* parent) :
Tab(parent, _(L("Print Settings")), "print") {} Tab(parent, _(L("Print Settings")), "print") {}