diff --git a/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp index 26e125bbcf..ec5de71b11 100644 --- a/src/libslic3r/GCode/Analyzer.cpp +++ b/src/libslic3r/GCode/Analyzer.cpp @@ -978,7 +978,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ float volumetric_rate = FLT_MAX; GCodePreviewData::Range height_range; GCodePreviewData::Range width_range; - GCodePreviewData::Range feedrate_range; + GCodePreviewData::MultiRange feedrate_range; GCodePreviewData::Range volumetric_rate_range; GCodePreviewData::Range fan_speed_range; @@ -1013,7 +1013,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm; height_range.update_from(move.data.height); width_range.update_from(move.data.width); - feedrate_range.update_from(move.data.feedrate); + feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::EXTRUSION); volumetric_rate_range.update_from(volumetric_rate); fan_speed_range.update_from(move.data.fan_speed); } @@ -1066,7 +1066,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s GCodePreviewData::Range height_range; GCodePreviewData::Range width_range; - GCodePreviewData::Range feedrate_range; + GCodePreviewData::MultiRange feedrate_range; // to avoid to call the callback too often unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1); @@ -1106,7 +1106,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s extruder_id = move.data.extruder_id; height_range.update_from(move.data.height); width_range.update_from(move.data.width); - feedrate_range.update_from(move.data.feedrate); + feedrate_range.update_from(move.data.feedrate, GCodePreviewData::FeedrateKind::TRAVEL); } // store last polyline diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index e7475089ac..64057ec8d5 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -11,9 +11,7 @@ namespace Slic3r { -const GCodePreviewData::Color GCodePreviewData::Color::Dummy(0.0f, 0.0f, 0.0f, 0.0f); - -std::vector GCodePreviewData::Color::as_bytes() const +std::vector Color::as_bytes() const { std::vector ret; for (unsigned int i = 0; i < 4; ++i) @@ -38,20 +36,6 @@ GCodePreviewData::Travel::Polyline::Polyline(EType type, EDirection direction, f { } -const GCodePreviewData::Color GCodePreviewData::Range::Default_Colors[Colors_Count] = -{ - Color(0.043f, 0.173f, 0.478f, 1.0f), - Color(0.075f, 0.349f, 0.522f, 1.0f), - Color(0.110f, 0.533f, 0.569f, 1.0f), - Color(0.016f, 0.839f, 0.059f, 1.0f), - Color(0.667f, 0.949f, 0.000f, 1.0f), - Color(0.988f, 0.975f, 0.012f, 1.0f), - Color(0.961f, 0.808f, 0.039f, 1.0f), - Color(0.890f, 0.533f, 0.125f, 1.0f), - Color(0.820f, 0.408f, 0.188f, 1.0f), - Color(0.761f, 0.322f, 0.235f, 1.0f) -}; - GCodePreviewData::Range::Range() { reset(); @@ -59,54 +43,52 @@ GCodePreviewData::Range::Range() void GCodePreviewData::Range::reset() { - min = FLT_MAX; - max = -FLT_MAX; + min_val = FLT_MAX; + max_val = -FLT_MAX; } bool GCodePreviewData::Range::empty() const { - return min == max; + return min_val >= max_val; } void GCodePreviewData::Range::update_from(float value) { - min = std::min(min, value); - max = std::max(max, value); + min_val = std::min(min_val, value); + max_val = std::max(max_val, value); } -void GCodePreviewData::Range::update_from(const Range& other) +void GCodePreviewData::Range::update_from(const RangeBase& other) { - min = std::min(min, other.min); - max = std::max(max, other.max); + min_val = std::min(min_val, other.min()); + max_val = std::max(max_val, other.max()); } -void GCodePreviewData::Range::set_from(const Range& other) +float GCodePreviewData::RangeBase::step_size() const { - min = other.min; - max = other.max; + return (max() - min()) / static_cast(range_rainbow_colors.size() - 1); } -float GCodePreviewData::Range::step_size() const -{ - return (max - min) / (float)(Colors_Count - 1); -} - -GCodePreviewData::Color GCodePreviewData::Range::get_color_at(float value) const +Color GCodePreviewData::RangeBase::get_color_at(float value) const { if (empty()) - return Color::Dummy; + return Color{}; - float global_t = (value - min) / step_size(); + // Input value scaled to the color range + const float global_t = std::max(0.0f, value - min()) / step_size(); // lower limit of 0.0f + + constexpr std::size_t color_max_idx = range_rainbow_colors.size() - 1; - unsigned int low = (unsigned int)global_t; - unsigned int high = clamp((unsigned int)0, Colors_Count - 1, low + 1); + // Compute the two colors just below (low) and above (high) the input value + const std::size_t color_low_idx = clamp(std::size_t{0}, color_max_idx, static_cast(global_t)); + const std::size_t color_high_idx = clamp(std::size_t{0}, color_max_idx, color_low_idx + 1); + const Color color_low = range_rainbow_colors[color_low_idx]; + const Color color_high = range_rainbow_colors[color_high_idx]; - Color color_low = colors[low]; - Color color_high = colors[high]; + // Compute how far the value is between the low and high colors so that they can be interpolated + const float local_t = std::min(global_t - static_cast(color_low_idx), 1.0f); // upper limit of 1.0f - float local_t = global_t - (float)low; - - // interpolate in RGB space + // Interpolate between the low and high colors in RGB space to find exactly which color the input value should get Color ret; for (unsigned int i = 0; i < 4; ++i) { @@ -115,13 +97,23 @@ GCodePreviewData::Color GCodePreviewData::Range::get_color_at(float value) const return ret; } -GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePreviewData::Color& color) +float GCodePreviewData::Range::min() const +{ + return min_val; +} + +float GCodePreviewData::Range::max() const +{ + return max_val; +} + +GCodePreviewData::LegendItem::LegendItem(const std::string& text, const Color& color) : text(text) , color(color) { } -const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] = +const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] = { Color(0.0f, 0.0f, 0.0f, 1.0f), // erNone Color(1.0f, 0.0f, 0.0f, 1.0f), // erPerimeter @@ -180,7 +172,7 @@ size_t GCodePreviewData::Extrusion::memory_used() const const float GCodePreviewData::Travel::Default_Width = 0.075f; const float GCodePreviewData::Travel::Default_Height = 0.075f; -const GCodePreviewData::Color GCodePreviewData::Travel::Default_Type_Colors[Num_Types] = +const Color GCodePreviewData::Travel::Default_Type_Colors[Num_Types] = { Color(0.0f, 0.0f, 0.75f, 1.0f), // Move Color(0.0f, 0.75f, 0.0f, 1.0f), // Extrude @@ -206,7 +198,7 @@ size_t GCodePreviewData::Travel::memory_used() const return out; } -const GCodePreviewData::Color GCodePreviewData::Retraction::Default_Color = GCodePreviewData::Color(1.0f, 1.0f, 1.0f, 1.0f); +const Color GCodePreviewData::Retraction::Default_Color = Color(1.0f, 1.0f, 1.0f, 1.0f); GCodePreviewData::Retraction::Position::Position(const Vec3crd& position, float width, float height) : position(position) @@ -238,17 +230,15 @@ GCodePreviewData::GCodePreviewData() void GCodePreviewData::set_default() { - ::memcpy((void*)ranges.height.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); - ::memcpy((void*)ranges.width.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); - ::memcpy((void*)ranges.feedrate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); - ::memcpy((void*)ranges.fan_speed.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); - ::memcpy((void*)ranges.volumetric_rate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); - extrusion.set_default(); travel.set_default(); retraction.set_default(); unretraction.set_default(); shell.set_default(); + + // Configure the color range for feedrate to match the default for travels and to enable extrusions since they are always visible + ranges.feedrate.set_mode(FeedrateKind::TRAVEL, travel.is_visible); + ranges.feedrate.set_mode(FeedrateKind::EXTRUSION, true); } void GCodePreviewData::reset() @@ -268,32 +258,32 @@ bool GCodePreviewData::empty() const return extrusion.layers.empty() && travel.polylines.empty() && retraction.positions.empty() && unretraction.positions.empty(); } -GCodePreviewData::Color GCodePreviewData::get_extrusion_role_color(ExtrusionRole role) const +Color GCodePreviewData::get_extrusion_role_color(ExtrusionRole role) const { return extrusion.role_colors[role]; } -GCodePreviewData::Color GCodePreviewData::get_height_color(float height) const +Color GCodePreviewData::get_height_color(float height) const { return ranges.height.get_color_at(height); } -GCodePreviewData::Color GCodePreviewData::get_width_color(float width) const +Color GCodePreviewData::get_width_color(float width) const { return ranges.width.get_color_at(width); } -GCodePreviewData::Color GCodePreviewData::get_feedrate_color(float feedrate) const +Color GCodePreviewData::get_feedrate_color(float feedrate) const { return ranges.feedrate.get_color_at(feedrate); } -GCodePreviewData::Color GCodePreviewData::get_fan_speed_color(float fan_speed) const +Color GCodePreviewData::get_fan_speed_color(float fan_speed) const { return ranges.fan_speed.get_color_at(fan_speed); } -GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate) const +Color GCodePreviewData::get_volumetric_rate_color(float rate) const { return ranges.volumetric_rate.get_color_at(rate); } @@ -312,7 +302,7 @@ void GCodePreviewData::set_extrusion_role_color(const std::string& role_name, fl void GCodePreviewData::set_extrusion_paths_colors(const std::vector& colors) { - unsigned int size = (unsigned int)colors.size(); + unsigned int size = (unsigned int)range_rainbow_colors.size(); if (size % 2 != 0) return; @@ -384,16 +374,16 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: { struct Helper { - static void FillListFromRange(LegendItemsList& list, const Range& range, unsigned int decimals, float scale_factor) + static void FillListFromRange(LegendItemsList& list, const RangeBase& range, unsigned int decimals, float scale_factor) { - list.reserve(Range::Colors_Count); + list.reserve(range_rainbow_colors.size()); float step = range.step_size(); - for (int i = Range::Colors_Count - 1; i >= 0; --i) + for (int i = static_cast(range_rainbow_colors.size()) - 1; i >= 0; --i) { char buf[1024]; - sprintf(buf, "%.*f", decimals, scale_factor * (range.min + (float)i * step)); - list.emplace_back(buf, range.colors[i]); + sprintf(buf, "%.*f", decimals, scale_factor * (range.min() + (float)i * step)); + list.emplace_back(buf, range_rainbow_colors[i]); } } }; @@ -446,8 +436,8 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: items.reserve(tools_colors_count); for (unsigned int i = 0; i < tools_colors_count; ++i) { - GCodePreviewData::Color color; - ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); + Color color; + ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); items.emplace_back((boost::format(Slic3r::I18N::translate(L("Extruder %d"))) % (i + 1)).str(), color); } @@ -460,7 +450,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: if (color_print_cnt == 1) // means "Default print color" { Color color; - ::memcpy((void*)color.rgba, (const void*)(tool_colors.data()), 4 * sizeof(float)); + ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data()), 4 * sizeof(float)); items.emplace_back(cp_items[0], color); break; @@ -472,7 +462,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: for (int i = 0 ; i < color_print_cnt; ++i) { Color color; - ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); + ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); items.emplace_back(cp_items[i], color); } @@ -496,23 +486,23 @@ size_t GCodePreviewData::memory_used() const sizeof(shell) + sizeof(ranges); } -const std::vector& GCodePreviewData::ColorPrintColors() +const std::vector& ColorPrintColors() { static std::vector color_print = {"#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6"}; return color_print; } -GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2) +Color operator + (const Color& c1, const Color& c2) { - return GCodePreviewData::Color(clamp(0.0f, 1.0f, c1.rgba[0] + c2.rgba[0]), + return Color(clamp(0.0f, 1.0f, c1.rgba[0] + c2.rgba[0]), clamp(0.0f, 1.0f, c1.rgba[1] + c2.rgba[1]), clamp(0.0f, 1.0f, c1.rgba[2] + c2.rgba[2]), clamp(0.0f, 1.0f, c1.rgba[3] + c2.rgba[3])); } -GCodePreviewData::Color operator * (float f, const GCodePreviewData::Color& color) +Color operator * (float f, const Color& color) { - return GCodePreviewData::Color(clamp(0.0f, 1.0f, f * color.rgba[0]), + return Color(clamp(0.0f, 1.0f, f * color.rgba[0]), clamp(0.0f, 1.0f, f * color.rgba[1]), clamp(0.0f, 1.0f, f * color.rgba[2]), clamp(0.0f, 1.0f, f * color.rgba[3])); diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp index 725c0258d9..a023203f1c 100644 --- a/src/libslic3r/GCode/PreviewData.hpp +++ b/src/libslic3r/GCode/PreviewData.hpp @@ -5,43 +5,188 @@ #include "../ExtrusionEntity.hpp" #include "../Point.hpp" +#include +#include +#include +#include +#include +#include +#include + namespace Slic3r { +// Represents an RGBA color +struct Color +{ + std::array rgba; + + Color(const float *argba) + { + memcpy(this->rgba.data(), argba, sizeof(float) * 4); + } + constexpr Color(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) : rgba{r,g,b,a} + { + // Intentionally empty + } + + std::vector as_bytes() const; +}; +Color operator + (const Color& c1, const Color& c2); +Color operator * (float f, const Color& color); + +// Default colors for Ranges +constexpr std::array range_rainbow_colors{ + Color{0.043f, 0.173f, 0.478f, 1.0f}, + Color{0.075f, 0.349f, 0.522f, 1.0f}, + Color{0.110f, 0.533f, 0.569f, 1.0f}, + Color{0.016f, 0.839f, 0.059f, 1.0f}, + Color{0.667f, 0.949f, 0.000f, 1.0f}, + Color{0.988f, 0.975f, 0.012f, 1.0f}, + Color{0.961f, 0.808f, 0.039f, 1.0f}, + Color{0.890f, 0.533f, 0.125f, 1.0f}, + Color{0.820f, 0.408f, 0.188f, 1.0f}, + Color{0.761f, 0.322f, 0.235f, 1.0f}}; + class GCodePreviewData { public: - struct Color + + // Color mapping to convert a float into a smooth rainbow of 10 colors. + class RangeBase { - float rgba[4]; + public: - Color(const float *argba) { memcpy(this->rgba, argba, sizeof(float) * 4); } - Color(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) { rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; } - - std::vector as_bytes() const; - - static const Color Dummy; + virtual void reset() = 0; + virtual bool empty() const = 0; + virtual float min() const = 0; + virtual float max() const = 0; + + // Gets the step size using min(), max() and colors + float step_size() const; + + // Gets the color at a value using colors, min(), and max() + Color get_color_at(float value) const; }; - - // Color mapping from a range into a smooth rainbow of 10 colors. - struct Range + + // Color mapping converting a float in a range between a min and a max into a smooth rainbow of 10 colors. + class Range : public RangeBase { - static const unsigned int Colors_Count = 10; - static const Color Default_Colors[Colors_Count]; - - Color colors[Colors_Count]; - float min; - float max; - + public: Range(); - void reset(); - bool empty() const; + // RangeBase Overrides + void reset() override; + bool empty() const override; + float min() const override; + float max() const override; + + // Range-specific methods void update_from(float value); - void update_from(const Range& other); - void set_from(const Range& other); - float step_size() const; + void update_from(const RangeBase& other); - Color get_color_at(float value) const; + private: + float min_val; + float max_val; + }; + + // Like Range, but stores multiple ranges internally that are used depending on mode. + // Template param EnumRangeType must be an enum with values for each type of range that needs to be tracked in this MultiRange. + // The last enum value should be num_values. The numerical values of all enum values should range from 0 to num_values. + template + class MultiRange : public RangeBase + { + public: + + void reset() override + { + bounds = decltype(bounds){}; + } + + bool empty() const override + { + for (std::size_t i = 0; i < bounds.size(); ++i) + { + if (bounds[i].min != bounds[i].max) + return false; + } + return true; + } + + float min() const override + { + float min = FLT_MAX; + for (std::size_t i = 0; i < bounds.size(); ++i) + { + // Only use bounds[i] if the current mode includes it + if (mode.test(i)) + { + min = std::min(min, bounds[i].min); + } + } + return min; + } + + float max() const override + { + float max = -FLT_MAX; + for (std::size_t i = 0; i < bounds.size(); ++i) + { + // Only use bounds[i] if the current mode includes it + if (mode.test(i)) + { + max = std::max(max, bounds[i].max); + } + } + return max; + } + + void update_from(const float value, EnumRangeType range_type_value) + { + bounds[static_cast(range_type_value)].update_from(value); + } + + void update_from(const MultiRange& other) + { + for (std::size_t i = 0; i < bounds.size(); ++i) + { + bounds[i].update_from(other.bounds[i]); + } + } + + void set_mode(const EnumRangeType range_type_value, const bool enable) + { + mode.set(static_cast(range_type_value), enable); + } + + private: + + // Interval bounds + struct Bounds + { + float min{FLT_MAX}; + float max{-FLT_MAX}; + void update_from(const float value) + { + min = std::min(min, value); + max = std::max(max, value); + } + void update_from(const Bounds other_bounds) + { + min = std::min(min, other_bounds.min); + max = std::max(max, other_bounds.max); + } + }; + + std::array(EnumRangeType::num_values)> bounds; + std::bitset(EnumRangeType::num_values)> mode; + }; + + // Enum distinguishing different kinds of feedrate data + enum class FeedrateKind + { + EXTRUSION = 0, // values must go from 0 up to num_values + TRAVEL, + num_values //must be last in the list of values }; struct Ranges @@ -51,7 +196,7 @@ public: // Color mapping by extrusion width. Range width; // Color mapping by feedrate. - Range feedrate; + MultiRange feedrate; // Color mapping by fan speed. Range fan_speed; // Color mapping by volumetric extrusion rate. @@ -245,9 +390,6 @@ public: static const std::vector& ColorPrintColors(); }; -GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2); -GCodePreviewData::Color operator * (float f, const GCodePreviewData::Color& color); - } // namespace Slic3r #endif /* slic3r_GCode_PreviewData_hpp_ */ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d2428cf967..2341e05d42 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2427,7 +2427,7 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio volume_index.first_volumes.emplace_back(extrusion_type, 0, (unsigned int)volumes.volumes.size()); - GLVolume *volume = volumes.new_nontoolpath_volume(retractions.color.rgba, VERTEX_BUFFER_RESERVE_SIZE); + GLVolume *volume = volumes.new_nontoolpath_volume(retractions.color.rgba.data(), VERTEX_BUFFER_RESERVE_SIZE); GCodePreviewData::Retraction::PositionsList copy(retractions.positions); std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2) { return p1.position(2) < p2.position(2); }); @@ -5863,7 +5863,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat return 0.0f; } - static GCodePreviewData::Color path_color(const GCodePreviewData& data, const std::vector& tool_colors, float value) + static Color path_color(const GCodePreviewData& data, const std::vector& tool_colors, float value) { switch (data.extrusion.view_type) { @@ -5881,8 +5881,8 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat return data.get_volumetric_rate_color(value); case GCodePreviewData::Extrusion::Tool: { - GCodePreviewData::Color color; - ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float)); + Color color; + ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float)); return color; } case GCodePreviewData::Extrusion::ColorPrint: @@ -5890,16 +5890,16 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat int color_cnt = (int)tool_colors.size() / 4; int val = value > color_cnt ? color_cnt - 1 : value; - GCodePreviewData::Color color; - ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float)); + Color color; + ::memcpy((void*)color.rgba.data(), (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float)); return color; } default: - return GCodePreviewData::Color::Dummy; + return Color{}; } - return GCodePreviewData::Color::Dummy; + return Color{}; } }; @@ -5942,7 +5942,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat if (! values.empty()) { m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, role, (unsigned int)m_volumes.volumes.size()); for (const float value : values) - roles_filters.back().emplace_back(value, m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value).rgba, vertex_buffer_prealloc_size)); + roles_filters.back().emplace_back(value, m_volumes.new_toolpath_volume(Helper::path_color(preview_data, tool_colors, value).rgba.data(), vertex_buffer_prealloc_size)); } } } @@ -6025,7 +6025,7 @@ inline void travel_paths_internal( by_type.reserve(values.size()); // creates a new volume for each feedrate for (TYPE type : values) - by_type.emplace_back(type, volumes.new_nontoolpath_volume(func_color(type).rgba, VERTEX_BUFFER_RESERVE_SIZE)); + by_type.emplace_back(type, volumes.new_nontoolpath_volume(func_color(type).rgba.data(), VERTEX_BUFFER_RESERVE_SIZE)); } // populates volumes @@ -6072,19 +6072,19 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, case GCodePreviewData::Extrusion::Feedrate: travel_paths_internal(preview_data, [](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.feedrate; }, - [&preview_data](const float feedrate) -> const GCodePreviewData::Color { return preview_data.get_feedrate_color(feedrate); }, + [&preview_data](const float feedrate) -> const Color { return preview_data.get_feedrate_color(feedrate); }, m_volumes, m_initialized); break; case GCodePreviewData::Extrusion::Tool: travel_paths_internal(preview_data, [](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.extruder_id; }, - [&tool_colors](const unsigned int extruder_id) -> const GCodePreviewData::Color { assert((extruder_id + 1) * 4 <= tool_colors.size()); return GCodePreviewData::Color(tool_colors.data() + extruder_id * 4); }, + [&tool_colors](const unsigned int extruder_id) -> const Color { assert((extruder_id + 1) * 4 <= tool_colors.size()); return Color(tool_colors.data() + extruder_id * 4); }, m_volumes, m_initialized); break; default: travel_paths_internal(preview_data, [](const GCodePreviewData::Travel::Polyline &polyline) { return polyline.type; }, - [&preview_data](const unsigned int type) -> const GCodePreviewData::Color& { return preview_data.travel.type_colors[type]; }, + [&preview_data](const unsigned int type) -> const Color& { return preview_data.travel.type_colors[type]; }, m_volumes, m_initialized); break; } diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 1a4d12d316..6900a1f567 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -533,7 +533,9 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt) void Preview::on_checkbox_travel(wxCommandEvent& evt) { m_gcode_preview_data->travel.is_visible = m_checkbox_travel->IsChecked(); - refresh_print(); + m_gcode_preview_data->ranges.feedrate.set_mode(GCodePreviewData::FeedrateKind::TRAVEL, m_gcode_preview_data->travel.is_visible); + // Rather than refresh, reload print so that speed color ranges get recomputed (affected by travel visibility) + reload_print(); } void Preview::on_checkbox_retractions(wxCommandEvent& evt)