Merge branch 'dev_native' of github.com:prusa3d/Slic3r into dev_native

This commit is contained in:
tamasmeszaros 2018-11-12 17:37:53 +01:00
commit 72a1f36281
11 changed files with 103 additions and 54 deletions

View File

@ -370,7 +370,7 @@ protected:
friend class Print; friend class Print;
friend class ModelObject; friend class ModelObject;
explicit ModelVolume(ModelVolume &rhs) = default; explicit ModelVolume(const ModelVolume &rhs) = default;
void set_model_object(ModelObject *model_object) { object = model_object; } void set_model_object(ModelObject *model_object) { object = model_object; }
private: private:

View File

@ -260,6 +260,8 @@ bool Print::invalidate_step(PrintStep step)
//FIXME Why should skirt invalidate brim? Shouldn't it be vice versa? //FIXME Why should skirt invalidate brim? Shouldn't it be vice versa?
if (step == psSkirt) if (step == psSkirt)
invalidated |= Inherited::invalidate_step(psBrim); invalidated |= Inherited::invalidate_step(psBrim);
if (step != psGCodeExport)
invalidated |= Inherited::invalidate_step(psGCodeExport);
return invalidated; return invalidated;
} }
@ -612,27 +614,45 @@ static inline bool model_volume_list_changed(const ModelObject &model_object_old
return false; return false;
} }
void Print::model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src) // Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
// in the exact order and with the same IDs.
// It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order.
void Print::model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_new)
{ {
// 1) Delete the support volumes from model_object_dst. typedef std::pair<const ModelVolume*, bool> ModelVolumeWithStatus;
{ std::vector<ModelVolumeWithStatus> old_volumes;
std::vector<ModelVolume*> dst; old_volumes.reserve(model_object_dst.volumes.size());
dst.reserve(model_object_dst.volumes.size()); for (const ModelVolume *model_volume : model_object_dst.volumes)
for (ModelVolume *vol : model_object_dst.volumes) { old_volumes.emplace_back(ModelVolumeWithStatus(model_volume, false));
if (vol->is_support_modifier()) auto model_volume_lower = [](const ModelVolumeWithStatus &mv1, const ModelVolumeWithStatus &mv2){ return mv1.first->id() < mv2.first->id(); };
dst.emplace_back(vol); auto model_volume_equal = [](const ModelVolumeWithStatus &mv1, const ModelVolumeWithStatus &mv2){ return mv1.first->id() == mv2.first->id(); };
else std::sort(old_volumes.begin(), old_volumes.end(), model_volume_lower);
delete vol; model_object_dst.volumes.clear();
model_object_dst.volumes.reserve(model_object_new.volumes.size());
for (const ModelVolume *model_volume_src : model_object_new.volumes) {
ModelVolumeWithStatus key(model_volume_src, false);
auto it = std::lower_bound(old_volumes.begin(), old_volumes.end(), key, model_volume_lower);
if (it != old_volumes.end() && model_volume_equal(*it, key)) {
// The volume was found in the old list. Just copy it.
assert(! it->second); // not consumed yet
it->second = true;
ModelVolume *model_volume_dst = const_cast<ModelVolume*>(it->first);
assert(model_volume_dst->type() == model_volume_src->type());
model_object_dst.volumes.emplace_back(model_volume_dst);
if (model_volume_dst->is_support_modifier())
model_volume_dst->set_transformation(model_volume_src->get_transformation());
assert(model_volume_dst->get_matrix().isApprox(model_volume_src->get_matrix()));
} else {
// The volume was not found in the old list. Create a new copy.
assert(model_volume_src->is_support_modifier());
model_object_dst.volumes.emplace_back(new ModelVolume(*model_volume_src));
model_object_dst.volumes.back()->set_model_object(&model_object_dst);
} }
model_object_dst.volumes = std::move(dst);
}
// 2) Copy the support volumes from model_object_src to the end of model_object_dst.
for (ModelVolume *vol : model_object_src.volumes) {
if (vol->is_support_modifier()) {
model_object_dst.volumes.emplace_back(new ModelVolume(*vol));
model_object_dst.volumes.back()->set_model_object(&model_object_dst);
}
} }
// Release the non-consumed old volumes (those were deleted from the new list).
for (ModelVolumeWithStatus &mv_with_status : old_volumes)
if (! mv_with_status.second)
delete mv_with_status.first;
} }
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolume::Type type) static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolume::Type type)
@ -852,7 +872,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
// Reorder the objects, add new objects. // Reorder the objects, add new objects.
// First stop background processing before shuffling or deleting the PrintObjects in the object list. // First stop background processing before shuffling or deleting the PrintObjects in the object list.
this->call_cancell_callback(); this->call_cancell_callback();
this->invalidate_step(psGCodeExport); update_apply_status(this->invalidate_step(psGCodeExport));
// Second create a new list of objects. // Second create a new list of objects.
std::vector<ModelObject*> model_objects_old(std::move(m_model.objects)); std::vector<ModelObject*> model_objects_old(std::move(m_model.objects));
m_model.objects.clear(); m_model.objects.clear();
@ -962,6 +982,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
} else if (support_blockers_differ || support_enforcers_differ) { } else if (support_blockers_differ || support_enforcers_differ) {
// First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list. // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list.
this->call_cancell_callback(); this->call_cancell_callback();
update_apply_status(false);
// Invalidate just the supports step. // Invalidate just the supports step.
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
for (auto it = range.first; it != range.second; ++ it) for (auto it = range.first; it != range.second; ++ it)
@ -1067,6 +1088,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
} }
if (m_objects != print_objects_new) { if (m_objects != print_objects_new) {
this->call_cancell_callback(); this->call_cancell_callback();
update_apply_status(this->invalidate_all_steps());
m_objects = print_objects_new; m_objects = print_objects_new;
// Delete the PrintObjects marked as Unknown or Deleted. // Delete the PrintObjects marked as Unknown or Deleted.
bool deleted_objects = false; bool deleted_objects = false;
@ -1131,7 +1153,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
int ireg = 0; int ireg = 0;
for (const std::vector<int> &volumes : print_object->region_volumes) { for (const std::vector<int> &volumes : print_object->region_volumes) {
if (! volumes.empty()) if (! volumes.empty())
-- m_regions[ireg]; -- m_regions[ireg]->m_refcnt;
++ ireg; ++ ireg;
} }
print_object->region_volumes.clear(); print_object->region_volumes.clear();
@ -1164,21 +1186,24 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
// Get the config applied to this volume. // Get the config applied to this volume.
PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume); PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume);
// Find an existing print region with the same config. // Find an existing print region with the same config.
for (int i = 0; i < (int)m_regions.size(); ++ i) int idx_empty_slot = -1;
if (config.equals(m_regions[i]->config())) { for (int i = 0; i < (int)m_regions.size(); ++ i) {
if (m_regions[i]->m_refcnt == 0)
idx_empty_slot = i;
else if (config.equals(m_regions[i]->config())) {
region_id = i; region_id = i;
break; break;
} }
}
// If no region exists with the same config, create a new one. // If no region exists with the same config, create a new one.
if (region_id == size_t(-1)) { if (region_id == -1) {
for (region_id = 0; region_id < m_regions.size(); ++ region_id) if (idx_empty_slot == -1) {
if (m_regions[region_id]->m_refcnt == 0) { region_id = (int)m_regions.size();
// An empty slot was found. this->add_region(config);
m_regions[region_id]->set_config(std::move(config)); } else {
break; region_id = idx_empty_slot;
} m_regions[region_id]->set_config(std::move(config));
if (region_id == m_regions.size()) }
this->add_region(config);
} }
map_volume_to_region[volume_id] = region_id; map_volume_to_region[volume_id] = region_id;
} else } else

View File

@ -174,6 +174,8 @@ protected:
bool set_copies(const Points &points); bool set_copies(const Points &points);
// Invalidates the step, and its depending steps in PrintObject and Print. // Invalidates the step, and its depending steps in PrintObject and Print.
bool invalidate_step(PrintObjectStep step); bool invalidate_step(PrintObjectStep step);
// Invalidates all PrintObject and Print steps.
bool invalidate_all_steps();
private: private:
void make_perimeters(); void make_perimeters();

View File

@ -570,9 +570,16 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// It also decides about what the wipe_into_infill / wipe_into_object features will do, // It also decides about what the wipe_into_infill / wipe_into_object features will do,
// and that too depends on many of the settings. // and that too depends on many of the settings.
invalidated |= m_print->invalidate_step(psWipeTower); invalidated |= m_print->invalidate_step(psWipeTower);
// Invalidate G-code export in any case.
invalidated |= m_print->invalidate_step(psGCodeExport);
return invalidated; return invalidated;
} }
bool PrintObject::invalidate_all_steps()
{
return Inherited::invalidate_all_steps() | m_print->invalidate_all_steps();
}
bool PrintObject::has_support_material() const bool PrintObject::has_support_material() const
{ {
return m_config.support_material return m_config.support_material

View File

@ -3658,7 +3658,6 @@ void GLCanvas3D::reload_scene(bool force)
{ {
if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr))
return; return;
#if !ENABLE_USE_UNIQUE_GLCONTEXT #if !ENABLE_USE_UNIQUE_GLCONTEXT
// ensures this canvas is current // ensures this canvas is current
if (!set_current()) if (!set_current())
@ -3695,7 +3694,7 @@ void GLCanvas3D::reload_scene(bool force)
if (m_regenerate_volumes) if (m_regenerate_volumes)
{ {
if (m_config->has("nozzle_diameter")) if (m_config->has("nozzle_diameter") && wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF)
{ {
// Should the wipe tower be visualized ? // Should the wipe tower be visualized ?
unsigned int extruders_count = (unsigned int)dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"))->values.size(); unsigned int extruders_count = (unsigned int)dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"))->values.size();
@ -3717,7 +3716,6 @@ void GLCanvas3D::reload_scene(bool force)
float depth = m_print->get_wipe_tower_depth(); float depth = m_print->get_wipe_tower_depth();
if (!m_print->is_step_done(psWipeTower)) if (!m_print->is_step_done(psWipeTower))
depth = (900.f/w) * (float)(extruders_count - 1) ; depth = (900.f/w) * (float)(extruders_count - 1) ;
m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower),
m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f); m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f);
} }
@ -6207,16 +6205,18 @@ void GLCanvas3D::_load_shells()
++object_id; ++object_id;
} }
// adds wipe tower's volume if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) {
double max_z = m_print->objects()[0]->model_object()->get_model()->bounding_box().max(2); // adds wipe tower's volume
const PrintConfig& config = m_print->config(); double max_z = m_print->objects()[0]->model_object()->get_model()->bounding_box().max(2);
unsigned int extruders_count = config.nozzle_diameter.size(); const PrintConfig& config = m_print->config();
if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) { unsigned int extruders_count = config.nozzle_diameter.size();
float depth = m_print->get_wipe_tower_depth(); if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) {
if (!m_print->is_step_done(psWipeTower)) float depth = m_print->get_wipe_tower_depth();
depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1) ; if (!m_print->is_step_done(psWipeTower))
m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1) ;
m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f); m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f);
}
} }
} }

View File

@ -704,7 +704,7 @@ void ObjectList::load_subobject(int type)
parts_changed(obj_idx); parts_changed(obj_idx);
for (int i = 0; i < part_names.size(); ++i) { for (int i = 0; i < part_names.size(); ++i) {
const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), /**m_bmp_vector[*/type/*]*/); const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), type);
if (i == part_names.size() - 1) if (i == part_names.size() - 1)
select_item(sel_item); select_item(sel_item);
@ -786,8 +786,11 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
const auto& sz = BoundingBoxf(bed_shape).size(); const auto& sz = BoundingBoxf(bed_shape).size();
const auto side = 0.1 * std::max(sz(0), sz(1)); const auto side = 0.1 * std::max(sz(0), sz(1));
if (type_name == _("Box")) if (type_name == _("Box")) {
mesh = make_cube(side, side, side); mesh = make_cube(side, side, side);
// box sets the base coordinate at 0, 0, move to center of plate
mesh.translate(-side * 0.5, -side * 0.5, 0);
}
else if (type_name == _("Cylinder")) else if (type_name == _("Cylinder"))
mesh = make_cylinder(0.5*side, side); mesh = make_cylinder(0.5*side, side);
else if (type_name == _("Sphere")) else if (type_name == _("Sphere"))
@ -1251,7 +1254,8 @@ void ObjectList::update_selections()
{ {
sels.Add(m_objects_model->GetItemById(selection.get_object_idx())); sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
} }
else if (selection.is_single_volume() || selection.is_multiple_volume() || selection.is_multiple_full_object()) { else if (selection.is_single_volume() || selection.is_modifier() ||
selection.is_multiple_volume() || selection.is_multiple_full_object()) {
for (auto idx : selection.get_volume_idxs()) { for (auto idx : selection.get_volume_idxs()) {
const auto gl_vol = selection.get_volume(idx); const auto gl_vol = selection.get_volume(idx);
if (selection.is_multiple_full_object()) if (selection.is_multiple_full_object())

View File

@ -86,6 +86,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent):
if (option_name == "Rotation") if (option_name == "Rotation")
def.min = -360; def.min = -360;
else
def.min == -1000;
const std::string lower_name = boost::algorithm::to_lower_copy(option_name); const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
@ -164,7 +166,7 @@ int ObjectManipulation::ol_selection()
void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection)
{ {
#if ENABLE_MODELVOLUME_TRANSFORM #if ENABLE_MODELVOLUME_TRANSFORM
if (selection.is_single_full_instance()) if (selection.is_single_full_instance() || selection.is_single_full_object())
#else #else
if (selection.is_single_full_object()) if (selection.is_single_full_object())
{ {

View File

@ -24,7 +24,7 @@ namespace Slic3r {
namespace GUI { namespace GUI {
Preview::Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data) Preview::Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
: m_canvas(nullptr) : m_canvas(nullptr)
, m_double_slider_sizer(nullptr) , m_double_slider_sizer(nullptr)
, m_label_view_type(nullptr) , m_label_view_type(nullptr)
@ -43,6 +43,7 @@ Preview::Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print,
, m_loaded(false) , m_loaded(false)
, m_enabled(false) , m_enabled(false)
, m_force_sliders_full_range(false) , m_force_sliders_full_range(false)
, m_schedule_background_process(schedule_background_process_func)
{ {
if (init(notebook, config, print, gcode_preview_data)) if (init(notebook, config, print, gcode_preview_data))
{ {
@ -488,6 +489,7 @@ void Preview::create_double_slider()
Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) {
auto& config = wxGetApp().preset_bundle->project_config; auto& config = wxGetApp().preset_bundle->project_config;
((config.option<ConfigOptionFloats>("colorprint_heights"))->values) = (m_slider->GetTicksValues()); ((config.option<ConfigOptionFloats>("colorprint_heights"))->values) = (m_slider->GetTicksValues());
m_schedule_background_process();
}); });
} }
@ -529,13 +531,16 @@ void Preview::fill_slider_values(std::vector<std::pair<int, double>> &values,
} }
// All ticks that would end up outside the slider range should be erased. // All ticks that would end up outside the slider range should be erased.
// TODO: this should probably be placed into more appropriate part of code, // TODO: this should be placed into more appropriate part of code,
// this way it relies on the Preview tab being active. // this function is e.g. not called when the last object is deleted
auto& config = wxGetApp().preset_bundle->project_config; auto& config = wxGetApp().preset_bundle->project_config;
std::vector<double> &ticks_from_config = (config.option<ConfigOptionFloats>("colorprint_heights"))->values; std::vector<double> &ticks_from_config = (config.option<ConfigOptionFloats>("colorprint_heights"))->values;
unsigned int old_size = ticks_from_config.size();
ticks_from_config.erase(std::remove_if(ticks_from_config.begin(), ticks_from_config.end(), ticks_from_config.erase(std::remove_if(ticks_from_config.begin(), ticks_from_config.end(),
[values](double val) { return values.back().second < val; }), [values](double val) { return values.back().second < val; }),
ticks_from_config.end()); ticks_from_config.end());
if (ticks_from_config.size() != old_size)
m_schedule_background_process();
} }
void Preview::set_double_slider_thumbs(const bool force_sliders_full_range, void Preview::set_double_slider_thumbs(const bool force_sliders_full_range,

View File

@ -40,6 +40,9 @@ class Preview : public wxPanel
Print* m_print; Print* m_print;
GCodePreviewData* m_gcode_preview_data; GCodePreviewData* m_gcode_preview_data;
// Calling this function object forces Plater::schedule_background_process.
std::function<void()> m_schedule_background_process;
unsigned int m_number_extruders; unsigned int m_number_extruders;
std::string m_preferred_color_mode; std::string m_preferred_color_mode;
@ -50,7 +53,7 @@ class Preview : public wxPanel
PrusaDoubleSlider* m_slider {nullptr}; PrusaDoubleSlider* m_slider {nullptr};
public: public:
Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = [](){});
virtual ~Preview(); virtual ~Preview();
wxGLCanvas* get_wxglcanvas() { return m_canvas; } wxGLCanvas* get_wxglcanvas() { return m_canvas; }

View File

@ -1002,7 +1002,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
_3DScene::add_canvas(canvas3D); _3DScene::add_canvas(canvas3D);
_3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample()); _3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample());
notebook->AddPage(canvas3D, _(L("3D"))); notebook->AddPage(canvas3D, _(L("3D")));
preview = new GUI::Preview(notebook, config, &print, &gcode_preview_data); preview = new GUI::Preview(notebook, config, &print, &gcode_preview_data, [this](){ schedule_background_process(); });
// XXX: If have OpenGL // XXX: If have OpenGL
_3DScene::enable_picking(canvas3D, true); _3DScene::enable_picking(canvas3D, true);

View File

@ -641,6 +641,7 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item)
PrusaObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx); PrusaObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx);
DeleteSettings(wxDataViewItem(last_child_node)); DeleteSettings(wxDataViewItem(last_child_node));
node_parent->GetChildren().Remove(last_child_node); node_parent->GetChildren().Remove(last_child_node);
node_parent->m_volumes_cnt = 0;
delete last_child_node; delete last_child_node;
#ifndef __WXGTK__ #ifndef __WXGTK__