mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Speed legend scales depending on travel visibility.
This commit is contained in:
		
							parent
							
								
									24bbad634a
								
							
						
					
					
						commit
						dea83da5b7
					
				
					 5 changed files with 254 additions and 120 deletions
				
			
		|  | @ -993,7 +993,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<GCodePreviewData::FeedrateKind> feedrate_range; | ||||
|     GCodePreviewData::Range volumetric_rate_range; | ||||
|     GCodePreviewData::Range fan_speed_range; | ||||
| 
 | ||||
|  | @ -1028,7 +1028,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); | ||||
|         } | ||||
|  | @ -1081,7 +1081,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<GCodePreviewData::FeedrateKind> 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); | ||||
|  | @ -1121,7 +1121,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
 | ||||
|  |  | |||
|  | @ -11,9 +11,7 @@ | |||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| const GCodePreviewData::Color GCodePreviewData::Color::Dummy(0.0f, 0.0f, 0.0f, 0.0f); | ||||
| 
 | ||||
| std::vector<unsigned char> GCodePreviewData::Color::as_bytes() const | ||||
| std::vector<unsigned char> Color::as_bytes() const | ||||
| { | ||||
|     std::vector<unsigned char> 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<float>(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<std::size_t>(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<float>(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<std::string>& 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<int>(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<std::string>& GCodePreviewData::ColorPrintColors() | ||||
| const std::vector<std::string>& ColorPrintColors() | ||||
| { | ||||
|     static std::vector<std::string> 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])); | ||||
|  |  | |||
|  | @ -5,43 +5,188 @@ | |||
| #include "../ExtrusionEntity.hpp" | ||||
| #include "../Point.hpp" | ||||
| 
 | ||||
| #include <tuple> | ||||
| #include <array> | ||||
| #include <vector> | ||||
| #include <bitset> | ||||
| #include <cstddef> | ||||
| #include <algorithm> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| // Represents an RGBA color
 | ||||
| struct Color | ||||
| { | ||||
|     std::array<float,4> 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<unsigned char> 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<Color, 10> 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<unsigned char> 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 <min, max> 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 <typename EnumRangeType> | ||||
|     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<std::size_t>(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<std::size_t>(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<Bounds, static_cast<std::size_t>(EnumRangeType::num_values)> bounds; | ||||
|         std::bitset<static_cast<std::size_t>(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<FeedrateKind> feedrate; | ||||
|         // Color mapping by fan speed.
 | ||||
|         Range fan_speed; | ||||
|         // Color mapping by volumetric extrusion rate.
 | ||||
|  | @ -245,9 +390,6 @@ public: | |||
|     static const std::vector<std::string>& 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_ */ | ||||
|  |  | |||
|  | @ -2417,7 +2417,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); }); | ||||
|  | @ -5841,7 +5841,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<float>& tool_colors, float value) | ||||
|         static Color path_color(const GCodePreviewData& data, const std::vector<float>& tool_colors, float value) | ||||
|         { | ||||
|             switch (data.extrusion.view_type) | ||||
|             { | ||||
|  | @ -5859,8 +5859,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: | ||||
|  | @ -5868,16 +5868,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{}; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|  | @ -5920,7 +5920,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)); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -6003,7 +6003,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
 | ||||
|  | @ -6050,19 +6050,19 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, | |||
| 	    case GCodePreviewData::Extrusion::Feedrate: | ||||
| 			travel_paths_internal<float>(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<unsigned int>(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<unsigned int>(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; | ||||
| 	    } | ||||
|  |  | |||
|  | @ -538,7 +538,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) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 foxox
						foxox