From 1e185dacc466dec21fd3663999dde60be6f604ee Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 5 Apr 2018 09:02:03 +0200 Subject: [PATCH 01/15] Out of bed detection - GUI buttons disabled after object load if model detected as out of bed --- lib/Slic3r/GUI/Plater.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 14c2d66ae5..ecac430a44 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -105,7 +105,6 @@ sub new { $self->{btn_reslice}->Enable($enable); $self->{btn_print}->Enable($enable); $self->{btn_send_gcode}->Enable($enable); - $self->{btn_export_stl}->Enable($enable); }; # Initialize 3D plater @@ -1915,7 +1914,8 @@ sub object_list_changed { } my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; - my $method = ($have_objects && ! $export_in_progress) ? 'Enable' : 'Disable'; + my $model_fits = $self->{model}->fits_print_volume($self->{config}); + my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); } From 76beaa6421ca1391c1463ce68d3bc21615f68e67 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 5 Apr 2018 12:52:29 +0200 Subject: [PATCH 02/15] Objects colored by extruder color --- lib/Slic3r/GUI/3DScene.pm | 5 ++ lib/Slic3r/GUI/Plater/3D.pm | 2 + lib/Slic3r/GUI/Plater/ObjectCutDialog.pm | 1 + lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 1 + xs/src/slic3r/GUI/3DScene.cpp | 96 ++++++++++++++++++++++- xs/src/slic3r/GUI/3DScene.hpp | 10 +++ xs/src/slic3r/GUI/PresetBundle.cpp | 2 +- xs/src/slic3r/GUI/PresetBundle.hpp | 2 + xs/xsp/GUI_3DScene.xsp | 1 + 9 files changed, 118 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index c05de06c67..a89ed08884 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1677,6 +1677,11 @@ sub draw_warning { } } +sub update_volumes_colors_by_extruder { + my ($self, $config) = @_; + $self->volumes->update_colors_by_extruder($config); +} + sub opengl_info { my ($self, %params) = @_; diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index 09cc029302..36d55d27be 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -216,6 +216,8 @@ sub reload_scene { } } + $self->update_volumes_colors_by_extruder($self->{config}); + # checks for geometry outside the print volume to render it accordingly if (scalar @{$self->volumes} > 0) { diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index 7712bd01d0..0b5312b30a 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -247,6 +247,7 @@ sub _update { $self->{cut_options}{z}, [@expolygons], ); + $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->{config}); $self->{canvas}->Render; } } diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 8a8e6064c8..424d88d699 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -162,6 +162,7 @@ sub new { $canvas->load_object($self->{model_object}, undef, undef, [0]); $canvas->set_auto_bed_shape; $canvas->SetSize([500,700]); + $canvas->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); $canvas->zoom_to_volumes; } diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index a459b7cbf5..1ce3d76bfd 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -9,6 +9,7 @@ #include "../../libslic3r/GCode/PreviewData.hpp" #include "../../libslic3r/Print.hpp" #include "../../libslic3r/Slicing.hpp" +#include "../../slic3r/GUI/PresetBundle.hpp" #include "GCode/Analyzer.hpp" #include @@ -381,6 +382,15 @@ std::vector GLVolumeCollection::load_object( std::vector volumes_idx; for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++ volume_idx) { const ModelVolume *model_volume = model_object->volumes[volume_idx]; + + int extruder_id = -1; + if (!model_volume->modifier) + { + extruder_id = model_volume->config.has("extruder") ? model_volume->config.option("extruder")->getInt() : 0; + if (extruder_id == 0) + extruder_id = model_object->config.has("extruder") ? model_object->config.option("extruder")->getInt() : 0; + } + for (int instance_idx : instance_idxs) { const ModelInstance *instance = model_object->instances[instance_idx]; TriangleMesh mesh = model_volume->mesh; @@ -410,8 +420,14 @@ std::vector GLVolumeCollection::load_object( v.drag_group_id = obj_idx * 1000; else if (drag_by == "instance") v.drag_group_id = obj_idx * 1000 + instance_idx; - if (! model_volume->modifier) + + if (!model_volume->modifier) + { v.layer_height_texture = layer_height_texture; + if (extruder_id != -1) + v.extruder_id = extruder_id; + } + v.is_modifier = model_volume->modifier; } } @@ -438,6 +454,7 @@ int GLVolumeCollection::load_wipe_tower_preview( v.composite_id = obj_idx * 1000000; v.select_group_id = obj_idx * 1000000; v.drag_group_id = obj_idx * 1000; + v.is_wipe_tower = true; return int(this->volumes.size() - 1); } @@ -642,6 +659,83 @@ void GLVolumeCollection::update_outside_state(const DynamicPrintConfig* config, } } +void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config) +{ + static const float inv_255 = 1.0f / 255.0f; + + struct Color + { + std::string text; + unsigned char rgb[3]; + + Color() + : text("") + { + rgb[0] = 255; + rgb[1] = 255; + rgb[2] = 255; + } + + void set(const std::string& text, unsigned char* rgb) + { + this->text = text; + ::memcpy((void*)this->rgb, (const void*)rgb, 3 * sizeof(unsigned char)); + } + }; + + if (config == nullptr) + return; + + const ConfigOptionStrings* extruders_opt = dynamic_cast(config->option("extruder_colour")); + if (extruders_opt == nullptr) + return; + + const ConfigOptionStrings* filamemts_opt = dynamic_cast(config->option("filament_colour")); + if (filamemts_opt == nullptr) + return; + + unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size()); + if (colors_count == 0) + return; + + std::vector colors(colors_count); + + unsigned char rgb[3]; + for (unsigned int i = 0; i < colors_count; ++i) + { + const std::string& txt_color = config->opt_string("extruder_colour", i); + if (PresetBundle::parse_color(txt_color, rgb)) + { + colors[i].set(txt_color, rgb); + } + else + { + const std::string& txt_color = config->opt_string("filament_colour", i); + if (PresetBundle::parse_color(txt_color, rgb)) + colors[i].set(txt_color, rgb); + } + } + + for (GLVolume* volume : volumes) + { + if ((volume == nullptr) || volume->is_modifier || volume->is_wipe_tower) + continue; + + int extruder_id = volume->extruder_id - 1; + if ((extruder_id < 0) || ((unsigned int)colors.size() <= extruder_id)) + extruder_id = 0; + + const Color& color = colors[extruder_id]; + if (!color.text.empty()) + { + for (int i = 0; i < 3; ++i) + { + volume->color[i] = (float)color.rgb[i] * inv_255; + } + } + } +} + std::vector GLVolumeCollection::get_current_print_zs() const { // Collect layer top positions of all volumes. diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 0fd31d8d69..6486a7f0e7 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -246,12 +246,15 @@ public: composite_id(-1), select_group_id(-1), drag_group_id(-1), + extruder_id(0), selected(false), is_active(true), zoom_to_volumes(true), outside_printer_detection_enabled(true), is_outside(false), hover(false), + is_modifier(false), + is_wipe_tower(false), tverts_range(0, size_t(-1)), qverts_range(0, size_t(-1)) { @@ -287,6 +290,8 @@ public: int select_group_id; // An ID for group dragging. It may be the same for all meshes of all object instances, or for just a single object instance. int drag_group_id; + // An ID containing the extruder ID (used to select color). + int extruder_id; // Is this object selected? bool selected; // Whether or not this volume is active for rendering @@ -299,6 +304,10 @@ public: bool is_outside; // Boolean: Is mouse over this object? bool hover; + // Wheter or not this volume has been generated from a modifier + bool is_modifier; + // Wheter or not this volume has been generated from the wipe tower + bool is_wipe_tower; // Interleaved triangles & normals with indexed triangles & quads. GLIndexedVertexArray indexed_vertex_array; @@ -417,6 +426,7 @@ public: } void update_outside_state(const DynamicPrintConfig* config, bool all_inside); + void update_colors_by_extruder(const DynamicPrintConfig* config); // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection std::vector get_current_print_zs() const; diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index bf79c6562e..ce56d4cb1f 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -788,7 +788,7 @@ static inline int hex_digit_to_int(const char c) (c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1; } -static inline bool parse_color(const std::string &scolor, unsigned char *rgb_out) +bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out) { rgb_out[0] = rgb_out[1] = rgb_out[2] = 0; if (scolor.size() != 7 || scolor.front() != '#') diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index e6aea206d1..e25647c7b1 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -98,6 +98,8 @@ public: // preset if the current print or filament preset is not compatible. void update_compatible_with_printer(bool select_other_if_incompatible); + static bool parse_color(const std::string &scolor, unsigned char *rgb_out); + private: // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. // and the external config is just referenced, not stored into user profile directory. diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 25aa6b81a7..ce773adebf 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -105,6 +105,7 @@ void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); void update_outside_state(DynamicPrintConfig* config, bool all_inside); + void update_colors_by_extruder(DynamicPrintConfig* config); bool move_volume_up(int idx) %code%{ From 3a61833d131ac3ae0181f8bc34212d63133c7270 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 5 Apr 2018 15:55:50 +0200 Subject: [PATCH 03/15] Update view in object's setting dialog when changing extruder --- lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 424d88d699..c7b9049d87 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -88,7 +88,7 @@ sub new { $self->{btn_move_down}->SetFont($Slic3r::GUI::small_font); # part settings panel - $self->{settings_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { $self->{part_settings_changed} = 1; }); + $self->{settings_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { $self->{part_settings_changed} = 1; $self->_update_canvas; }); my $settings_sizer = Wx::StaticBoxSizer->new($self->{staticbox} = Wx::StaticBox->new($self, -1, "Part Settings"), wxVERTICAL); $settings_sizer->Add($self->{settings_panel}, 1, wxEXPAND | wxALL, 0); @@ -479,6 +479,7 @@ sub _parts_changed { $self->{canvas}->reset_objects; $self->{canvas}->load_object($self->{model_object}); $self->{canvas}->zoom_to_volumes; + $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); $self->{canvas}->Render; } } @@ -509,6 +510,25 @@ sub PartSettingsChanged { return $self->{part_settings_changed}; } +sub _update_canvas { + my ($self) = @_; + + if ($self->{canvas}) { + $self->{canvas}->reset_objects; + $self->{canvas}->load_object($self->{model_object}); + + # restore selection, if any + if (my $itemData = $self->get_selection) { + if ($itemData->{type} eq 'volume') { + $self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1); + } + } + + $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); + $self->{canvas}->Render; + } +} + sub _update { my ($self) = @_; my ($m_x, $m_y, $m_z) = ($self->{move_options}{x}, $self->{move_options}{y}, $self->{move_options}{z}); @@ -529,6 +549,7 @@ sub _update { push @objects, $self->{model_object}; $self->{canvas}->reset_objects; $self->{canvas}->load_object($_, undef, [0]) for @objects; + $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); $self->{canvas}->Render; } From 254592c849326ed552677ff8e923922f678220c9 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 9 Apr 2018 14:20:44 +0200 Subject: [PATCH 04/15] Delete key enabled in Object's Settings Dialog --- lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index c7b9049d87..47fd8a0929 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -401,14 +401,17 @@ sub on_tree_key_down { my ($self, $event) = @_; my $keycode = $event->GetKeyCode; # Wx >= 0.9911 - if (defined(&Wx::TreeEvent::GetKeyEvent) && - ($event->GetKeyEvent->GetModifiers & wxMOD_CONTROL)) { - if ($keycode == WXK_UP) { - $event->Skip; - $self->on_btn_move_up; - } elsif ($keycode == WXK_DOWN) { - $event->Skip; - $self->on_btn_move_down; + if (defined(&Wx::TreeEvent::GetKeyEvent)) { + if ($event->GetKeyEvent->GetModifiers & wxMOD_CONTROL) { + if ($keycode == WXK_UP) { + $event->Skip; + $self->on_btn_move_up; + } elsif ($keycode == WXK_DOWN) { + $event->Skip; + $self->on_btn_move_down; + } + } elsif ($keycode == WXK_DELETE) { + $self->on_btn_delete; } } } From df328179929b977398f47ee4d8d2a42958d37839 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 9 Apr 2018 14:57:23 +0200 Subject: [PATCH 05/15] Auto assign multi-part extruders --- xs/src/libslic3r/Model.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index ad2ce54cd2..d49594c722 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -406,9 +406,24 @@ void Model::convert_multipart_object() ModelObject* object = new ModelObject(this); object->input_file = this->objects.front()->input_file; + unsigned int auto_extruder_id = 1; + char str_extruder[64]; + for (const ModelObject* o : this->objects) for (const ModelVolume* v : o->volumes) - object->add_volume(*v)->name = o->name; + { + ModelVolume* new_v = object->add_volume(*v); + if (new_v != nullptr) + { + new_v->name = o->name; + + sprintf(str_extruder, "%ud", auto_extruder_id); + new_v->config.set_deserialize("extruder", str_extruder); + + if (++auto_extruder_id > 4) + auto_extruder_id = 1; + } + } for (const ModelInstance* i : this->objects.front()->instances) object->add_instance(*i); From 9993f2215d56d7dfdf727794b590756893a2ba39 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 10 Apr 2018 12:17:55 +0200 Subject: [PATCH 06/15] Auto assignement of extruder, after object's splitting to parts --- xs/src/libslic3r/Model.cpp | 40 +++++++++++++++++++++++++++++--------- xs/src/libslic3r/Model.hpp | 6 ++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index d49594c722..5611067132 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -16,6 +16,8 @@ namespace Slic3r { + unsigned int Model::s_auto_extruder_id = 1; + Model::Model(const Model &other) { // copy materials @@ -405,9 +407,8 @@ void Model::convert_multipart_object() ModelObject* object = new ModelObject(this); object->input_file = this->objects.front()->input_file; - - unsigned int auto_extruder_id = 1; - char str_extruder[64]; + + reset_auto_extruder_id(); for (const ModelObject* o : this->objects) for (const ModelVolume* v : o->volumes) @@ -416,12 +417,7 @@ void Model::convert_multipart_object() if (new_v != nullptr) { new_v->name = o->name; - - sprintf(str_extruder, "%ud", auto_extruder_id); - new_v->config.set_deserialize("extruder", str_extruder); - - if (++auto_extruder_id > 4) - auto_extruder_id = 1; + new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string()); } } @@ -481,6 +477,28 @@ bool Model::fits_print_volume(const FullPrintConfig &config) const return print_volume.contains(transformed_bounding_box()); } +unsigned int Model::get_auto_extruder_id() +{ + unsigned int id = s_auto_extruder_id; + + if (++s_auto_extruder_id > 4) + reset_auto_extruder_id(); + + return id; +} + +std::string Model::get_auto_extruder_id_as_string() +{ + char str_extruder[64]; + sprintf(str_extruder, "%ud", get_auto_extruder_id()); + return str_extruder; +} + +void Model::reset_auto_extruder_id() +{ + s_auto_extruder_id = 1; +} + ModelObject::ModelObject(Model *model, const ModelObject &other, bool copy_volumes) : name(other.name), input_file(other.input_file), @@ -1010,6 +1028,9 @@ size_t ModelVolume::split() size_t idx = 0; size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin(); std::string name = this->name; + + Model::reset_auto_extruder_id(); + for (TriangleMesh *mesh : meshptrs) { mesh->repair(); if (idx == 0) @@ -1019,6 +1040,7 @@ size_t ModelVolume::split() char str_idx[64]; sprintf(str_idx, "_%d", idx + 1); this->object->volumes[ivolume]->name = name + str_idx; + this->object->volumes[ivolume]->config.set_deserialize("extruder", Model::get_auto_extruder_id_as_string()); delete mesh; ++ idx; } diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index bf7f60e36c..0c0ffe7769 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -230,6 +230,8 @@ private: // all objects may share mutliple materials. class Model { + static unsigned int s_auto_extruder_id; + public: // Materials are owned by a model and referenced by objects through t_model_material_id. // Single material may be shared by multiple models. @@ -288,6 +290,10 @@ public: bool fits_print_volume(const FullPrintConfig &config) const; void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); } + + static unsigned int get_auto_extruder_id(); + static std::string get_auto_extruder_id_as_string(); + static void reset_auto_extruder_id(); }; } From a81f78045b209420cbc243af27890bd196cc2697 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 10 Apr 2018 12:47:09 +0200 Subject: [PATCH 07/15] Delete key enabled in Object's Settings Dialog also for 3D view --- lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 47fd8a0929..f7e38ed873 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -9,7 +9,7 @@ use utf8; use File::Basename qw(basename); use Wx qw(:misc :sizer :treectrl :button :keycode wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxID_CANCEL wxMOD_CONTROL wxTheApp); -use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN); +use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN EVT_KEY_DOWN); use base 'Wx::Panel'; use constant ICON_OBJECT => 0; @@ -191,6 +191,14 @@ sub new { EVT_BUTTON($self, $self->{btn_split}, \&on_btn_split); EVT_BUTTON($self, $self->{btn_move_up}, \&on_btn_move_up); EVT_BUTTON($self, $self->{btn_move_down}, \&on_btn_move_down); + EVT_KEY_DOWN($canvas, sub { + my ($canvas, $event) = @_; + if ($event->GetKeyCode == WXK_DELETE) { + $canvas->GetParent->on_btn_delete; + } else { + $event->Skip; + } + }); $self->reload_tree; From b961711f28c90886b32ce88a2130113dac41f455 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 10 Apr 2018 13:39:10 +0200 Subject: [PATCH 08/15] Fixed autoscale of objects after loading --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ecac430a44..c74b2d32c3 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -737,7 +737,7 @@ sub load_model_objects { { # if the object is too large (more than 5 times the bed), scale it down my $size = $o->bounding_box->size; - my $ratio = max(@$size[X,Y]) / unscale(max(@$bed_size[X,Y])); + my $ratio = max($size->x / unscale($bed_size->x), $size->y / unscale($bed_size->y)); if ($ratio > 5) { $_->set_scaling_factor(1/$ratio) for @{$o->instances}; $scaled_down = 1; From d789b5c0df5042516c66729fa9f63d63907d9180 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 10 Apr 2018 14:12:16 +0200 Subject: [PATCH 09/15] Fixed warning texture not disappearing when deleting object out of bed --- lib/Slic3r/GUI/Plater/3D.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index 36d55d27be..e9416b3cc5 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -231,6 +231,9 @@ sub reload_scene { Slic3r::GUI::_3DScene::reset_warning_texture(); $self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons); } + } else { + $self->set_warning_enabled(0); + Slic3r::GUI::_3DScene::reset_warning_texture(); } } From b062cddeea4f6ef11557b6bb533a046076ba177d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 12 Apr 2018 12:56:42 +0200 Subject: [PATCH 10/15] Fixed object cutting --- xs/src/libslic3r/Model.cpp | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 5611067132..bda49421d0 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -863,33 +863,9 @@ void ModelObject::cut(coordf_t z, Model* model) const lower->add_volume(*volume); } else { TriangleMesh upper_mesh, lower_mesh; - // TODO: shouldn't we use object bounding box instead of per-volume bb? - coordf_t cut_z = z + volume->mesh.bounding_box().min.z; - if (false) { -// if (volume->mesh.has_multiple_patches()) { - // Cutting algorithm does not work on intersecting meshes. - // As we are not sure whether the meshes don't intersect, - // we rather split the mesh into multiple non-intersecting pieces. - TriangleMeshPtrs meshptrs = volume->mesh.split(); - for (TriangleMeshPtrs::iterator mesh = meshptrs.begin(); mesh != meshptrs.end(); ++mesh) { - printf("Cutting mesh patch %d of %d\n", int(mesh - meshptrs.begin()), int(meshptrs.size())); - (*mesh)->repair(); - TriangleMeshSlicer tms(*mesh); - if (mesh == meshptrs.begin()) { - tms.cut(cut_z, &upper_mesh, &lower_mesh); - } else { - TriangleMesh upper_mesh_this, lower_mesh_this; - tms.cut(cut_z, &upper_mesh_this, &lower_mesh_this); - upper_mesh.merge(upper_mesh_this); - lower_mesh.merge(lower_mesh_this); - } - delete *mesh; - } - } else { - printf("Cutting mesh patch\n"); - TriangleMeshSlicer tms(&volume->mesh); - tms.cut(cut_z, &upper_mesh, &lower_mesh); - } + printf("Cutting mesh patch\n"); + TriangleMeshSlicer tms(&volume->mesh); + tms.cut(z, &upper_mesh, &lower_mesh); upper_mesh.repair(); lower_mesh.repair(); From a3fc49ee76673ddcc9650baffc6a95c2f02ce144 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 12 Apr 2018 13:54:26 +0200 Subject: [PATCH 11/15] Fixed hovering not shown on out of print bed objects --- lib/Slic3r/GUI/3DScene.pm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index a89ed08884..e5990fe8d5 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1828,7 +1828,6 @@ sub _fragment_shader_Gouraud { return <<'FRAGMENT'; #version 110 -const vec4 OUTSIDE_COLOR = vec4(0.24, 0.42, 0.62, 1.0); const vec3 ZERO = vec3(0.0, 0.0, 0.0); // x = tainted, y = specular; @@ -1841,11 +1840,9 @@ uniform vec4 uniform_color; void main() { - // if the fragment is outside the print volume use predefined color - vec4 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? OUTSIDE_COLOR : uniform_color; - - gl_FragColor = vec4(intensity.y, intensity.y, intensity.y, 0.0) + color * intensity.x; - gl_FragColor.a = color.a; + // if the fragment is outside the print volume -> use darker color + vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb; + gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a); } FRAGMENT From acd8d2df98d5207c0fb8091c96a8d86a57980387 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 13 Apr 2018 09:01:48 +0200 Subject: [PATCH 12/15] Fixed layer height profile editing for multipart objects --- lib/Slic3r/GUI/3DScene.pm | 12 ++++++------ xs/src/slic3r/GUI/3DScene.cpp | 7 ++++++- xs/src/slic3r/GUI/3DScene.hpp | 5 +---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index e5990fe8d5..13460cfed2 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1527,10 +1527,13 @@ sub draw_active_object_annotations { my ($reset_left, $reset_bottom, $reset_right, $reset_top) = $self->_variable_layer_thickness_reset_rect_viewport; my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative; + my $print_object = $self->{print}->get_object($object_idx); + my $z_max = $print_object->model_object->bounding_box->z_max; + $self->{layer_height_edit_shader}->enable; $self->{layer_height_edit_shader}->set_uniform('z_to_texture_row', $volume->layer_height_texture_z_to_row_id); $self->{layer_height_edit_shader}->set_uniform('z_texture_row_to_normalized', 1. / $volume->layer_height_texture_height); - $self->{layer_height_edit_shader}->set_uniform('z_cursor', $volume->bounding_box->z_max * $z_cursor_relative); + $self->{layer_height_edit_shader}->set_uniform('z_cursor', $z_max * $z_cursor_relative); $self->{layer_height_edit_shader}->set_uniform('z_cursor_band_width', $self->{layer_height_edit_band_width}); glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_z_texture_id}); glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $volume->layer_height_texture_width, $volume->layer_height_texture_height, @@ -1552,8 +1555,8 @@ sub draw_active_object_annotations { glBegin(GL_QUADS); glVertex3f($bar_left, $bar_bottom, 0); glVertex3f($bar_right, $bar_bottom, 0); - glVertex3f($bar_right, $bar_top, $volume->bounding_box->z_max); - glVertex3f($bar_left, $bar_top, $volume->bounding_box->z_max); + glVertex3f($bar_right, $bar_top, $z_max); + glVertex3f($bar_left, $bar_top, $z_max); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); $self->{layer_height_edit_shader}->disable; @@ -1572,7 +1575,6 @@ sub draw_active_object_annotations { # Paint the graph. #FIXME show some kind of legend. - my $print_object = $self->{print}->get_object($object_idx); my $max_z = unscale($print_object->size->z); my $profile = $print_object->model_object->layer_height_profile; my $layer_height = $print_object->config->get('layer_height'); @@ -1934,8 +1936,6 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -uniform float z_to_texture_row; - // x = tainted, y = specular; varying vec2 intensity; diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 1ce3d76bfd..a33ef4d1c6 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -305,7 +305,7 @@ void GLVolume::render_using_layer_height() const glUniform1f(z_texture_row_to_normalized_id, (GLfloat)(1.0f / layer_height_texture_height())); if (z_cursor_id >= 0) - glUniform1f(z_cursor_id, (GLfloat)(bounding_box.max.z * layer_height_texture_data.z_cursor_relative)); + glUniform1f(z_cursor_id, (GLfloat)(layer_height_texture_data.print_object->model_object()->bounding_box().max.z * layer_height_texture_data.z_cursor_relative)); if (z_cursor_band_width_id >= 0) glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width); @@ -327,6 +327,11 @@ void GLVolume::render_using_layer_height() const glUseProgram(current_program_id); } +double GLVolume::layer_height_texture_z_to_row_id() const +{ + return (this->layer_height_texture.get() == nullptr) ? 0.0 : double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * this->layer_height_texture_data.print_object->model_object()->bounding_box().max.z); +} + void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force) { GLTexture *tex = this->layer_height_texture.get(); diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 6486a7f0e7..380206dd97 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -361,10 +361,7 @@ public: return (layer_height_texture.get() == nullptr) ? 0 : (void*)(layer_height_texture->data.data() + layer_height_texture->width * layer_height_texture->height * 4); } - double layer_height_texture_z_to_row_id() const { - return (this->layer_height_texture.get() == nullptr) ? 0. : - double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * bounding_box.max.z); - } + double layer_height_texture_z_to_row_id() const; void generate_layer_height_texture(PrintObject *print_object, bool force); void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, PrintObject* print_object, float z_cursor_relative, float edit_band_width) From 7b29ecb15cf450347cedece3d3445449b2f57c1f Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 13 Apr 2018 12:15:43 +0200 Subject: [PATCH 13/15] Fixed cutting plane z in 3D view when object is scaled --- lib/Slic3r/GUI/Plater/ObjectCutDialog.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index 0b5312b30a..7f930c1d0f 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -244,7 +244,7 @@ sub _update { $self->{canvas}->reset_objects; $self->{canvas}->load_object($_, undef, undef, [0]) for @objects; $self->{canvas}->SetCuttingPlane( - $self->{cut_options}{z}, + $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor, [@expolygons], ); $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->{config}); From 359e7e4d32225d485c36c4733ba9f3847d5c80b5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 13 Apr 2018 13:59:36 +0200 Subject: [PATCH 14/15] Scale down meshes of too big objects after loading them --- lib/Slic3r/GUI/Plater.pm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c74b2d32c3..ce37a16511 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -738,7 +738,13 @@ sub load_model_objects { # if the object is too large (more than 5 times the bed), scale it down my $size = $o->bounding_box->size; my $ratio = max($size->x / unscale($bed_size->x), $size->y / unscale($bed_size->y)); - if ($ratio > 5) { + if ($ratio > 10000) { + # the size of the object is too big -> this could lead to overflow when moving to clipper coordinates, + # so scale down the mesh + $o->scale_xyz(Slic3r::Pointf3->new(1/$ratio, 1/$ratio, 1/$ratio)); + $scaled_down = 1; + } + elsif ($ratio > 5) { $_->set_scaling_factor(1/$ratio) for @{$o->instances}; $scaled_down = 1; } From 659eb3412b132350bafad6a9c8fd74feaa5560fd Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 13 Apr 2018 14:40:42 +0200 Subject: [PATCH 15/15] Fixed value of z in cut dialog when object is scaled --- lib/Slic3r/GUI/Plater/ObjectCutDialog.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index 7f930c1d0f..7b5752cd2b 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -60,7 +60,7 @@ sub new { label => 'Z', default => $self->{cut_options}{z}, min => 0, - max => $self->{model_object}->bounding_box->size->z * $self->{model_object}->instances->[0]->scaling_factor, + max => $self->{model_object}->bounding_box->size->z, full_width => 1, )); { @@ -244,7 +244,7 @@ sub _update { $self->{canvas}->reset_objects; $self->{canvas}->load_object($_, undef, undef, [0]) for @objects; $self->{canvas}->SetCuttingPlane( - $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor, + $self->{cut_options}{z}, [@expolygons], ); $self->{canvas}->update_volumes_colors_by_extruder($self->GetParent->{config});