Skip to content

Commit 197b958

Browse files
committed
Merge remote-tracking branch 'remotes/local/dev' into superslicer_variant
2 parents 96bca56 + 2677d9f commit 197b958

15 files changed

+336
-68
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
2+
# How to create a vendor profile
3+
4+
The vendor profiles allow to easily creates many different profiles from a common base, via an inheritance graph. It's all contained in a single ini file.
5+
6+
7+
## ini format
8+
As the file in in ini format, each section is in the format:
9+
```
10+
[section_id:section_value]
11+
setting_name1 = setting_value1
12+
setting_name2 = setting_value2
13+
```
14+
each setting in a section need to be unique.
15+
16+
## Sections
17+
Here are the different sections of the vendor profile ini file. Each are explained in more detail afterwards
18+
* `[vendor]`: the first section, containing information about the vendor, to be displayed in the wizard, and to help with (auto-)updates.
19+
* `[printer_model]`: allow to group printer Presets into a common section, with its thumbnail for the wizard. it's the entry point to install vendor presets. When installed, the slicer will remember each {vendor-printer_model-variant} key is installed.
20+
* `[printer]`: printer preset with its extruder(s)
21+
* `[filament]`: fff filament preset
22+
* `[print]`: fff print preset
23+
* `[sla_material]`: sla resin preset
24+
* `[sla_print]`: sla print preset
25+
26+
For the printer, filament and print section, there is two kinds of name:
27+
1) `[print:my_print_preset_key]`: this is a preset that is useable in the slicer, it can be selected in the combo box in the interface.
28+
2) `[print:*0.2mmheight_print*]`: this is a preset that isn't visible in the slicer, it's only used as a library of settings to be applied at the end to the first kind
29+
30+
The printer, filament and print section can inherit another one (of the same type) via the `inherit` setting. It can takes a single value or an array, separated by `;`. Example:
31+
```
32+
[print:*common_print*]
33+
perimeters = 3
34+
...
35+
36+
[print:*one_per_top*]
37+
only_one_perimeter_top = 1
38+
39+
[print:final_print_preset]
40+
inherit = *common_print*; *one_per_top*
41+
fill_density = 15%
42+
```
43+
## `[vendor]`Section
44+
This section doesn't have any section value, it's just `[vendor]`
45+
The settings are:
46+
* `id`: the string id of the vendor file.
47+
* `technologies` = The printer technologies available in this files. Can be `FFF`, `SLA` or `FFF;SLA` if this file has both.
48+
* `name`: the displayed string in the wizard. If `{technology}` is present inside, it will be replaced by the technology string (FFF or SLA).
49+
* `full_name`: a displayed string in the wizard. can have `{technology}`.
50+
* `config_version`: the current version to see if this file is newer , the same or older than the one installed in the slicer. See below how it works.
51+
* `config_update_url`: the url to call to check for new versions. Left it empty if you don't have it.
52+
* `changelog_url`: the url for the changelog of this file. Can be left empty.
53+
54+
### version
55+
The version has X.X.X.X+metadata-prerelease
56+
Example of valid versions:
57+
`2.7`
58+
`2.7.0`
59+
`2.7.61.12345`
60+
`2.7.1.1-alpha2`
61+
`2.7.1.1-beta1`
62+
`2.7.1.1+2024.01.23`
63+
`2.7.1.1+2024.01.23-susi`
64+
if the version is 'bigger', then it's more recent can replace an older version.
65+
How to check if one version is bigger/ more recent than the other?
66+
First we check the first number: `2.0` > `1.10`
67+
If equal, then we check the second number: `2.10` > `2.9`
68+
If equal, then we check the third number: `2.7.1234` > `2.7.0`
69+
If equal, then we check the third number: `2.7.0.1` > `2.7.0.0`
70+
If equal, then we check the prerelease string (alphanumeric order): `2.7.0.1-b1` > `2.7.0.1-a2`, or if it exists `2.7.0.1` > `2.7.0.1-b`
71+
72+
note: the metadata part is ignored
73+
note: if the number of digit is different, then the comparison only look at the first ones`2.7.1` == `2.7`, `2.7` > `2.7.1-alpha`
74+
75+
## `[printer_model]`Section
76+
The section has a value. It's a id to link the printer_model with printer profiles. Example: `[printer_model:Voron_v4_250]`
77+
The settings are:
78+
* `name`: Displayed name in the wizard for this printer model.
79+
* `variants`: array of string separated by ';' to link a printer preset to a variant. These strings are displayed in the wizard in this order, with the first being the 'default' for this printer model. Example: `0.4; 0.25; highflow 0.6; 0.4 with 5 filaments`
80+
* `technology`: FFF or SLA
81+
`family`: all printer_model with the same family string are placed on the same line. these families are in the same order as in this file.
82+
* `bed_model`: name of the stl file in your vendor directory that contains the bed geometry (example: `bed_model = bed-v4-250.stl`)
83+
* `bed_texture`: name of the png file in your vendor directory that contains the bed texture (example: `bed_texture= bed-v4-250.png`)
84+
* `bed_with_grid`: 0 or 1 if you want to have a grid displayed on top of the bed texture.
85+
* `thumbnail`: name of the png file in your vendor directory that contains the thumbnail to display in the wizard (example: `thumbnail = Voron_v4_250_thumb.png`)
86+
* `default_materials`: array of filaments/materials name to install by default when installing at least one of this printer model. example: `default_materials = Basic ABS @VORON; Basic PLA @VORON;`
87+
88+
## print/sla_print/printer/filament/sla_material
89+
90+
The section value is used as an id to reference the printers preset for the inheritance graph. There are two kind of presets: the normal ones that can be displayed and used and the hidden ones that have a `*` as the first and last character and are only used as intermediate preset in the inheritance tree.
91+
Examples: `[printer:*common*]` `[printer:Printer project 42-id.2]` `[printer:my_printer_id]`
92+
93+
94+
### Slicer settings
95+
To define a setting in a print, filament or printer preset, you put its key (look at the tooltip in the slicer), then the value after an `=``.
96+
* Boolean type: put `0` for false and `1` for true.
97+
* Integer type: write the number
98+
* Float type: write it with a `.` as zero-separator (`42.1234`)
99+
* Percentage: like a Float with a `%` after (`42.1234%`)
100+
* String type: you can write it directly after the `=` (`start_gcode = #custom start\nprint_start EXTRUDER=200`). Some`\` will be interpreted: `\n` for new line, `\\` for a '\', `\n` for 'carriage return' ). You can also enclosed it into `"`: (`start_gcode = "#custom start\nprint_start EXTRUDER=200"`)
101+
* Enum type: you need to get the value key for the option you need. The easiest is to get it from a saved config (from the end of a gcode or a saved profile). Example: `fill_pattern = gyroid`
102+
* Point type: it's FloatxFloat (`thumbnails = 64x64`)
103+
* Graph type: it's a vector of value separated by `:`. the first three value are: begin_index, end_index, curve_type(0=SQUARE, 1=LINEAR, 2=SPLINE) and all the other values are the points of the graph. Example: `overhangs_dynamic_speed= 0:3:1:0x0:50x25:100x100`
104+
105+
If the settings is an array, the values need to be separated by a `,`: `thumbnails = 64x64,400x300`
106+
If the setting is deactivated, put a `!` before: `first_layer_extrusion_width = !0.42`
107+
For an array, you can deactivate each value the same way: `idle_temperature = !30,!30`
108+
109+
It's not possible to replace only one element of a vector, you need to set the full vector.
110+
111+
### inheritance
112+
113+
The `inherits` setting allow to start this preset with some settings already set. it's an array using `;` as separator. It's not mandatory.
114+
Examples: `inherits = *common*; *hot*` `inherits = my_printer_id; *slow*`
115+
116+
The preset start with nothing defined.
117+
The first preset in `inherits` can set the values it defines.
118+
Same for the next ones in the `inherits` array, and it erase the current value if it's already defined.
119+
Then the settings defined in this Preset ca erase anything already defined by the `inherits`.
120+
121+
Advice about inheritance:
122+
* If you define it, put it first after the section name, to increase its visibility.
123+
* There is two kind of presets:
124+
1) The first kind defines every settings, by themselves or from an inherited preset. We call them 'full preset'
125+
2) The second kind only defines a subset of the settings, and so don't inherit any 'full preset'. We call them 'flavour preset'
126+
* Any final preset (without `*` as first and last character in their id) need to be a 'full preset'.
127+
* Hidden presets (with `*` as first and last character in their id) can be 'full preset' or 'flavour preset'.
128+
* A final preset can inherit a final preset.
129+
* A 'full preset' should defines all settings or inherit another 'full preset'. Any setting that isn't defined in a final Preset won't be able to be reverted to 'system value' in the slicer.
130+
* If a 'full preset' inherit another 'full preset', it needs to be the first in the `inherits` array (anything before will be erased by it).
131+
* It's advised to use the word 'common' in any hidden 'full preset', to be sure you only put them as the first inheritance. It's easy to have a `*common*` root that defines everything and then specialised 'commons' like `*common_voron2*` that inherit another common. And of course avoid naming any 'flavour preset' as 'common'.
132+
## `[printer]` Section
133+
The printer section has some special setting:
134+
* `printer_model`: Any final Preset (without `*` as first and last character in their id) need to have this setting defined (by itself or by inheritance) to link it to a printer_model. The value of this setting need to be the same as the printer_model section value. Example: `printer_model = Voron_v4_250`
135+
* `printer_variant`: Any final Preset (without `*` as first and last character in their id) need to have this setting defined (by itself or by inheritance) to link it to a printer_model variant. The value of this setting need to be the same as one of the `variants` values of the linked printer_model. Examples: `printer_variant = 0.4` `printer_variant = highflow 0.6`
136+
* `default_print_profile`: the print section value that should be the default when you select this printer.
137+
* `default_filament_profile`: the filament section value that should be the default when you select this printer.
138+
* `default_sla_print_profile`: the print_sla section value that should be the default when you select this printer.
139+
* `default_sla_material_profile`: the sla_material section value that should be the default when you select this printer.
140+
141+
## `[print]` and `[sla_print]` Section
142+
it's advised to set a `compatible_printers_condition` or a `compatible_printers` to let the user select this print option only when the desired printer(s) is selected. It avoids polluting the interface's print profile list with print profile from other vendors.
143+
144+
## `[filament]` and `[sla_material]` Section
145+
You may want to set `compatible_printers_condition` or a `compatible_printers` for the default material profile (like "basic PLA") to not pollute the material list with a "basic pla" for each vendor installed.
146+
If you define a special material only defined in this vendor profile, you can let these field blank to allow any printer to use this material.
147+
148+
You can also use `compatible_prints` and `compatible_prints_condition` if you need to have special filament setting for a special kind of print profile (like a speedy print profile that need higher temperature & more cooling).
149+
150+
## Tool
151+
If you are able to build the slicer, you can build the project `convert_config`.
152+
This tool allow to check & fix a vendor profile.
153+
If you launch it with the path of your profile, it will tell you the issues the profiles has (if you feed it with a profile from prusaslicer, it will tell you all the conversions it makes). Then it will create a fixed config in a new directory (named 'convert'), adding any missing setting into the common roots.
154+
Take care of any "error" or "warning" line, these indicates problems you need to take care manually (like a preset inheriting two presets that both defines everything).
155+
If you want to submit a new vendor or a revision of a current profile for a certain version of the slicer, then the ini file should be unchanged when going through this tool.

src/libslic3r/Format/BBConfig.cpp

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,6 @@ void init()
479479
value_translation_map["machine_limits_usage"]["1"] = "emit_to_gcode";
480480

481481

482-
483482
/// GCODE
484483
custom_gcode_replace.emplace_back("[bed_temperature_initial_layer_single]", "{first_layer_bed_temperature[initial_extruder]}");
485484
custom_gcode_replace.emplace_back("bed_temperature_initial_layer_single", "first_layer_bed_temperature[initial_extruder]");
@@ -572,6 +571,20 @@ void complicated_convert(t_config_option_key &opt_key,
572571
opt_key = "print_extrusion_multiplier";
573572
value = std::to_string(int(std::stof(value.c_str()) * 100));
574573
}
574+
// since Mar 10, 2024 ( Optimize ensure vertical feature's UX #4402 )
575+
if ("ensure_vertical_shell_thickness" == opt_key && value != "0" && value != "1") {
576+
if ("none" == value) {
577+
value = "disabled";
578+
} else if("ensure_critical_only" == value) {
579+
value = "enabled_old";
580+
output["solid_over_perimeters"] = "2";
581+
} else if("ensure_moderate" == value) {
582+
value = "enabled_old";
583+
output["solid_over_perimeters"] = "4";
584+
} else if("ensure_all" == value) {
585+
value = "enabled_old";
586+
}
587+
}
575588
}
576589

577590
void very_complicated_convert(ConfigSubstitutionContext &unconverted_config, ConfigBase &conf_to_read_and_update) {
@@ -793,6 +806,8 @@ bool read_json_file_bambu(const std_path &temp_file,
793806
std::map<std::string, std::string> good_key_values;
794807
std::map<std::string, std::vector<std::string>> good_key_vector_values;
795808
std::unordered_map<t_config_option_key, std::pair<t_config_option_key, std::string>> dict_opt;
809+
810+
// key_translation_map
796811
for (const auto& [bb_key, value] : key_values) {
797812
if (push_into_custom_variable(config, bb_key, value))
798813
continue;
@@ -803,7 +818,8 @@ bool read_json_file_bambu(const std_path &temp_file,
803818

804819
dict_opt[my_key] = {my_key, value};
805820
}
806-
PrintConfigDef::handle_legacy_map(dict_opt, false);
821+
822+
// complicated_convert & value_translation_map
807823
for (auto &[saved_key, key_val] : dict_opt) {
808824
auto &[opt_key, value] = key_val;
809825

@@ -818,7 +834,24 @@ bool read_json_file_bambu(const std_path &temp_file,
818834
//else
819835
// config_substitutions.substitutions.push_back(ConfigSubstitution{ nullptr, entry.first+std::string(" : ")+value, nullptr});
820836
}
821-
837+
838+
// handle_legacy_map
839+
dict_opt.clear();
840+
for (const auto &[my_key, value] : good_key_values) {
841+
dict_opt[my_key] = {my_key, value};
842+
}
843+
PrintConfigDef::handle_legacy_map(dict_opt, false);
844+
good_key_values.clear();
845+
for (auto &[saved_key, key_val] : dict_opt) {
846+
auto &[opt_key, value] = key_val;
847+
if (!opt_key.empty())
848+
good_key_values[opt_key] = value;
849+
//else
850+
// config_substitutions.substitutions.push_back(ConfigSubstitution{ nullptr, entry.first+std::string(" : ")+value, nullptr});
851+
}
852+
853+
//now same for vectors (but no complicated_convert)
854+
// key_translation_map, handle_legacy_pair
822855
std::unordered_map<t_config_option_key, std::pair<t_config_option_key, std::string>> dict_opt_vector;
823856
std::unordered_map<t_config_option_key, std::string> dict_old_value;
824857
for (auto &entry : key_vector_values) {
@@ -828,29 +861,22 @@ bool read_json_file_bambu(const std_path &temp_file,
828861
continue;
829862
if (auto it = key_translation_map.find(key); it != key_translation_map.end())
830863
key = it->second;
831-
832-
dict_opt_vector[key] = {key, values[0]};
833-
}
834-
PrintConfigDef::handle_legacy_map(dict_opt_vector, false);
835-
for (auto &[saved_key, key_val] : dict_opt_vector) {
836-
auto &[opt_key, value] = key_val;
837864

838-
std::string saved_val = key_vector_values[saved_key][0];
839-
if (!opt_key.empty()) {
840-
if (saved_val != value) {
841-
for (size_t idx = 1; idx < key_vector_values[saved_key].size(); ++idx) {
842-
PrintConfigDef::handle_legacy_pair(opt_key, key_vector_values[saved_key][idx], false);
843-
assert(!opt_key.empty());
865+
if (!key.empty()) {
866+
for (size_t idx = 0; idx < values.size(); ++idx) {
867+
PrintConfigDef::handle_legacy_pair(key, values[idx], false);
868+
if (key.empty()) {
869+
break;
844870
}
845871
}
846-
if (!opt_key.empty()) {
847-
key_vector_values[saved_key][0] = value;
848-
good_key_vector_values[opt_key] = key_vector_values[saved_key];
872+
if (!key.empty()) {
873+
good_key_vector_values[key] = values;
849874
}
850875
}
851876
//else
852-
// config_substitutions.substitutions.push_back(ConfigSubstitution{ nullptr, entry.first+std::string(" : ")+(values.empty()?"":values.front()), nullptr});
877+
// config_substitutions.substitutions.push_back(ConfigSubstitution{ nullptr, entry.first+std::string(" : ")+value, nullptr});
853878
}
879+
// there will be a final handle_legacy_pair after concat anyway
854880

855881
// check how to serialize the array (string use ';', others ',')
856882
const ConfigDef *config_def = config.def();
@@ -906,10 +932,14 @@ bool read_json_file_bambu(const std_path &temp_file,
906932
}
907933

908934
// push these into config
909-
910-
for (auto &entry : good_key_values) {
911-
if(config_def->has(entry.first))
912-
config.set_deserialize(entry.first, entry.second, config_substitutions);
935+
dict_opt.clear();
936+
for (const auto &[my_key, value] : good_key_values) {
937+
dict_opt[my_key] = {my_key, value};
938+
}
939+
PrintConfigDef::handle_legacy_map(dict_opt, false);
940+
for (auto &entry : dict_opt) {
941+
if (!entry.second.first.empty() && config_def->has(entry.second.first))
942+
config.set_deserialize(entry.second.first, entry.second.second, config_substitutions);
913943
}
914944

915945
// final transform

src/libslic3r/GCode.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7085,8 +7085,8 @@ void GCodeGenerator::_add_object_change_labels(std::string& gcode) {
70857085
// if ramping lift, the move_z may be removed by exclude object. so ensure it's at the right z
70867086
// if m_new_z_target, then the ramping lift will be written. if not, then there isn't anything to ensure a good z
70877087
if(!m_new_z_target && BOOL_EXTRUDER_CONFIG(travel_ramping_lift) && m_spiral_vase_layer <= 0) {
7088-
gcode += m_writer.get_travel_to_z_gcode(m_writer.get_position().z(), "ensure z is right");
7089-
m_writer.set_lift(0);
7088+
gcode += m_writer.get_travel_to_z_gcode(m_writer.get_position().z(), "ensure z is correct when starting this object");
7089+
//m_writer.set_lift(0); // don't remove lift, we used get_position, not get_unlifted_position()
70907090
}
70917091
}
70927092
}
@@ -7337,7 +7337,6 @@ std::vector<coord_t> GCodeGenerator::get_travel_elevation(Polyline& travel, doub
73377337
void GCodeGenerator::write_travel_to(std::string &gcode, Polyline& travel, std::string comment)
73387338
{
73397339
// Note: if last_pos is undefined, then travel.size() == 1
7340-
73417340
// ramping travel?
73427341
//TODO: ramp up for the first half, then ramp down.
73437342
std::vector<coord_t> z_relative_travel;

src/libslic3r/GCode/Travels.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,9 @@ std::vector<DistancedPoint> slice_xy_path(tcb::span<const Point> xy_path,
334334
} else {
335335
//don't bother if it's at less than epsilon from the last point
336336
if (dist_target > total_distance + min_distance) {
337-
total_distance = dist_target;
338337
result.emplace_back(
339-
DistancedPoint{Line(result.back().point, point).point_at(dist_target), total_distance});
338+
DistancedPoint{Line(result.back().point, point).point_at(dist_target - total_distance), dist_target});
339+
total_distance = dist_target;
340340
}
341341
}
342342
++dist_idx;

src/libslic3r/GCode/WipeTowerIntegration.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,13 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
127127
} else {
128128
boost::replace_first(tcr_rotated_gcode, "[toolchange_gcode_enable_linear_advance]\n","");
129129
}
130-
std::string tcr_gcode;
131-
unescape_string_cstyle(tcr_rotated_gcode, tcr_gcode);
132-
gcode += tcr_gcode;
130+
131+
// the custom gcode is already processed by the parser...
132+
// supermerill: why? it breaks the '\' from custom gcode. disabling it
133+
//std::string tcr_gcode;
134+
//unescape_string_cstyle(tcr_rotated_gcode, tcr_gcode);
135+
//gcode += tcr_gcode;
136+
gcode += tcr_rotated_gcode;
133137

134138
// tag for fan speed (to not lost it)
135139
if (!finalize)

0 commit comments

Comments
 (0)