mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-24 17:21:11 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_6dof_camera
This commit is contained in:
commit
34aac7e292
17 changed files with 723 additions and 391 deletions
|
|
@ -1088,7 +1088,7 @@ namespace Slic3r {
|
|||
return;
|
||||
pt::ptree code_tree = main_tree.front().second;
|
||||
|
||||
m_model->custom_gcode_per_print_z.clear();
|
||||
m_model->custom_gcode_per_print_z.gcodes.clear();
|
||||
|
||||
for (const auto& code : code_tree)
|
||||
{
|
||||
|
|
@ -1100,7 +1100,7 @@ namespace Slic3r {
|
|||
int extruder = tree.get<int> ("<xmlattr>.extruder" );
|
||||
std::string color = tree.get<std::string> ("<xmlattr>.color" );
|
||||
|
||||
m_model->custom_gcode_per_print_z.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ;
|
||||
m_model->custom_gcode_per_print_z.gcodes.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2631,12 +2631,12 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv
|
|||
{
|
||||
std::string out = "";
|
||||
|
||||
if (!model.custom_gcode_per_print_z.empty())
|
||||
if (!model.custom_gcode_per_print_z.gcodes.empty())
|
||||
{
|
||||
pt::ptree tree;
|
||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", "");
|
||||
|
||||
for (const Model::CustomGCode& code : model.custom_gcode_per_print_z)
|
||||
for (const Model::CustomGCode& code : model.custom_gcode_per_print_z.gcodes)
|
||||
{
|
||||
pt::ptree& code_tree = main_tree.add("code", "");
|
||||
// store minX and maxZ
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
|||
int extruder = atoi(m_value[2].c_str());
|
||||
const std::string& color = m_value[3];
|
||||
|
||||
m_model.custom_gcode_per_print_z.push_back(Model::CustomGCode{height, gcode, extruder, color});
|
||||
m_model.custom_gcode_per_print_z.gcodes.push_back(Model::CustomGCode{height, gcode, extruder, color});
|
||||
|
||||
for (std::string& val: m_value)
|
||||
val.clear();
|
||||
|
|
@ -1250,14 +1250,14 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||
stream << " </constellation>\n";
|
||||
}
|
||||
|
||||
if (!model->custom_gcode_per_print_z.empty())
|
||||
if (!model->custom_gcode_per_print_z.gcodes.empty())
|
||||
{
|
||||
std::string out = "";
|
||||
pt::ptree tree;
|
||||
|
||||
pt::ptree& main_tree = tree.add("custom_gcodes_per_height", "");
|
||||
|
||||
for (const Model::CustomGCode& code : model->custom_gcode_per_print_z)
|
||||
for (const Model::CustomGCode& code : model->custom_gcode_per_print_z.gcodes)
|
||||
{
|
||||
pt::ptree& code_tree = main_tree.add("code", "");
|
||||
// store minX and maxZ
|
||||
|
|
|
|||
|
|
@ -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<GCodePreviewData::FeedrateKind> 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<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);
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "Analyzer.hpp"
|
||||
#include "PreviewData.hpp"
|
||||
#include <float.h>
|
||||
#include <I18N.hpp>
|
||||
#include "Utils.hpp"
|
||||
|
||||
|
|
@ -11,9 +10,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 +35,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 +42,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 = std::clamp(static_cast<std::size_t>(global_t), std::size_t{ 0 }, color_max_idx);
|
||||
const std::size_t color_high_idx = std::clamp(color_low_idx + 1, std::size_t{ 0 }, color_max_idx);
|
||||
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 +96,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 +171,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 +197,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 +229,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 +257,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);
|
||||
}
|
||||
|
|
@ -384,16 +373,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 +435,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 +449,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 +461,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);
|
||||
}
|
||||
|
|
@ -502,20 +491,20 @@ const std::vector<std::string>& GCodePreviewData::ColorPrintColors()
|
|||
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]),
|
||||
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]));
|
||||
return Color(std::clamp(c1.rgba[0] + c2.rgba[0], 0.0f, 1.0f),
|
||||
std::clamp(c1.rgba[1] + c2.rgba[1], 0.0f, 1.0f),
|
||||
std::clamp(c1.rgba[2] + c2.rgba[2], 0.0f, 1.0f),
|
||||
std::clamp(c1.rgba[3] + c2.rgba[3], 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
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]),
|
||||
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]));
|
||||
return Color(std::clamp(f * color.rgba[0], 0.0f, 1.0f),
|
||||
std::clamp(f * color.rgba[1], 0.0f, 1.0f),
|
||||
std::clamp(f * color.rgba[2], 0.0f, 1.0f),
|
||||
std::clamp(f * color.rgba[3], 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -5,43 +5,190 @@
|
|||
#include "../ExtrusionEntity.hpp"
|
||||
#include "../Point.hpp"
|
||||
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
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 +198,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 +392,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_ */
|
||||
|
|
|
|||
|
|
@ -129,8 +129,12 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
|||
// Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object.
|
||||
// Do it only if all the objects were configured to be printed with a single extruder.
|
||||
std::vector<std::pair<double, unsigned int>> per_layer_extruder_switches;
|
||||
if (print.object_extruders().size() == 1)
|
||||
per_layer_extruder_switches = custom_tool_changes(print.model(), (unsigned int)print.config().nozzle_diameter.size());
|
||||
if (auto num_extruders = unsigned(print.config().nozzle_diameter.size());
|
||||
num_extruders > 1 && print.object_extruders().size() == 1) {
|
||||
// Printing a single extruder platter on a printer with more than 1 extruder (or single-extruder multi-material).
|
||||
// There may be custom per-layer tool changes available at the model.
|
||||
per_layer_extruder_switches = custom_tool_changes(print.model(), num_extruders);
|
||||
}
|
||||
|
||||
// Collect extruders reuqired to print the layers.
|
||||
for (auto object : print.objects())
|
||||
|
|
@ -142,11 +146,6 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
|||
this->fill_wipe_tower_partitions(print.config(), object_bottom_z);
|
||||
|
||||
this->collect_extruder_statistics(prime_multi_material);
|
||||
|
||||
// Assign custom G-code actions from Model::custom_gcode_per_print_z to their respecive layers,
|
||||
// ignoring the extruder switches, which were processed above, and ignoring color changes for extruders,
|
||||
// that do not print above their respective print_z.
|
||||
this->assign_custom_gcodes(print);
|
||||
}
|
||||
|
||||
void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
||||
|
|
@ -463,13 +462,15 @@ void ToolOrdering::assign_custom_gcodes(const Print &print)
|
|||
// Only valid for non-sequential print.
|
||||
assert(! print.config().complete_objects.value);
|
||||
|
||||
const std::vector<Model::CustomGCode> &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
|
||||
if (custom_gcode_per_print_z.empty())
|
||||
const Model::CustomGCodeInfo &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
|
||||
if (custom_gcode_per_print_z.gcodes.empty())
|
||||
return;
|
||||
|
||||
unsigned int num_extruders = *std::max_element(m_all_printing_extruders.begin(), m_all_printing_extruders.end()) + 1;
|
||||
std::vector<unsigned char> extruder_printing_above(num_extruders, false);
|
||||
auto custom_gcode_it = custom_gcode_per_print_z.rbegin();
|
||||
auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin();
|
||||
// If printing on a single extruder machine, make the tool changes trigger color change (M600) events.
|
||||
bool tool_changes_as_color_changes = num_extruders == 1;
|
||||
// From the last layer to the first one:
|
||||
for (auto it_lt = m_layer_tools.rbegin(); it_lt != m_layer_tools.rend(); ++ it_lt) {
|
||||
LayerTools < = *it_lt;
|
||||
|
|
@ -477,8 +478,8 @@ void ToolOrdering::assign_custom_gcodes(const Print &print)
|
|||
for (unsigned int i : lt.extruders)
|
||||
extruder_printing_above[i] = true;
|
||||
// Skip all custom G-codes above this layer and skip all extruder switches.
|
||||
for (; custom_gcode_it != custom_gcode_per_print_z.rend() && (custom_gcode_it->print_z > lt.print_z + EPSILON || custom_gcode_it->gcode == ExtruderChangeCode); ++ custom_gcode_it);
|
||||
if (custom_gcode_it == custom_gcode_per_print_z.rend())
|
||||
for (; custom_gcode_it != custom_gcode_per_print_z.gcodes.rend() && (custom_gcode_it->print_z > lt.print_z + EPSILON || custom_gcode_it->gcode == ExtruderChangeCode); ++ custom_gcode_it);
|
||||
if (custom_gcode_it == custom_gcode_per_print_z.gcodes.rend())
|
||||
// Custom G-codes were processed.
|
||||
break;
|
||||
// Some custom G-code is configured for this layer or a layer below.
|
||||
|
|
@ -489,7 +490,8 @@ void ToolOrdering::assign_custom_gcodes(const Print &print)
|
|||
print_z_below = it_lt_below->print_z;
|
||||
if (custom_gcode.print_z > print_z_below + 0.5 * EPSILON) {
|
||||
// The custom G-code applies to the current layer.
|
||||
if (custom_gcode.gcode != ColorChangeCode || extruder_printing_above[unsigned(custom_gcode.extruder - 1)])
|
||||
if ( tool_changes_as_color_changes || custom_gcode.gcode != ColorChangeCode ||
|
||||
(custom_gcode.extruder <= num_extruders && extruder_printing_above[unsigned(custom_gcode.extruder - 1)]))
|
||||
// If it is color change, it will actually be useful as the exturder above will print.
|
||||
lt.custom_gcode = &custom_gcode;
|
||||
// Consume that custom G-code event.
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||
if (add_default_instances)
|
||||
model.add_default_instances();
|
||||
|
||||
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
||||
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z.gcodes, config);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
|
|||
if (add_default_instances)
|
||||
model.add_default_instances();
|
||||
|
||||
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
|
||||
update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z.gcodes, config);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
|
@ -1846,7 +1846,7 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
|||
std::vector<std::pair<double, unsigned int>> custom_tool_changes(const Model &model, size_t num_extruders)
|
||||
{
|
||||
std::vector<std::pair<double, unsigned int>> custom_tool_changes;
|
||||
for (const Model::CustomGCode &custom_gcode : model.custom_gcode_per_print_z)
|
||||
for (const Model::CustomGCode &custom_gcode : model.custom_gcode_per_print_z.gcodes)
|
||||
if (custom_gcode.gcode == ExtruderChangeCode) {
|
||||
// If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders
|
||||
custom_tool_changes.emplace_back(custom_gcode.print_z, static_cast<unsigned int>(custom_gcode.extruder > num_extruders ? 1 : custom_gcode.extruder));
|
||||
|
|
|
|||
|
|
@ -772,7 +772,28 @@ public:
|
|||
std::string color; // if gcode is equal to PausePrintCode,
|
||||
// this field is used for save a short message shown on Printer display
|
||||
};
|
||||
std::vector<CustomGCode> custom_gcode_per_print_z;
|
||||
|
||||
struct CustomGCodeInfo
|
||||
{
|
||||
enum MODE
|
||||
{
|
||||
SingleExtruder, // single extruder printer preset is selected
|
||||
MultiAsSingle, // multiple extruder printer preset is selected, but
|
||||
// this mode works just for Single extruder print
|
||||
// (For all print from objects settings is used just one extruder)
|
||||
MultiExtruder // multiple extruder printer preset is selected
|
||||
} mode;
|
||||
|
||||
std::vector<CustomGCode> gcodes;
|
||||
|
||||
bool operator==(const CustomGCodeInfo& rhs) const
|
||||
{
|
||||
return (rhs.mode == this->mode ) &&
|
||||
(rhs.gcodes == this->gcodes );
|
||||
}
|
||||
bool operator!=(const CustomGCodeInfo& rhs) const { return !(*this == rhs); }
|
||||
}
|
||||
custom_gcode_per_print_z;
|
||||
|
||||
// Default constructor assigns a new ID to the model.
|
||||
Model() { assert(this->id().valid()); }
|
||||
|
|
|
|||
|
|
@ -723,7 +723,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
model_object_status.emplace(model_object->id(), ModelObjectStatus::New);
|
||||
} else {
|
||||
if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) {
|
||||
update_apply_status(custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z, model.custom_gcode_per_print_z) ?
|
||||
update_apply_status(custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes) ?
|
||||
// The Tool Ordering and the Wipe Tower are no more valid.
|
||||
this->invalidate_steps({ psWipeTower, psGCodeExport }) :
|
||||
// There is no change in Tool Changes stored in custom_gcode_per_print_z, therefore there is no need to update Tool Ordering.
|
||||
|
|
|
|||
|
|
@ -242,11 +242,10 @@ private:
|
|||
|
||||
struct WipeTowerData
|
||||
{
|
||||
WipeTowerData(ToolOrdering &tool_ordering) : tool_ordering(tool_ordering) { clear(); }
|
||||
// Following section will be consumed by the GCodeGenerator.
|
||||
// Tool ordering of a non-sequential print has to be known to calculate the wipe tower.
|
||||
// Cache it here, so it does not need to be recalculated during the G-code generation.
|
||||
ToolOrdering tool_ordering;
|
||||
ToolOrdering &tool_ordering;
|
||||
// Cache of tool changes per print layer.
|
||||
std::unique_ptr<std::vector<WipeTower::ToolChangeResult>> priming;
|
||||
std::vector<std::vector<WipeTower::ToolChangeResult>> tool_changes;
|
||||
|
|
@ -267,6 +266,14 @@ struct WipeTowerData
|
|||
depth = 0.f;
|
||||
brim_width = 0.f;
|
||||
}
|
||||
|
||||
private:
|
||||
// Only allow the WipeTowerData to be instantiated internally by Print,
|
||||
// as this WipeTowerData shares reference to Print::m_tool_ordering.
|
||||
friend class Print;
|
||||
WipeTowerData(ToolOrdering &tool_ordering) : tool_ordering(tool_ordering) { clear(); }
|
||||
WipeTowerData(const WipeTowerData & /* rhs */) = delete;
|
||||
WipeTowerData &operator=(const WipeTowerData & /* rhs */) = delete;
|
||||
};
|
||||
|
||||
struct PrintStatistics
|
||||
|
|
@ -394,6 +401,7 @@ public:
|
|||
|
||||
// Accessed by SupportMaterial
|
||||
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
||||
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; } // #ys_FIXME just for testing
|
||||
|
||||
protected:
|
||||
// methods for handling regions
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue