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%{