Vectorization of customgcode

This commit is contained in:
Lukas Matena 2024-10-16 10:51:04 +02:00
parent 90136d3ad3
commit da13a0a80e
10 changed files with 144 additions and 94 deletions

View File

@ -1607,46 +1607,61 @@ namespace Slic3r {
if (main_tree.front().first != "custom_gcodes_per_print_z")
return;
pt::ptree code_tree = main_tree.front().second;
m_model->custom_gcode_per_print_z.gcodes.clear();
for (CustomGCode::Info& info : m_model->get_custom_gcode_per_print_z_vector())
info.gcodes.clear();
for (const auto& code : code_tree) {
if (code.first == "mode") {
pt::ptree tree = code.second;
std::string mode = tree.get<std::string>("<xmlattr>.value");
m_model->custom_gcode_per_print_z.mode = mode == CustomGCode::SingleExtruderMode ? CustomGCode::Mode::SingleExtruder :
mode == CustomGCode::MultiAsSingleMode ? CustomGCode::Mode::MultiAsSingle :
CustomGCode::Mode::MultiExtruder;
for (const auto& bed_block : main_tree) {
if (bed_block.first != "custom_gcodes_per_print_z")
continue;
int bed_idx = 0;
try {
bed_block.second.get<int>("<xmlattr>.bed_idx");
} catch (const boost::property_tree::ptree_bad_path&) {
// Probably an old project with no bed_idx info. Imagine that we saw 0.
}
if (code.first != "code")
if (bed_idx >= int(m_model->get_custom_gcode_per_print_z_vector().size()))
continue;
pt::ptree tree = code.second;
double print_z = tree.get<double> ("<xmlattr>.print_z" );
int extruder = tree.get<int> ("<xmlattr>.extruder");
std::string color = tree.get<std::string> ("<xmlattr>.color" );
pt::ptree code_tree = bed_block.second;
CustomGCode::Type type;
std::string extra;
pt::ptree attr_tree = tree.find("<xmlattr>")->second;
if (attr_tree.find("type") == attr_tree.not_found()) {
// It means that data was saved in old version (2.2.0 and older) of PrusaSlicer
// read old data ...
std::string gcode = tree.get<std::string> ("<xmlattr>.gcode");
// ... and interpret them to the new data
type = gcode == "M600" ? CustomGCode::ColorChange :
gcode == "M601" ? CustomGCode::PausePrint :
gcode == "tool_change" ? CustomGCode::ToolChange : CustomGCode::Custom;
extra = type == CustomGCode::PausePrint ? color :
type == CustomGCode::Custom ? gcode : "";
for (const auto& code : code_tree) {
if (code.first == "mode") {
pt::ptree tree = code.second;
std::string mode = tree.get<std::string>("<xmlattr>.value");
m_model->get_custom_gcode_per_print_z_vector()[bed_idx].mode = mode == CustomGCode::SingleExtruderMode ? CustomGCode::Mode::SingleExtruder :
mode == CustomGCode::MultiAsSingleMode ? CustomGCode::Mode::MultiAsSingle :
CustomGCode::Mode::MultiExtruder;
}
if (code.first != "code")
continue;
pt::ptree tree = code.second;
double print_z = tree.get<double> ("<xmlattr>.print_z" );
int extruder = tree.get<int> ("<xmlattr>.extruder");
std::string color = tree.get<std::string> ("<xmlattr>.color" );
CustomGCode::Type type;
std::string extra;
pt::ptree attr_tree = tree.find("<xmlattr>")->second;
if (attr_tree.find("type") == attr_tree.not_found()) {
// It means that data was saved in old version (2.2.0 and older) of PrusaSlicer
// read old data ...
std::string gcode = tree.get<std::string> ("<xmlattr>.gcode");
// ... and interpret them to the new data
type = gcode == "M600" ? CustomGCode::ColorChange :
gcode == "M601" ? CustomGCode::PausePrint :
gcode == "tool_change" ? CustomGCode::ToolChange : CustomGCode::Custom;
extra = type == CustomGCode::PausePrint ? color :
type == CustomGCode::Custom ? gcode : "";
}
else {
type = static_cast<CustomGCode::Type>(tree.get<int>("<xmlattr>.type"));
extra = tree.get<std::string>("<xmlattr>.extra");
}
m_model->get_custom_gcode_per_print_z_vector()[bed_idx].gcodes.push_back(CustomGCode::Item{print_z, type, extruder, color, extra});
}
else {
type = static_cast<CustomGCode::Type>(tree.get<int>("<xmlattr>.type"));
extra = tree.get<std::string>("<xmlattr>.extra");
}
m_model->custom_gcode_per_print_z.gcodes.push_back(CustomGCode::Item{print_z, type, extruder, color, extra}) ;
}
}
}
}
@ -3765,34 +3780,43 @@ 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.gcodes.empty()) {
if (std::any_of(model.get_custom_gcode_per_print_z_vector().begin(), model.get_custom_gcode_per_print_z_vector().end(), [](const auto& cg) { return !cg.gcodes.empty(); })) {
pt::ptree tree;
pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", "");
for (size_t bed_idx=0; bed_idx<model.get_custom_gcode_per_print_z_vector().size(); ++bed_idx) {
if (bed_idx != 0 && model.get_custom_gcode_per_print_z_vector()[bed_idx].gcodes.empty()) {
// Always save the first bed so older slicers are able to tell
// that there are no color changes on it.
continue;
}
for (const CustomGCode::Item& code : model.custom_gcode_per_print_z.gcodes) {
pt::ptree& code_tree = main_tree.add("code", "");
pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", "");
main_tree.put("<xmlattr>.bed_idx" , bed_idx);
// store data of custom_gcode_per_print_z
code_tree.put("<xmlattr>.print_z" , code.print_z );
code_tree.put("<xmlattr>.type" , static_cast<int>(code.type));
code_tree.put("<xmlattr>.extruder" , code.extruder );
code_tree.put("<xmlattr>.color" , code.color );
code_tree.put("<xmlattr>.extra" , code.extra );
for (const CustomGCode::Item& code : model.get_custom_gcode_per_print_z_vector()[bed_idx].gcodes) {
pt::ptree& code_tree = main_tree.add("code", "");
// add gcode field data for the old version of the PrusaSlicer
std::string gcode = code.type == CustomGCode::ColorChange ? config->opt_string("color_change_gcode") :
code.type == CustomGCode::PausePrint ? config->opt_string("pause_print_gcode") :
code.type == CustomGCode::Template ? config->opt_string("template_custom_gcode") :
code.type == CustomGCode::ToolChange ? "tool_change" : code.extra;
code_tree.put("<xmlattr>.gcode" , gcode );
// store data of custom_gcode_per_print_z
code_tree.put("<xmlattr>.print_z" , code.print_z );
code_tree.put("<xmlattr>.type" , static_cast<int>(code.type));
code_tree.put("<xmlattr>.extruder" , code.extruder );
code_tree.put("<xmlattr>.color" , code.color );
code_tree.put("<xmlattr>.extra" , code.extra );
// add gcode field data for the old version of the PrusaSlicer
std::string gcode = code.type == CustomGCode::ColorChange ? config->opt_string("color_change_gcode") :
code.type == CustomGCode::PausePrint ? config->opt_string("pause_print_gcode") :
code.type == CustomGCode::Template ? config->opt_string("template_custom_gcode") :
code.type == CustomGCode::ToolChange ? "tool_change" : code.extra;
code_tree.put("<xmlattr>.gcode" , gcode );
}
pt::ptree& mode_tree = main_tree.add("mode", "");
// store mode of a custom_gcode_per_print_z
mode_tree.put("<xmlattr>.value", model.custom_gcode_per_print_z().mode == CustomGCode::Mode::SingleExtruder ? CustomGCode::SingleExtruderMode :
model.custom_gcode_per_print_z().mode == CustomGCode::Mode::MultiAsSingle ? CustomGCode::MultiAsSingleMode :
CustomGCode::MultiExtruderMode);
}
pt::ptree& mode_tree = main_tree.add("mode", "");
// store mode of a custom_gcode_per_print_z
mode_tree.put("<xmlattr>.value", model.custom_gcode_per_print_z.mode == CustomGCode::Mode::SingleExtruder ? CustomGCode::SingleExtruderMode :
model.custom_gcode_per_print_z.mode == CustomGCode::Mode::MultiAsSingle ? CustomGCode::MultiAsSingleMode :
CustomGCode::MultiExtruderMode);
if (!tree.empty()) {
std::ostringstream oss;
boost::property_tree::write_xml(oss, tree);

View File

@ -700,7 +700,7 @@ void AMFParserContext::endElement(const char * /* name */)
CustomGCode::Type type = static_cast<CustomGCode::Type>(atoi(m_value[3].c_str()));
const std::string& extra= m_value[4];
m_model.custom_gcode_per_print_z.gcodes.push_back(CustomGCode::Item{print_z, type, extruder, color, extra});
m_model.custom_gcode_per_print_z().gcodes.push_back(CustomGCode::Item{print_z, type, extruder, color, extra});
for (std::string& val: m_value)
val.clear();
@ -710,9 +710,9 @@ void AMFParserContext::endElement(const char * /* name */)
case NODE_TYPE_CUSTOM_GCODE_MODE: {
const std::string& mode = m_value[0];
m_model.custom_gcode_per_print_z.mode = mode == CustomGCode::SingleExtruderMode ? CustomGCode::Mode::SingleExtruder :
mode == CustomGCode::MultiAsSingleMode ? CustomGCode::Mode::MultiAsSingle :
CustomGCode::Mode::MultiExtruder;
m_model.custom_gcode_per_print_z().mode = mode == CustomGCode::SingleExtruderMode ? CustomGCode::Mode::SingleExtruder :
mode == CustomGCode::MultiAsSingleMode ? CustomGCode::Mode::MultiAsSingle :
CustomGCode::Mode::MultiExtruder;
for (std::string& val: m_value)
val.clear();
break;

View File

@ -546,7 +546,7 @@ namespace DoExport {
}
}
if (ret.size() < MAX_TAGS_COUNT) {
const CustomGCode::Info& custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
const CustomGCode::Info& custom_gcode_per_print_z = print.model().custom_gcode_per_print_z();
for (const auto& gcode : custom_gcode_per_print_z.gcodes) {
check(_u8L("Custom G-code"), gcode.extra);
if (ret.size() == MAX_TAGS_COUNT)

View File

@ -165,17 +165,17 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
std::vector<std::pair<double, unsigned int>> per_layer_extruder_switches;
auto num_extruders = unsigned(print.config().nozzle_diameter.size());
if (num_extruders > 1 && print.object_extruders().size() == 1 && // the current Print's configuration is CustomGCode::MultiAsSingle
print.model().custom_gcode_per_print_z.mode == CustomGCode::MultiAsSingle) {
print.model().custom_gcode_per_print_z().mode == CustomGCode::MultiAsSingle) {
// 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().custom_gcode_per_print_z, num_extruders);
per_layer_extruder_switches = custom_tool_changes(print.model().custom_gcode_per_print_z(), num_extruders);
}
// Color changes for each layer to determine which extruder needs to be picked before color change.
// This is done just for multi-extruder printers without enabled Single Extruder Multi Material (tool changer printers).
std::vector<std::pair<double, unsigned int>> per_layer_color_changes;
if (num_extruders > 1 && print.model().custom_gcode_per_print_z.mode == CustomGCode::MultiExtruder && !print.config().single_extruder_multi_material) {
per_layer_color_changes = custom_color_changes(print.model().custom_gcode_per_print_z, num_extruders);
if (num_extruders > 1 && print.model().custom_gcode_per_print_z().mode == CustomGCode::MultiExtruder && !print.config().single_extruder_multi_material) {
per_layer_color_changes = custom_color_changes(print.model().custom_gcode_per_print_z(), num_extruders);
}
// Collect extruders required to print the layers.
@ -612,7 +612,7 @@ void ToolOrdering::assign_custom_gcodes(const Print &print)
// Only valid for non-sequential print.
assert(! print.config().complete_objects.value);
const CustomGCode::Info &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
const CustomGCode::Info &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z();
if (custom_gcode_per_print_z.gcodes.empty())
return;
@ -620,7 +620,7 @@ void ToolOrdering::assign_custom_gcodes(const Print &print)
CustomGCode::Mode mode =
(num_extruders == 1) ? CustomGCode::SingleExtruder :
print.object_extruders().size() == 1 ? CustomGCode::MultiAsSingle : CustomGCode::MultiExtruder;
CustomGCode::Mode model_mode = print.model().custom_gcode_per_print_z.mode;
CustomGCode::Mode model_mode = print.model().custom_gcode_per_print_z().mode;
std::vector<unsigned char> extruder_printing_above(num_extruders, false);
auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin();
// Tool changes and color changes will be ignored, if the model's tool/color changes were entered in mm mode and the print is in non mm mode

View File

@ -69,8 +69,9 @@ Model& Model::assign_copy(const Model &rhs)
}
// copy custom code per height
this->custom_gcode_per_print_z = rhs.custom_gcode_per_print_z;
this->custom_gcode_per_print_z_vector = rhs.custom_gcode_per_print_z_vector;
this->wipe_tower = rhs.wipe_tower;
return *this;
}
@ -91,8 +92,9 @@ Model& Model::assign_copy(Model &&rhs)
rhs.objects.clear();
// copy custom code per height
this->custom_gcode_per_print_z = std::move(rhs.custom_gcode_per_print_z);
this->custom_gcode_per_print_z_vector = std::move(rhs.custom_gcode_per_print_z_vector);
this->wipe_tower = rhs.wipe_tower;
return *this;
}
@ -118,6 +120,17 @@ void Model::update_links_bottom_up_recursive()
}
}
CustomGCode::Info& Model::custom_gcode_per_print_z()
{
return const_cast<CustomGCode::Info&>(const_cast<const Model*>(this)->custom_gcode_per_print_z());
}
const CustomGCode::Info& Model::custom_gcode_per_print_z() const
{
return custom_gcode_per_print_z_vector[s_multiple_beds.get_active_bed()];
}
// Loading model from a file, it may be a simple geometry file as STL or OBJ, however it may be a project file as well.
Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, LoadAttributes options)
{
@ -154,16 +167,18 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
if (model.objects.empty())
throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty");
if (!boost::ends_with(input_file, ".printRequest"))
for (ModelObject *o : model.objects)
o->input_file = input_file;
if (options & LoadAttribute::AddDefaultInstances)
model.add_default_instances();
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
for (CustomGCode::Info& info : model.custom_gcode_per_print_z_vector) {
CustomGCode::update_custom_gcode_per_print_z_from_config(info, config);
CustomGCode::check_mode_for_custom_gcode_per_print_z(info);
}
sort_remove_duplicates(config_substitutions->substitutions);
return model;
@ -201,8 +216,10 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
if (options & LoadAttribute::AddDefaultInstances)
model.add_default_instances();
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config);
CustomGCode::check_mode_for_custom_gcode_per_print_z(model.custom_gcode_per_print_z);
for (CustomGCode::Info& info : model.custom_gcode_per_print_z_vector) {
CustomGCode::update_custom_gcode_per_print_z_from_config(info, config);
CustomGCode::check_mode_for_custom_gcode_per_print_z(info);
}
handle_legacy_sla(*config);

View File

@ -1304,9 +1304,15 @@ public:
// Wipe tower object.
ModelWipeTower wipe_tower;
CustomGCode::Info& custom_gcode_per_print_z();
const CustomGCode::Info& custom_gcode_per_print_z() const;
std::vector<CustomGCode::Info>& get_custom_gcode_per_print_z_vector() { return custom_gcode_per_print_z_vector; }
private:
// Extensions for color print
CustomGCode::Info custom_gcode_per_print_z;
std::vector<CustomGCode::Info> custom_gcode_per_print_z_vector = std::vector<CustomGCode::Info>(MAX_NUMBER_OF_BEDS);
public:
// Default constructor assigns a new ID to the model.
Model() { assert(this->id().valid()); }
~Model() { this->clear_objects(); this->clear_materials(); }

View File

@ -1147,18 +1147,18 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
for (const ModelObject *model_object : m_model.objects)
model_object_status_db.add(*model_object, ModelObjectStatus::New);
} else {
if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) {
const CustomGCode::Mode current_mode = m_model.custom_gcode_per_print_z.mode;
const CustomGCode::Mode next_mode = model.custom_gcode_per_print_z.mode;
if (m_model.custom_gcode_per_print_z() != model.custom_gcode_per_print_z()) {
const CustomGCode::Mode current_mode = m_model.custom_gcode_per_print_z().mode;
const CustomGCode::Mode next_mode = model.custom_gcode_per_print_z().mode;
const bool multi_extruder_differ = (current_mode == next_mode) && (current_mode == CustomGCode::MultiExtruder || next_mode == CustomGCode::MultiExtruder);
// Tool change G-codes are applied as color changes for a single extruder printer, no need to invalidate tool ordering.
// FIXME The tool ordering may be invalidated unnecessarily if the custom_gcode_per_print_z.mode is not applicable
// to the active print / model state, and then it is reset, so it is being applicable, but empty, thus the effect is the same.
const bool tool_change_differ = num_extruders > 1 && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes, CustomGCode::ToolChange);
const bool tool_change_differ = num_extruders > 1 && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z().gcodes, model.custom_gcode_per_print_z().gcodes, CustomGCode::ToolChange);
// For multi-extruder printers, we perform a tool change before a color change.
// So, in that case, we must invalidate tool ordering and wipe tower even if custom color change g-codes differ.
const bool color_change_differ = num_extruders > 1 && (next_mode == CustomGCode::MultiExtruder) && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes, CustomGCode::ColorChange);
const bool color_change_differ = num_extruders > 1 && (next_mode == CustomGCode::MultiExtruder) && custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z().gcodes, model.custom_gcode_per_print_z().gcodes, CustomGCode::ColorChange);
update_apply_status(
(num_extruders_changed || tool_change_differ || multi_extruder_differ || color_change_differ) ?
@ -1166,7 +1166,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
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.
this->invalidate_step(psGCodeExport));
m_model.custom_gcode_per_print_z = model.custom_gcode_per_print_z;
m_model.custom_gcode_per_print_z() = model.custom_gcode_per_print_z();
}
if (model_object_list_equal(m_model, model)) {
// The object list did not change.

View File

@ -422,7 +422,7 @@ void Preview::create_sliders()
if (wxGetApp().is_editor()) {
m_layers_slider->set_callback_on_ticks_changed([this]() -> void {
Model& model = wxGetApp().plater()->model();
model.custom_gcode_per_print_z = m_layers_slider->GetTicksValues();
model.custom_gcode_per_print_z() = m_layers_slider->GetTicksValues();
m_schedule_background_process();
m_keep_current_preview_type = false;
@ -615,7 +615,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
Plater* plater = wxGetApp().plater();
CustomGCode::Info ticks_info_from_model;
if (wxGetApp().is_editor())
ticks_info_from_model = plater->model().custom_gcode_per_print_z;
ticks_info_from_model = plater->model().custom_gcode_per_print_z();
else {
ticks_info_from_model.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_model.gcodes = active_gcode_result()->custom_gcode_per_print_z;
@ -956,7 +956,8 @@ void Preview::load_print_as_fff(bool keep_z_range)
const std::vector<std::string> tool_colors = wxGetApp().plater()->get_extruder_color_strings_from_plater_config(active_gcode_result());
const std::vector<CustomGCode::Item>& color_print_values = wxGetApp().is_editor() ?
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : active_gcode_result()->custom_gcode_per_print_z;
wxGetApp().plater()->model().custom_gcode_per_print_z().gcodes : active_gcode_result()->custom_gcode_per_print_z;
std::vector<std::string> color_print_colors;
if (!color_print_values.empty()) {
color_print_colors = wxGetApp().plater()->get_color_strings_for_color_print(active_gcode_result());

View File

@ -1329,7 +1329,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
show_substitutions_info(config_substitutions.substitutions, filename.string());
if (load_config) {
this->model.custom_gcode_per_print_z = model.custom_gcode_per_print_z;
this->model.get_custom_gcode_per_print_z_vector() = model.get_custom_gcode_per_print_z_vector();
this->model.wipe_tower = model.wipe_tower;
}
}
@ -1355,8 +1355,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
preset_bundle->load_config_model(filename.string(), std::move(config));
q->notify_about_installed_presets();
if (loaded_printer_technology == ptFFF)
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &preset_bundle->project_config);
//if (loaded_printer_technology == ptFFF)
// CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z(), &preset_bundle->project_config);
// For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload"
wxGetApp().load_current_presets(false);
@ -1956,7 +1956,8 @@ void Plater::priv::delete_all_objects_from_model()
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
sidebar->show_sliced_info_sizer(false);
model.custom_gcode_per_print_z.gcodes.clear();
for (CustomGCode::Info& info : model.get_custom_gcode_per_print_z_vector())
info.gcodes.clear();
}
void Plater::priv::reset()
@ -1988,7 +1989,8 @@ void Plater::priv::reset()
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
this->sidebar->show_sliced_info_sizer(false);
model.custom_gcode_per_print_z.gcodes.clear();
for (CustomGCode::Info& info : model.get_custom_gcode_per_print_z_vector())
info.gcodes.clear();
}
void Plater::priv::mirror(Axis axis)
@ -6649,7 +6651,7 @@ std::vector<std::string> Plater::get_extruder_color_strings_from_plater_config(c
std::vector<std::string> Plater::get_color_strings_for_color_print(const GCodeProcessorResult* const result) const
{
std::vector<std::string> colors = get_extruder_color_strings_from_plater_config(result);
colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size());
colors.reserve(colors.size() + p->model.custom_gcode_per_print_z().gcodes.size());
if (wxGetApp().is_gcode_viewer() && result != nullptr) {
for (const CustomGCode::Item& code : result->custom_gcode_per_print_z) {
@ -6658,7 +6660,7 @@ std::vector<std::string> Plater::get_color_strings_for_color_print(const GCodePr
}
}
else {
for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z.gcodes) {
for (const CustomGCode::Item& code : p->model.custom_gcode_per_print_z().gcodes) {
if (code.type == CustomGCode::ColorChange)
colors.emplace_back(code.color);
}

View File

@ -48,7 +48,7 @@ void ProjectDirtyStateManager::update_from_preview()
{
if (wxApp::GetInstance() == nullptr || wxGetApp().plater() == nullptr)
return;
const bool is_dirty = m_initial_custom_gcode_per_print_z != wxGetApp().model().custom_gcode_per_print_z;
const bool is_dirty = m_initial_custom_gcode_per_print_z != wxGetApp().model().custom_gcode_per_print_z();
if (m_custom_gcode_per_print_z_dirty != is_dirty) {
m_custom_gcode_per_print_z_dirty = is_dirty;
if (wxApp::GetInstance() != nullptr)
@ -73,7 +73,7 @@ void ProjectDirtyStateManager::reset_initial_presets()
for (const PresetCollection *preset_collection : app.get_active_preset_collections())
m_initial_presets[preset_collection->type()] = preset_collection->get_selected_preset_name();
m_initial_project_config = app.preset_bundle->project_config;
m_initial_custom_gcode_per_print_z = app.model().custom_gcode_per_print_z;
m_initial_custom_gcode_per_print_z = app.model().custom_gcode_per_print_z();
}
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW