mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-02 21:31:16 +00:00
Map BambuStudio Keys and Values to Their OrcaSlicer Equivalents
BambuStudio projects lost or misread several settings on import: - Rename role_base_wipe_speed, no_slow_down_for_cooling_on_outwalls, process_notes, prime_tower_max_speed, enable_support_ironing and sparse_infill_lattice_angle_1/2 to their OrcaSlicer names. - Map the values 2dlattice, 2dhoneycomb and tree_organic. - Map BambuStudio's ensure_vertical_shell_thickness levels, and read top_one_wall_type = not apply as off. - Keep prime_tower_rib_wall = 0 as a rectangle wall instead of dropping the key, which fell back to a rib wall. - Read a negative raft_first_layer_expansion (BambuStudio's auto) as 2 mm, which also stops it failing the range check. - Rename whole entries of different_settings_to_system, so a rename no longer rewrites longer keys that contain the old name.
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include "GCode/Thumbnails.hpp"
|
||||
#include <set>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
@@ -9185,16 +9187,18 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
} else if (opt_key == "tree_support_wall_count" && value == "-1") {
|
||||
value = "0";
|
||||
} else if (opt_key == "different_settings_to_system") {
|
||||
std::string copy_value = value;
|
||||
copy_value.erase(std::remove(copy_value.begin(), copy_value.end(), '\"'), copy_value.end()); // remove '"' in string
|
||||
std::set<std::string> split_keys = SplitStringAndRemoveDuplicateElement(copy_value, ";");
|
||||
for (std::string split_key : split_keys) {
|
||||
std::string copy_key = split_key, copy_value = "";
|
||||
handle_legacy(copy_key, copy_value);
|
||||
if (copy_key != split_key) {
|
||||
ReplaceString(value, split_key, copy_key);
|
||||
}
|
||||
// Rename whole entries: a substring rename would also hit longer keys that contain the old name.
|
||||
std::vector<std::string> entries;
|
||||
boost::split(entries, value, boost::is_any_of(";"));
|
||||
for (std::string &entry : entries) {
|
||||
std::string key = entry, unused_value;
|
||||
key.erase(std::remove(key.begin(), key.end(), '\"'), key.end());
|
||||
std::string new_key = key;
|
||||
handle_legacy(new_key, unused_value);
|
||||
if (new_key != key)
|
||||
ReplaceString(entry, key, new_key);
|
||||
}
|
||||
value = boost::algorithm::join(entries, ";");
|
||||
} else if (opt_key == "overhang_fan_threshold" && value == "5%") {
|
||||
value = "10%";
|
||||
} else if( opt_key == "wall_infill_order" ) {
|
||||
@@ -9236,6 +9240,13 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
else if (value == "0"){
|
||||
value = "ensure_moderate";
|
||||
}
|
||||
// BambuStudio's levels
|
||||
else if (value == "enabled")
|
||||
value = "ensure_all";
|
||||
else if (value == "partial")
|
||||
value = "ensure_moderate";
|
||||
else if (value == "disabled")
|
||||
value = "none";
|
||||
} else if (opt_key == "rotate_solid_infill_direction") {
|
||||
opt_key = "solid_infill_rotate_template";
|
||||
if (value == "1") {
|
||||
@@ -9251,9 +9262,11 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
opt_key = "chamber_temperature";
|
||||
} else if (opt_key == "thumbnail_size") {
|
||||
opt_key = "thumbnails";
|
||||
} else if (opt_key == "top_one_wall_type" && value != "none") {
|
||||
} else if (opt_key == "top_one_wall_type") {
|
||||
// BambuStudio's "topmost" (one wall on the topmost layer only) widens to every top surface.
|
||||
opt_key = "only_one_wall_top";
|
||||
value = "1";
|
||||
if (!value.empty())
|
||||
value = (value == "not apply" || value == "none") ? "0" : "1";
|
||||
} else if (opt_key == "initial_layer_flow_ratio") {
|
||||
opt_key = "bottom_solid_infill_flow_ratio";
|
||||
} else if (opt_key == "ironing_direction") {
|
||||
@@ -9271,6 +9284,20 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
opt_key == "ironing_pattern" ||
|
||||
opt_key == "support_ironing_pattern") && value == "zig-zag") {
|
||||
value = "rectilinear";
|
||||
} else if (opt_key == "sparse_infill_pattern" && value == "2dlattice") {
|
||||
// BambuStudio's name, and OrcaSlicer's before the lateral patterns were renamed
|
||||
value = "lateral-lattice";
|
||||
} else if (opt_key == "sparse_infill_pattern" && value == "2dhoneycomb") {
|
||||
value = "lateral-honeycomb";
|
||||
} else if (opt_key == "sparse_infill_lattice_angle_1" || opt_key == "lattice_angle_1") {
|
||||
opt_key = "lateral_lattice_angle_1";
|
||||
} else if (opt_key == "sparse_infill_lattice_angle_2" || opt_key == "lattice_angle_2") {
|
||||
opt_key = "lateral_lattice_angle_2";
|
||||
} else if (opt_key == "support_style" && value == "tree_organic") {
|
||||
value = "organic";
|
||||
} else if (opt_key == "raft_first_layer_expansion" && !value.empty() && value.front() == '-') {
|
||||
// BambuStudio's auto: 2 mm for normal supports and rafts. Tree branches use tree_support_auto_brim here.
|
||||
value = "2";
|
||||
} else if (opt_key == "filament_map_mode") {
|
||||
if (value == "Auto") value = "Auto For Flush";
|
||||
}
|
||||
@@ -9299,12 +9326,11 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
}
|
||||
// Orca: Rename wipe tower ribs related options
|
||||
else if (opt_key == "prime_tower_rib_wall") {
|
||||
if (value == "1") {
|
||||
opt_key = "wipe_tower_wall_type";
|
||||
value = "rib";
|
||||
} else {
|
||||
opt_key = "";
|
||||
}
|
||||
opt_key = "wipe_tower_wall_type";
|
||||
if (value == "1" || value == "true")
|
||||
value = "rib";
|
||||
else if (!value.empty())
|
||||
value = "rectangle";
|
||||
} else if (opt_key == "prime_tower_extra_rib_length") {
|
||||
opt_key = "wipe_tower_extra_rib_length";
|
||||
} else if (opt_key == "prime_tower_rib_width") {
|
||||
@@ -9316,6 +9342,18 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
} else if (opt_key == "machine_switch_extruder_time") {
|
||||
opt_key = "machine_tool_change_time";
|
||||
}
|
||||
// BambuStudio names of OrcaSlicer options
|
||||
else if (opt_key == "role_base_wipe_speed") {
|
||||
opt_key = "role_based_wipe_speed";
|
||||
} else if (opt_key == "no_slow_down_for_cooling_on_outwalls") {
|
||||
opt_key = "dont_slow_down_outer_wall";
|
||||
} else if (opt_key == "process_notes") {
|
||||
opt_key = "notes";
|
||||
} else if (opt_key == "prime_tower_max_speed") {
|
||||
opt_key = "wipe_tower_max_purge_speed";
|
||||
} else if (opt_key == "enable_support_ironing") {
|
||||
opt_key = "support_ironing";
|
||||
}
|
||||
else if (opt_key == "wall_direction" && value == "auto") {
|
||||
value = "ccw";
|
||||
}
|
||||
|
||||
@@ -508,6 +508,83 @@ TEST_CASE("load_from_json hands a preset's include list to the caller instead of
|
||||
CHECK(config.opt_string("machine_end_gcode") == "M84");
|
||||
}
|
||||
|
||||
TEST_CASE("handle_legacy maps BambuStudio keys and values to their OrcaSlicer equivalents", "[Config]") {
|
||||
struct Row { std::string key, value, expected_key, expected_value; };
|
||||
const Row row = GENERATE(values<Row>({
|
||||
{"role_base_wipe_speed", "0", "role_based_wipe_speed", "0"},
|
||||
{"no_slow_down_for_cooling_on_outwalls", "1", "dont_slow_down_outer_wall", "1"},
|
||||
{"process_notes", "note", "notes", "note"},
|
||||
{"prime_tower_max_speed", "70", "wipe_tower_max_purge_speed", "70"},
|
||||
{"enable_support_ironing", "1", "support_ironing", "1"},
|
||||
{"sparse_infill_lattice_angle_1", "-30", "lateral_lattice_angle_1", "-30"},
|
||||
{"sparse_infill_lattice_angle_2", "20", "lateral_lattice_angle_2", "20"},
|
||||
{"lattice_angle_1", "-30", "lateral_lattice_angle_1", "-30"},
|
||||
{"lattice_angle_2", "20", "lateral_lattice_angle_2", "20"},
|
||||
{"sparse_infill_pattern", "2dlattice", "sparse_infill_pattern", "lateral-lattice"},
|
||||
{"sparse_infill_pattern", "2dhoneycomb", "sparse_infill_pattern", "lateral-honeycomb"},
|
||||
{"support_style", "tree_organic", "support_style", "organic"},
|
||||
{"raft_first_layer_expansion", "-1", "raft_first_layer_expansion", "2"},
|
||||
{"raft_first_layer_expansion", "3.5", "raft_first_layer_expansion", "3.5"},
|
||||
{"ensure_vertical_shell_thickness", "enabled", "ensure_vertical_shell_thickness", "ensure_all"},
|
||||
{"ensure_vertical_shell_thickness", "partial", "ensure_vertical_shell_thickness", "ensure_moderate"},
|
||||
{"ensure_vertical_shell_thickness", "disabled", "ensure_vertical_shell_thickness", "none"},
|
||||
{"top_one_wall_type", "not apply", "only_one_wall_top", "0"},
|
||||
{"top_one_wall_type", "all top", "only_one_wall_top", "1"},
|
||||
{"top_one_wall_type", "topmost", "only_one_wall_top", "1"},
|
||||
{"prime_tower_rib_wall", "1", "wipe_tower_wall_type", "rib"},
|
||||
{"prime_tower_rib_wall", "0", "wipe_tower_wall_type", "rectangle"},
|
||||
{"prime_tower_rib_wall", "true", "wipe_tower_wall_type", "rib"},
|
||||
// A rename touches whole entries, not keys that contain the old name.
|
||||
{"different_settings_to_system", "lattice_angle_1;sparse_infill_lattice_angle_1;wall_loops", "different_settings_to_system",
|
||||
"lateral_lattice_angle_1;lateral_lattice_angle_1;wall_loops"},
|
||||
// different_settings_to_system and JSON arrays pass the key alone
|
||||
{"prime_tower_rib_wall", "", "wipe_tower_wall_type", ""},
|
||||
{"top_one_wall_type", "", "only_one_wall_top", ""},
|
||||
{"enable_height_slowdown", "1", "", "1"},
|
||||
{"counter_coef_2", "0.025", "", "0.025"},
|
||||
}));
|
||||
t_config_option_key key = row.key;
|
||||
std::string value = row.value;
|
||||
PrintConfigDef::handle_legacy(key, value);
|
||||
INFO(row.key << " = " << row.value);
|
||||
CHECK(key == row.expected_key);
|
||||
CHECK(value == row.expected_value);
|
||||
}
|
||||
|
||||
TEST_CASE("A BambuStudio project config loads its renamed settings without substitutions", "[Config]") {
|
||||
ScopedTemporaryFile tmp(".json");
|
||||
{
|
||||
boost::nowide::ofstream ofs(tmp.string());
|
||||
ofs << R"({"role_base_wipe_speed":"0","no_slow_down_for_cooling_on_outwalls":["1","0"],)"
|
||||
R"("process_notes":"note","prime_tower_max_speed":"70","enable_support_ironing":"1",)"
|
||||
R"("sparse_infill_pattern":"2dlattice","sparse_infill_lattice_angle_1":"-30",)"
|
||||
R"("support_style":"tree_organic","ensure_vertical_shell_thickness":"partial",)"
|
||||
R"("top_one_wall_type":"not apply","prime_tower_rib_wall":"0","raft_first_layer_expansion":"-1",)"
|
||||
R"("enable_height_slowdown":["1"]})";
|
||||
}
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
ConfigSubstitutionContext substitutions(ForwardCompatibilitySubstitutionRule::Disable);
|
||||
std::map<std::string, std::string> key_values;
|
||||
std::string reason;
|
||||
REQUIRE(config.load_from_json(tmp.string(), substitutions, true, key_values, reason) == 0);
|
||||
CHECK(substitutions.substitutions.empty());
|
||||
CHECK(substitutions.unrecogized_keys == std::vector<std::string>{"enable_height_slowdown"});
|
||||
|
||||
CHECK_FALSE(config.opt_bool("role_based_wipe_speed"));
|
||||
CHECK(config.option<ConfigOptionBools>("dont_slow_down_outer_wall")->values == std::vector<unsigned char>{1, 0});
|
||||
CHECK(config.opt_string("notes") == "note");
|
||||
CHECK_THAT(config.opt_float("wipe_tower_max_purge_speed"), Catch::Matchers::WithinAbs(70., 1e-9));
|
||||
CHECK(config.opt_bool("support_ironing"));
|
||||
CHECK(config.opt_enum<InfillPattern>("sparse_infill_pattern") == ipLateralLattice);
|
||||
CHECK_THAT(config.opt_float("lateral_lattice_angle_1"), Catch::Matchers::WithinAbs(-30., 1e-9));
|
||||
CHECK(config.opt_enum<SupportMaterialStyle>("support_style") == smsTreeOrganic);
|
||||
CHECK(config.opt_enum<EnsureVerticalShellThickness>("ensure_vertical_shell_thickness") == evstModerate);
|
||||
CHECK_FALSE(config.opt_bool("only_one_wall_top"));
|
||||
CHECK(config.opt_enum<WipeTowerWallType>("wipe_tower_wall_type") == wtwRectangle);
|
||||
CHECK_THAT(config.opt_float("raft_first_layer_expansion"), Catch::Matchers::WithinAbs(2., 1e-9));
|
||||
CHECK(config.validate().count("raft_first_layer_expansion") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("save_to_json writes the same document to a stream as to a file", "[Config]") {
|
||||
DynamicPrintConfig config;
|
||||
config.set_key_value("layer_height", new ConfigOptionFloat(0.2));
|
||||
|
||||
Reference in New Issue
Block a user