mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-13 19:01:21 +00:00
Fix crash when opening a G-code file exported by OrcaSlicer (#16441)
This commit is contained in:
@@ -3752,7 +3752,8 @@ DynamicConfig GCodeProcessor::export_config_for_render() const
|
||||
config.set_key_value("filament_is_support", new ConfigOptionBools(m_parser.get_config().filament_is_support.values));
|
||||
config.set_key_value("filament_type", new ConfigOptionStrings(m_parser.get_config().filament_type.values));
|
||||
config.set_key_value("filament_map", new ConfigOptionInts(m_parser.get_config().filament_map.values));
|
||||
config.apply(m_belt_render_config);
|
||||
// += clones the options; apply() would need a definition this config does not have.
|
||||
config += m_belt_render_config;
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <catch2/catch_message.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/generators/catch_generators.hpp>
|
||||
#include <catch2/matchers/catch_matchers.hpp>
|
||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||
|
||||
@@ -49,6 +54,74 @@ TEST_CASE("The belt header's angle marks G-code as belt G-code", "[GCodeProcesso
|
||||
CHECK_THAT(processed_belt_tilt(gcode), WithinAbs(45., 1e-6));
|
||||
}
|
||||
|
||||
TEST_CASE("A loaded G-code's belt settings and bed replace the selected printer's in the preview", "[GCodeProcessor][belt][Regression]")
|
||||
{
|
||||
// Loading a G-code applies the selected printer's config to the Print, then the file's render
|
||||
// config on top, so the preview's belt view and back-transform follow the file. The selected
|
||||
// printer is always the other kind, and every belt and bed key differs between the two.
|
||||
const bool file_is_belt = GENERATE(false, true);
|
||||
CAPTURE(file_is_belt);
|
||||
|
||||
DynamicPrintConfig file = DynamicPrintConfig::full_print_config();
|
||||
file.set_deserialize_strict({
|
||||
{ "belt_printer", file_is_belt },
|
||||
{ "belt_slice_rotation", "y" },
|
||||
{ "belt_slice_rotation_angle", -30 },
|
||||
{ "gcode_remap_x", "rev_x" },
|
||||
{ "gcode_remap_y", "pos_z" },
|
||||
{ "gcode_remap_z", "pos_y" },
|
||||
{ "belt_frame_tilt_decouple", 1 },
|
||||
{ "belt_frame_tilt_angle", 35 },
|
||||
{ "printable_area", "0x0,300x0,300x250,0x250" },
|
||||
{ "printable_height", 123 },
|
||||
});
|
||||
DynamicPrintConfig selected = DynamicPrintConfig::full_print_config();
|
||||
selected.set_deserialize_strict({
|
||||
{ "belt_printer", !file_is_belt },
|
||||
{ "belt_slice_rotation", "x" },
|
||||
{ "belt_slice_rotation_angle", 45 },
|
||||
{ "gcode_remap_x", "pos_x" },
|
||||
{ "gcode_remap_y", "pos_y" },
|
||||
{ "gcode_remap_z", "pos_z" },
|
||||
{ "belt_frame_tilt_decouple", 0 },
|
||||
{ "belt_frame_tilt_angle", 50 },
|
||||
{ "printable_area", "0x0,180x0,180x180,0x180" },
|
||||
{ "printable_height", 200 },
|
||||
});
|
||||
|
||||
ScopedTemporaryFile temp(".gcode");
|
||||
{
|
||||
std::ofstream os(temp.string());
|
||||
REQUIRE(os.is_open());
|
||||
// A full config block, as the loader rejects one with fewer than 80 values.
|
||||
os << "; generated by OrcaSlicer\n" << body << "; CONFIG_BLOCK_START\n";
|
||||
for (const std::string &key : file.keys())
|
||||
os << "; " << key << " = " << file.opt_serialize(key) << '\n';
|
||||
os << "; CONFIG_BLOCK_END\n";
|
||||
REQUIRE(os.good());
|
||||
}
|
||||
GCodeProcessor processor;
|
||||
REQUIRE_NOTHROW(processor.process_file(temp.string()));
|
||||
|
||||
Model model;
|
||||
Print print;
|
||||
print.apply(model, selected);
|
||||
REQUIRE_NOTHROW(print.apply_config_for_render(processor.export_config_for_render()));
|
||||
|
||||
// The file's belt settings win either way, so a non-belt file turns a selected belt printer's view off.
|
||||
for (const char *key : { "belt_printer", "belt_slice_rotation", "belt_slice_rotation_angle", "gcode_remap_x",
|
||||
"gcode_remap_y", "gcode_remap_z", "belt_frame_tilt_decouple", "belt_frame_tilt_angle" }) {
|
||||
CAPTURE(key);
|
||||
CHECK(print.config().opt_serialize(key) == file.opt_serialize(key));
|
||||
}
|
||||
// Only a belt file brings the bed it was sliced for.
|
||||
const DynamicPrintConfig &bed_source = file_is_belt ? file : selected;
|
||||
for (const char *key : { "printable_area", "printable_height" }) {
|
||||
CAPTURE(key);
|
||||
CHECK(print.config().opt_serialize(key) == bed_source.opt_serialize(key));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Non-belt start G-code moves keep the first-layer Z in the processor", "[GCodeProcessor]")
|
||||
{
|
||||
// The belt path (GCodeWriter tests: "start-gcode prepare-stage moves keep their real Z")
|
||||
|
||||
Reference in New Issue
Block a user