Merge branch 'master' into fs_QuadricEdgeCollapse

This commit is contained in:
Filip Sykala 2021-08-18 10:37:21 +02:00
commit cc88b1e86b
18 changed files with 269 additions and 137 deletions

View file

@ -303,13 +303,16 @@ void GLVolume::SinkingContours::render()
void GLVolume::SinkingContours::update()
{
if (m_parent.is_sinking() && !m_parent.is_below_printbed()) {
int object_idx = m_parent.object_idx();
Model& model = GUI::wxGetApp().plater()->model();
if (0 <= object_idx && object_idx < (int)model.objects.size() && m_parent.is_sinking() && !m_parent.is_below_printbed()) {
const BoundingBoxf3& box = m_parent.transformed_convex_hull_bounding_box();
if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) {
m_old_box = box;
m_shift = Vec3d::Zero();
const TriangleMesh& mesh = GUI::wxGetApp().plater()->model().objects[m_parent.object_idx()]->volumes[m_parent.volume_idx()]->mesh();
const TriangleMesh& mesh = model.objects[object_idx]->volumes[m_parent.volume_idx()]->mesh();
assert(mesh.has_shared_vertices());
m_model.reset();

View file

@ -6373,7 +6373,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
case EWarning::ObjectOutside: text = _u8L("An object outside the print area was detected."); break;
case EWarning::ToolpathOutside: text = _u8L("A toolpath outside the print area was detected."); error = ErrorType::SLICING_ERROR; break;
case EWarning::SlaSupportsOutside: text = _u8L("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
case EWarning::SomethingNotShown: text = _u8L("Some objects are not visible."); break;
case EWarning::SomethingNotShown: text = _u8L("Some objects are not visible during editing."); break;
case EWarning::ObjectClashed:
text = _u8L("An object outside the print area was detected.\n"
"Resolve the current problem to continue slicing.");

View file

@ -1778,10 +1778,8 @@ void ObjectList::del_subobject_item(wxDataViewItem& item)
del_layers_from_object(obj_idx);
else if (type & itLayer && obj_idx != -1)
del_layer_from_object(obj_idx, m_objects_model->GetLayerRangeByItem(item));
else if (type & itInfo && obj_idx != -1) {
Unselect(item);
Select(parent);
}
else if (type & itInfo && obj_idx != -1)
del_info_item(obj_idx, m_objects_model->GetInfoItemType(item));
else if (idx == -1)
return;
else if (!del_subobject_from_object(obj_idx, idx, type))
@ -1795,6 +1793,52 @@ void ObjectList::del_subobject_item(wxDataViewItem& item)
update_info_items(obj_idx);
}
void ObjectList::del_info_item(const int obj_idx, InfoItemType type)
{
Plater* plater = wxGetApp().plater();
GLCanvas3D* cnv = plater->canvas3D();
switch (type) {
case InfoItemType::CustomSupports:
cnv->get_gizmos_manager().reset_all_states();
Plater::TakeSnapshot(plater, _L("Remove paint-on supports"));
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
mv->supported_facets.clear();
break;
case InfoItemType::CustomSeam:
cnv->get_gizmos_manager().reset_all_states();
Plater::TakeSnapshot(plater, _L("Remove paint-on seam"));
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
mv->seam_facets.clear();
break;
case InfoItemType::MmuSegmentation:
cnv->get_gizmos_manager().reset_all_states();
Plater::TakeSnapshot(plater, _L("Remove Multi Material painting"));
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
mv->mmu_segmentation_facets.clear();
break;
case InfoItemType::Sinking:
Plater::TakeSnapshot(plater, _L("Shift objects to bed"));
(*m_objects)[obj_idx]->ensure_on_bed();
cnv->reload_scene(true, true);
break;
case InfoItemType::VariableLayerHeight:
Plater::TakeSnapshot(plater, _L("Remove variable layer height"));
(*m_objects)[obj_idx]->layer_height_profile.clear();
if (cnv->is_layers_editing_enabled())
//cnv->post_event(SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING));
cnv->force_main_toolbar_left_action(cnv->get_main_toolbar_item_id("layersediting"));
break;
case InfoItemType::Undef : assert(false); break;
}
cnv->post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item)
{
const bool is_layer_settings = m_objects_model->GetItemType(parent_item) == itLayer;

View file

@ -254,6 +254,7 @@ public:
void del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range);
void del_layers_from_object(const int obj_idx);
bool del_subobject_from_object(const int obj_idx, const int idx, const int type);
void del_info_item(const int obj_idx, InfoItemType type);
void split();
void merge(bool to_multipart_object);
void layers_editing();

View file

@ -789,8 +789,8 @@ void Preview::update_layers_slider_mode()
return false;
for (ModelVolume* volume : object->volumes)
if (volume->config.has("extruder") &&
volume->config.option("extruder")->getInt() != extruder ||
if ((volume->config.has("extruder") &&
volume->config.option("extruder")->getInt() != extruder) ||
!volume->mmu_segmentation_facets.empty())
return false;

View file

@ -55,8 +55,15 @@ std::string GLGizmoCut::on_get_name() const
void GLGizmoCut::on_set_state()
{
// Reset m_cut_z on gizmo activation
#if ENABLE_SINKING_CONTOURS
if (get_state() == On) {
m_cut_z = bounding_box().center().z();
m_cut_contours.reset();
}
#else
if (get_state() == On)
m_cut_z = bounding_box().center().z();
#endif // ENABLE_SINKING_CONTOURS
}
bool GLGizmoCut::on_is_activable() const
@ -209,8 +216,12 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->end();
if (cut_clicked && (m_keep_upper || m_keep_lower))
if (cut_clicked && (m_keep_upper || m_keep_lower)) {
perform_cut(m_parent.get_selection());
#if ENABLE_SINKING_CONTOURS
m_cut_contours.reset();
#endif // ENABLE_SINKING_CONTOURS
}
}
void GLGizmoCut::set_cut_z(double cut_z)
@ -308,9 +319,8 @@ void GLGizmoCut::update_contours()
m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f });
}
}
else if (box.center() != m_cut_contours.position) {
else if (box.center() != m_cut_contours.position)
m_cut_contours.shift = box.center() - m_cut_contours.position;
}
}
else
m_cut_contours.contours.reset();

View file

@ -35,6 +35,16 @@ class GLGizmoCut : public GLGizmoBase
Vec3d shift{ Vec3d::Zero() };
int object_idx{ -1 };
int instance_idx{ -1 };
void reset() {
mesh.clear();
contours.reset();
cut_z = 0.0;
position = Vec3d::Zero();
shift = Vec3d::Zero();
object_idx = -1;
instance_idx = -1;
}
};
CutContours m_cut_contours;

View file

@ -497,9 +497,6 @@ void GLGizmoRotate3D::on_render()
m_gizmos[Z].render();
}
const char * GLGizmoRotate3D::RotoptimzeWindow::options[RotoptimizeJob::get_methods_count()];
bool GLGizmoRotate3D::RotoptimzeWindow::options_valid = false;
GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
State & state,
const Alignment &alignment)
@ -515,21 +512,26 @@ GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
y = std::min(y, alignment.bottom_limit - win_h);
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
ImGui::PushItemWidth(200.f);
ImGui::PushItemWidth(300.f);
size_t methods_cnt = RotoptimizeJob::get_methods_count();
if (!options_valid) {
for (size_t i = 0; i < methods_cnt; ++i)
options[i] = RotoptimizeJob::get_method_names()[i].c_str();
if (ImGui::BeginCombo(_L("Choose goal").c_str(), RotoptimizeJob::get_method_name(state.method_id).c_str())) {
for (size_t i = 0; i < RotoptimizeJob::get_methods_count(); ++i) {
if (ImGui::Selectable(RotoptimizeJob::get_method_name(i).c_str())) {
state.method_id = i;
wxGetApp().app_config->set("sla_auto_rotate",
"method_id",
std::to_string(state.method_id));
}
options_valid = true;
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", RotoptimizeJob::get_method_description(i).c_str());
}
ImGui::EndCombo();
}
int citem = state.method_id;
if (ImGui::Combo(_L("Choose goal").c_str(), &citem, options, methods_cnt) ) {
state.method_id = citem;
wxGetApp().app_config->set("sla_auto_rotate", "method_id", std::to_string(state.method_id));
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", RotoptimizeJob::get_method_description(state.method_id).c_str());
ImGui::Separator();

View file

@ -138,10 +138,6 @@ private:
class RotoptimzeWindow {
ImGuiWrapper *m_imgui = nullptr;
static const char * options [];
static bool options_valid;
public:
struct State {

View file

@ -447,7 +447,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
}
if (action == SLAGizmoEventType::DiscardChanges) {
editing_mode_discard_changes();
ask_about_changes_call_after([this](){ editing_mode_apply_changes(); },
[this](){ editing_mode_discard_changes(); });
return true;
}
@ -879,6 +880,22 @@ CommonGizmosDataID GLGizmoSlaSupports::on_get_requirements() const
void GLGizmoSlaSupports::ask_about_changes_call_after(std::function<void()> on_yes, std::function<void()> on_no)
{
wxGetApp().CallAfter([this, on_yes, on_no]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
MessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually "
"edited support points?") + "\n",_L("Save support points?"), wxICON_QUESTION | wxYES | wxNO | wxCANCEL );
int ret = dlg.ShowModal();
if (ret == wxID_YES)
on_yes();
else if (ret == wxID_NO)
on_no();
});
}
void GLGizmoSlaSupports::on_set_state()
{
if (m_state == m_old_state)
@ -901,18 +918,8 @@ void GLGizmoSlaSupports::on_set_state()
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
bool will_ask = m_editing_mode && unsaved_changes() && on_is_activable();
if (will_ask) {
wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
//wxMessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually "
MessageDialog dlg(GUI::wxGetApp().mainframe, _L("Do you want to save your manually "
"edited support points?") + "\n",_L("Save support points?"), wxICON_QUESTION | wxYES | wxNO | wxCANCEL );
int ret = dlg.ShowModal();
if (ret == wxID_YES)
editing_mode_apply_changes();
else if (ret == wxID_NO)
editing_mode_discard_changes();
});
ask_about_changes_call_after([this](){ editing_mode_apply_changes(); },
[this](){ editing_mode_discard_changes(); });
// refuse to be turned off so the gizmo is active when the CallAfter is executed
m_state = m_old_state;
}

View file

@ -117,6 +117,7 @@ private:
void auto_generate();
void switch_to_editing_mode();
void disable_editing_mode();
void ask_about_changes_call_after(std::function<void()> on_yes, std::function<void()> on_no);
protected:
void on_set_state() override;

View file

@ -15,14 +15,21 @@ class RotoptimizeJob : public PlaterJob
using FindFn = std::function<Vec2d(const ModelObject & mo,
const sla::RotOptimizeParams &params)>;
struct FindMethod { std::string name; FindFn findfn; };
struct FindMethod { std::string name; FindFn findfn; std::string descr; };
static inline const FindMethod Methods[] = {
{ L("Best surface quality"), sla::find_best_misalignment_rotation },
{ L("Least supports"), sla::find_least_supports_rotation },
// Just a min area bounding box that is done for all methods anyway.
{ L("Z axis only"), nullptr }
};
static inline const FindMethod Methods[]
= {{L("Best surface quality"),
sla::find_best_misalignment_rotation,
L("Optimize object rotation for best surface quality.")},
{L("Reduced overhang slopes"),
sla::find_least_supports_rotation,
L("Optimize object rotation to have minimum amount of overhangs needing support "
"structures.\nNote that this method will try to find the best surface of the object "
"for touching the print bed if no elevation is set.")},
// Just a min area bounding box that is done for all methods anyway.
{L("Smallest bounding box (Z axis only)"),
nullptr,
L("Rotate the object only in Z axis to have the smallest bounding box.")}};
size_t m_method_id = 0;
float m_accuracy = 0.75;
@ -52,20 +59,15 @@ public:
void finalize() override;
static constexpr size_t get_methods_count() { return std::size(Methods); }
static const auto & get_method_names()
static std::string get_method_name(size_t i)
{
static bool m_method_names_valid = false;
static std::array<std::string, std::size(Methods)> m_method_names;
return _utf8(Methods[i].name);
}
if (!m_method_names_valid) {
for (size_t i = 0; i < std::size(Methods); ++i)
m_method_names[i] = _utf8(Methods[i].name);
m_method_names_valid = true;
}
return m_method_names;
static std::string get_method_description(size_t i)
{
return _utf8(Methods[i].descr);
}
};

View file

@ -1141,7 +1141,7 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type
if (!node ||
node->GetIdx() <-1 ||
( node->GetIdx() == -1 &&
!(node->GetType() & (itObject | itSettings | itInstanceRoot | itLayerRoot/* | itLayer*/))
!(node->GetType() & (itObject | itSettings | itInstanceRoot | itLayerRoot | itInfo))
)
)
return;