Calibration help: first 2 item
- bed leveling calibration - filament flow calibration (need some more pics)
51
resources/calibration/bed_leveling/bed_leveling.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bed level calibration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bed level calibration</h1>
|
||||
<p>This calibration is the first one to do, because it's mandatory to make a print stick on the build plate.</p>
|
||||
<p>This calibration is made to do the fine tuning. Please level roughly the printer before: move your nozzle to 0.2mm, then you must be able to move a paper between the nozzle and the plater, but you have to be able to feel the nozzle touching it. With that, you should be able to level the bed with a ~0.1mm precision.</p>
|
||||
<h2>How it works</h2>
|
||||
<p>First, select your printer and your default print profile, with the filament profile for a filament you have. Note that this works with your first extruder if you have multiple ones.</p>
|
||||
<p>When clicking on the Generate button, the program will create and slice the test print. You have to send it to your printer and print it. After the print end, check the result of each corners and the middle one against the photo below. You will have to tune your printer/firmware to correct the height if needed.</p>
|
||||
<h2>Results</h2>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><img src="./low_ll.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./low_l.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./low.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./good.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high_h.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high_hh.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">Too far away</td>
|
||||
<td style="text-align: center;">Too far</td>
|
||||
<td style="text-align: center;">Too far:<br />You can spot<br />a little gap</td>
|
||||
<td style="text-align: center;">perfect</td>
|
||||
<td style="text-align: center;">Too near</td>
|
||||
<td style="text-align: center;">Trap!<br />It's too near:<br />check the thickness<br />with your fingers!</td>
|
||||
<td style="text-align: center;">Far too near<br />Dangerous<br />for the bed</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>How to tune your printer</h2>
|
||||
<p><strong>If your printer has screws</strong>, use them to lift or drop the bed below the patch that need an adjust. Don't forget to print the test after the adjust to verify the compensation. Be careful, most of the time, a half-turn means 0.2mm of height, which equals (often) to the height of the first layer, so if you lift the bed, never turn more than that and prefer adjusting by quarter-turn at most.</p>
|
||||
<p><strong>If it doesn’t</strong>, you have to use the software or modify the firmware configuration, refer to the manual of your printer.</p>
|
||||
<h2>Advices</h2>
|
||||
<p>If your filament have a hard time sticking to the bed, you can try to :</p>
|
||||
<ul>
|
||||
<li>Increase the first layer width, it will increase the squish (pressure) without any over-extrusion. You can go as far as 200% nozzle width, but 150% should be enough. (Advanced setting, print -> width)</li>
|
||||
<li>Reduce first layer printing speed, to let it time to stick. (Advanced setting, print -> speed)</li>
|
||||
<li>You can disable/enable z-hop for the first layer by increasing "only lift z"-> above Z" to a higher value than your first layer height. Enbaling it may pull the filament from the bed and diabling may let the nozzle strke & push the deposited filament, so you have to test and keep the best. (Advanced setting, printer -> extruder)</li>
|
||||
</ul>
|
||||
<h2>Notes</h2>
|
||||
<p>After the filament flow calibration, if it appears that the flow was very wrong, you may want to redo this calibration just after.</p>
|
||||
<p>Most of the calibrations need to done is the right order. This one is the first to do.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
resources/calibration/bed_leveling/good.jpg
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
resources/calibration/bed_leveling/high.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/calibration/bed_leveling/high_h.jpg
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
resources/calibration/bed_leveling/high_hh.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/calibration/bed_leveling/low.jpg
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
resources/calibration/bed_leveling/low_l.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/calibration/bed_leveling/low_ll.jpg
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
resources/calibration/bed_leveling/patch.amf
Normal file
12
resources/calibration/bridge_flow/bridge_flow.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Document HTML</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>hello you</h1>
|
||||
bonjour le monde
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
resources/calibration/calibration_cube.amf
Normal file
BIN
resources/calibration/filament_flow/0_v1.jpg
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
resources/calibration/filament_flow/O.amf
Normal file
BIN
resources/calibration/filament_flow/_0.amf
Normal file
57
resources/calibration/filament_flow/filament_flow.html
Normal file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Filament flow calibration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Filament flow calibration</h1>
|
||||
<p>You need to do the bed level calibration before this one.</p>
|
||||
<p>This test will print five tests samples with various level of flow. You can choose the flow difference between each steps. You should start with the 10% one. After verifying the result with the help of the tabel below, you have to modify the filamant extrusion multiplier in your filament preset (if the -20 is the best, change the multiplier from 1 to 0.8, see the formula below). Don't forget to save it afterwards. You can continue with the 2.5 step if you want a bit more precision.</p>
|
||||
<h2>Results</h2>
|
||||
<table>
|
||||
<tbody>
|
||||
<h4>Exemple:</h4>
|
||||
<tr>
|
||||
<td><img src="./m20.jpg" alt="too low, by far" width="150" height="150" /></td>
|
||||
<td><img src="./m10.jpg" alt="too low, by far" width="150" height="150" /></td>
|
||||
<td><img src="./0_v1.jpg" alt="too low, by far" width="150" height="150" /></td>
|
||||
<td><img src="./p10.jpg" alt="too low, by far" width="150" height="150" /></td>
|
||||
<td><img src="./p20.jpg" alt="too low, by far" width="150" height="150" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">not flat</td>
|
||||
<td style="text-align: center;">not flat</td>
|
||||
<td style="text-align: center;">not flat</td>
|
||||
<td style="text-align: center;">flat<br />But the circle<br />isn't flat enough</td>
|
||||
<td style="text-align: center;">Flat surface<br />and good circle</td>
|
||||
</tr>
|
||||
<p>So here, I should </p>
|
||||
</table>
|
||||
<p>The flow you want to choose is the lowest that don't create gaps in the top surface. Here it seems that the good flow is below +20. So you have to change your extrusion multiplier to 1.2 and print the second set of test (or put 1.15 and call it for now).</p>
|
||||
<h2>How to tune your printer</h2>
|
||||
<p>You have to change the extrusion multiplier for the filament you calibrate for (and save it). Formula for the new extrusion multipler: new_multiplier = ( (100 + choosen_number) / 100 ) * old_multiplier<br />
|
||||
Exemple: first step, i choose the -10, so i have ((100-10)/100) * 1 = (0.9) * 1 = 0.9<br />
|
||||
second step i chooe +5, so i have ((100+5)/100) * 0.9 = (1.05) * 0.9 = 0.945
|
||||
</p>
|
||||
<p>If you want to make this change permanent and left your extrusion multipler to 1 in slic3r++, you can change your firmware configuration by mutiplying (or dividing, depends of the firmware/setting) the 'extruder speed setting' (e-step, step_distance) by this extrusion multipler.</p>
|
||||
<h2>Advice</h2>
|
||||
<p>Before doing this test, it's preferable to calibrate your extruder (it's easier on bowden setup):</p>
|
||||
<ul>
|
||||
<li>Remove the extruder bowden tube from the output of the extruder (or remove the extruder assembly from the nozzle assembly if you have a direct-extruder)</li>
|
||||
<li>Put the filament through it (by hand or using the software control)</li>
|
||||
<li>Cut the filament flush with the output of the extruder. Measure with your spring-steel ruler that you measure just 0mm. If not, note the value and don't forget to remove it from every other measure you do.</li>
|
||||
<li>Ask your extruder to extrude 200mm of filament (gcode: G1 E200).</li>
|
||||
<li>Measure the length o the extruded filament. Repeat this process two times more if you want to be more precise.</li>
|
||||
<li>You have to change your extruder multiplier (estep, step_distance) by multipliying (or dividing, depending on your firmware) the current value by (200 / average_measured_value).</li>
|
||||
<p>Note that this value may change if you change the pressure the extuder exerce against the filament.</p>
|
||||
</ul>
|
||||
<h2>Notes</h2>
|
||||
<p>It's very difficult to tune the flow below the 2% mark, and no filament is consistent enought to warrant it anyway. A filament that have a guarantee of +-0,03mm have a ~7% variation between the low and high end cross section.</p>
|
||||
<p>Most of the calibrations need to done is the right order. This one should be the second.</p>
|
||||
<p>You may want to re-do the bed level calibration is the result is below 0.9 or higher than 1.1.</p>
|
||||
<p>Note that the filament extrusion multipler can change with a different filament material, as a softer one can be squished/dented more by the extruder and so have a lower diameter in the extruder gears.</p>
|
||||
<p>If your printer extruder eat the filament and can't complete the top layer, you have to increase the ironing distribution (by 5% increment). (Expert seting, print -> infill)</p>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
resources/calibration/filament_flow/filament_flow_test_cube.amf
Normal file
BIN
resources/calibration/filament_flow/m10.amf
Normal file
BIN
resources/calibration/filament_flow/m10.jpg
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
resources/calibration/filament_flow/m2.amf
Normal file
BIN
resources/calibration/filament_flow/m20.amf
Normal file
BIN
resources/calibration/filament_flow/m20.jpg
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
resources/calibration/filament_flow/m4.amf
Normal file
BIN
resources/calibration/filament_flow/m6.amf
Normal file
BIN
resources/calibration/filament_flow/m8.amf
Normal file
BIN
resources/calibration/filament_flow/p10.amf
Normal file
BIN
resources/calibration/filament_flow/p10.jpg
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
resources/calibration/filament_flow/p20.amf
Normal file
BIN
resources/calibration/filament_flow/p20.jpg
Normal file
After Width: | Height: | Size: 4.9 KiB |
59
resources/calibration/filament_temp/filament_temp.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Filament temperature calibration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Filament flow calibration</h1>
|
||||
<p>You need to do the bed level calibration before this one.</p>
|
||||
<p>This test will print five tests samples with various level of flow. You can choose the flow difference between each steps. You should start with the 10% one. After verifying the result with the help of the tabel below, you have to modify the filamant extrusion multiplier in your filament preset (if the -20 is the best, change the multiplier from 1 to 0.8, see the formula below). Don't forget to save it afterwards. You can continue with the 2.5 step if you want a bit more precision.</p>
|
||||
<h2>Results</h2>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><img src="./low_ll.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./low_l.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./low.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./good.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high_h.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
<td><img src="./high_hh.jpg" alt="too low, by far" width="100" height="200" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">not enough flow</td>
|
||||
<td style="text-align: center;">Too far</td>
|
||||
<td style="text-align: center;">Too far:<br />You can spot<br />a little gap</td>
|
||||
<td style="text-align: center;">ok</td>
|
||||
<td style="text-align: center;">ok</td>
|
||||
<td style="text-align: center;">Trap!<br />It's too near:<br />check the thickness<br />of the patch!</td>
|
||||
<td style="text-align: center;">Far too near.<br />Dangerous<br />for the bed</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>The flow you want to choose is the lowest that don't create gaps in the top surface.</p>
|
||||
<h2>How to tune your printer</h2>
|
||||
<p>You have to change the extrusion multiplier for the filament you calibrate for (and save it). Formula for the new extrusion multipler: new_multiplier = ( (100 + choosen_number) / 100 ) * old_multiplier<br />
|
||||
Exemple: first step, i choose the -10, so i have ((100-10)/100) * 1 = (0.9) * 1 = 0.9<br />
|
||||
second step i chooe +5, so i have ((100+5)/100) * 0.9 = (1.05) * 0.9 = 0.945
|
||||
</p>
|
||||
<p>If you want to make this change permanent and left your extrusion multipler to 1 in slic3r++, you can change your firmware configuration by mutiplying (or dividing, depends of the firmware/setting) the 'extruder speed setting' (e-step, step_distance) by this extrusion multipler.</p>
|
||||
<h2>Advice</h2>
|
||||
<p>Before doing this test, it's preferable to calibrate your extruder (it's easier on bowden setup):</p>
|
||||
<ul>
|
||||
<li>Remove the extruder bowden tube from the output of the extruder (or remove the extruder assembly from the nozzle assembly if you have a direct-extruder)</li>
|
||||
<li>Put the filament through it (by hand or using the software control)</li>
|
||||
<li>Cut the filament flush with the output of the extruder. Measure with your spring-steel ruler that you measure just 0mm. If not, note the value and don't forget to remove it from every other measure you do.</li>
|
||||
<li>Ask your extruder to extrude 200mm of filament (gcode: G1 E200).</li>
|
||||
<li>Measure the length o the extruded filament. Repeat this process two times more if you want to be more precise.</li>
|
||||
<li>You have to change your extruder multiplier (estep, step_distance) by multipliying (or dividing, depending on your firmware) the current value by (200 / average_measured_value).</li>
|
||||
<p>Note that this value may change if you change the pressure the extuder exerce against the filament.</p>
|
||||
</ul>
|
||||
<h2>Notes</h2>
|
||||
<p>It's very difficult to tune the flow below the 2% mark, and no filament is consistent enought to warrant it anyway. A filament that have a guarantee of +-0,03mm have a ~7% variation between the low and high end cross section.</p>
|
||||
<p>Most of the calibrations need to done is the right order. This one should be the second.</p>
|
||||
<p>You may want to re-do the bed level calibration is the result is below 0.9 or higher than 1.1.</p>
|
||||
<p>Note that the filament extrusion multipler can change with a different filament material, as a softer one can be squished/dented more by the extruder and so have a lower diameter in the extruder gears.</p>
|
||||
<p>If your printer extruder eat the filament and can't complete the top layer, you have to increase the ironing distribution (by 5% increment). (Expert seting, print -> infill)</p>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
resources/calibration/filament_temp/overhang_test.amf
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Document HTML</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>hello you</h1>
|
||||
bonjour le monde
|
||||
|
||||
</body>
|
||||
</html>
|
@ -125,7 +125,7 @@ group:sidetext_width$3:Advanced
|
||||
setting:infill_first
|
||||
group:Advanced Infill
|
||||
line:Ironing tuning
|
||||
setting:label_width$6:width$5:fill_smooth_width
|
||||
setting:label_width$6:width$5:sidetext_width$7:fill_smooth_width
|
||||
setting:label_width$9:width$5:fill_smooth_distribution
|
||||
end_line
|
||||
|
||||
@ -157,16 +157,16 @@ group:Raft
|
||||
setting:raft_layers
|
||||
group:Options for support material and raft
|
||||
line:Z-offset
|
||||
setting:support_material_contact_distance_type
|
||||
setting:support_material_contact_distance_top
|
||||
setting:support_material_contact_distance_bottom
|
||||
setting:width$12:support_material_contact_distance_type
|
||||
setting:width$6:support_material_contact_distance_top
|
||||
setting:width$6:support_material_contact_distance_bottom
|
||||
end_line
|
||||
setting:support_material_pattern
|
||||
setting:support_material_with_sheath
|
||||
setting:support_material_spacing
|
||||
setting:support_material_angle
|
||||
setting:support_material_buildplate_only
|
||||
setting:support_material_xy_spacing
|
||||
setting:sidetext_width$7:support_material_xy_spacing
|
||||
setting:dont_support_bridges
|
||||
setting:support_material_synchronize_layers
|
||||
group:Options for support material interface
|
||||
|
@ -215,7 +215,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
|
||||
if (surface.has_fill_solid()) {
|
||||
density = 100.;
|
||||
fill_pattern = ipRectilinear;
|
||||
fill_pattern = ipRectilinearWGapFill;
|
||||
if (surface.has_pos_external() && !is_bridge)
|
||||
fill_pattern = surface.has_pos_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value;
|
||||
else if (!is_bridge)
|
||||
|
@ -48,7 +48,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
||||
case ipSmoothHilbert: return new FillSmoothHilbert();
|
||||
case ipRectiWithPerimeter: return new FillRectilinear2Peri();
|
||||
case ipSawtooth: return new FillRectilinearSawtooth();
|
||||
default: throw std::invalid_argument("unknown type");
|
||||
default: throw std::invalid_argument("unknown type : "+type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2821,7 +2821,9 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
|
||||
}
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm_per_height = m_writer.extruder()->e_per_mm3() * path->mm3_per_mm / this->m_layer->height;
|
||||
double e_per_mm_per_height = (path->mm3_per_mm / this->m_layer->height)
|
||||
* m_writer.extruder()->e_per_mm3()
|
||||
* this->config().print_extrusion_multiplier.get_abs_value(1);
|
||||
if (m_writer.extrusion_axis().empty()) e_per_mm_per_height = 0;
|
||||
{
|
||||
std::string comment = m_config.gcode_comments ? description : "";
|
||||
@ -3322,7 +3324,9 @@ std::string GCode::extrude_multi_path3D(const ExtrusionMultiPath3D &multipath3D,
|
||||
gcode += this->_before_extrude(path, description, speed);
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm = m_writer.extruder()->e_per_mm3() * path.mm3_per_mm;
|
||||
double e_per_mm = path.mm3_per_mm
|
||||
* m_writer.extruder()->e_per_mm3()
|
||||
* this->config().print_extrusion_multiplier.get_abs_value(1);
|
||||
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
|
||||
double path_length = 0.;
|
||||
{
|
||||
@ -3389,7 +3393,9 @@ std::string GCode::extrude_path_3D(const ExtrusionPath3D &path, const std::strin
|
||||
std::string gcode = this->_before_extrude(path, description, speed);
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm = m_writer.extruder()->e_per_mm3() * path.mm3_per_mm;
|
||||
double e_per_mm = path.mm3_per_mm
|
||||
* m_writer.extruder()->e_per_mm3()
|
||||
* this->config().print_extrusion_multiplier.get_abs_value(1);
|
||||
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
|
||||
double path_length = 0.;
|
||||
{
|
||||
@ -3548,7 +3554,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
|
||||
std::string gcode = this->_before_extrude(path, description, speed);
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm = m_writer.extruder()->e_per_mm3() * path.mm3_per_mm;
|
||||
double e_per_mm = path.mm3_per_mm
|
||||
* m_writer.extruder()->e_per_mm3()
|
||||
* this->config().print_extrusion_multiplier.get_abs_value(1);
|
||||
if (this->m_layer_index <= 0) e_per_mm *= this->config().first_layer_flow_ratio.get_abs_value(1);
|
||||
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
|
||||
double path_length = 0.;
|
||||
|
@ -873,12 +873,25 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Extrusion multiplier");
|
||||
def->category = OptionCategory::filament;
|
||||
def->tooltip = L("This factor changes the amount of flow proportionally. You may need to tweak "
|
||||
"this setting to get nice surface finish and correct single wall widths. "
|
||||
"Usual values are between 0.9 and 1.1. If you think you need to change this more, "
|
||||
"check filament diameter and your firmware E steps.");
|
||||
"this setting to get nice surface finish and correct single wall widths. "
|
||||
"Usual values are between 0.9 and 1.1. If you think you need to change this more, "
|
||||
"check filament diameter and your firmware E steps.");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloats { 1. });
|
||||
|
||||
def = this->add("print_extrusion_multiplier", coPercent);
|
||||
def->label = L("Extrusion multiplier");
|
||||
def->category = OptionCategory::width;
|
||||
def->tooltip = L("This factor changes the amount of flow proportionally. You may need to tweak "
|
||||
"this setting to get nice surface finish and correct single wall widths. "
|
||||
"Usual values are between 0.9 and 1.1. If you think you need to change this more, "
|
||||
"check filament diameter and your firmware E steps."
|
||||
" This print setting is multiplied against the extrusion_multiplier from the filament tab."
|
||||
" Its only purpose is to offer the same functionality but with a per-object basis.");
|
||||
def->mode = comSimple;
|
||||
def->min = 2;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
def = this->add("extrusion_width", coFloatOrPercent);
|
||||
def->label = L("Default extrusion width");
|
||||
def->category = OptionCategory::width;
|
||||
@ -1720,7 +1733,7 @@ void PrintConfigDef::init_fff_params()
|
||||
" It assume infinite acceleration for this time estimation, and only takes into account G1 and G0 moves. Use 0 to deactivate, negative to remove the 'D' option.");
|
||||
def->sidetext = L("s");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
def->set_default_value(new ConfigOptionFloat(-1));
|
||||
|
||||
{
|
||||
struct AxisDefault {
|
||||
|
@ -631,6 +631,7 @@ public:
|
||||
ConfigOptionFloat perimeter_speed;
|
||||
// Total number of perimeters.
|
||||
ConfigOptionInt perimeters;
|
||||
ConfigOptionPercent print_extrusion_multiplier;
|
||||
ConfigOptionFloatOrPercent small_perimeter_speed;
|
||||
ConfigOptionEnum<InfillPattern> solid_fill_pattern;
|
||||
ConfigOptionFloat solid_infill_below_area;
|
||||
@ -710,6 +711,7 @@ protected:
|
||||
OPT_PTR(perimeter_loop_seam);
|
||||
OPT_PTR(perimeter_speed);
|
||||
OPT_PTR(perimeters);
|
||||
OPT_PTR(print_extrusion_multiplier);
|
||||
OPT_PTR(small_perimeter_speed);
|
||||
OPT_PTR(solid_fill_pattern);
|
||||
OPT_PTR(solid_infill_below_area);
|
||||
|
@ -18,6 +18,14 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/BackgroundSlicingProcess.hpp
|
||||
GUI/BitmapCache.cpp
|
||||
GUI/BitmapCache.hpp
|
||||
GUI/CalibrationBedDialog.cpp
|
||||
GUI/CalibrationBedDialog.hpp
|
||||
GUI/CalibrationBridgeDialog.cpp
|
||||
GUI/CalibrationBridgeDialog.hpp
|
||||
GUI/CalibrationFlowDialog.cpp
|
||||
GUI/CalibrationFlowDialog.hpp
|
||||
GUI/CalibrationTempDialog.cpp
|
||||
GUI/CalibrationTempDialog.hpp
|
||||
GUI/ConfigSnapshotDialog.cpp
|
||||
GUI/ConfigSnapshotDialog.hpp
|
||||
GUI/3DScene.cpp
|
||||
|
@ -163,8 +163,8 @@ void GLIndexedVertexArray::render(
|
||||
const std::pair<size_t, size_t>& tverts_range,
|
||||
const std::pair<size_t, size_t>& qverts_range) const
|
||||
{
|
||||
assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||
// assert(this->vertices_and_normals_interleaved_VBO_id != 0);
|
||||
// assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
|
||||
|
||||
// Render using the Vertex Buffer Objects.
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
|
||||
|
216
src/slic3r/GUI/CalibrationBedDialog.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
#include "CalibrationBedDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "tab.hpp"
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/file.h>
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#if ENABLE_SCROLLABLE
|
||||
static wxSize get_screen_size(wxWindow* window)
|
||||
{
|
||||
const auto idx = wxDisplay::GetFromWindow(window);
|
||||
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
|
||||
return display.GetClientArea().GetSize();
|
||||
}
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
CalibrationBedDialog::CalibrationBedDialog(GUI_App* app, MainFrame* mainframe)
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Bed calibration - test objects generation")),
|
||||
#if ENABLE_SCROLLABLE
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
{
|
||||
this->gui_app = app;
|
||||
this->main_frame = mainframe;
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
||||
// fonts
|
||||
const wxFont& font = wxGetApp().normal_font();
|
||||
const wxFont& bold_font = wxGetApp().bold_font();
|
||||
SetFont(font);
|
||||
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//html
|
||||
std::cout << "display test.html\n";
|
||||
html_viewer = new wxHtmlWindow(this, wxID_ANY,
|
||||
wxDefaultPosition, wxSize(800, 500), wxHW_SCROLLBAR_AUTO);
|
||||
html_viewer->LoadPage("./resources/calibration/bed_leveling/bed_leveling.html");
|
||||
main_sizer->Add(html_viewer, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
wxStdDialogButtonSizer* buttons = new wxStdDialogButtonSizer();
|
||||
wxButton* bt = new wxButton(this, wxID_FILE1, _(L("Generate")));
|
||||
bt->Bind(wxEVT_BUTTON, &CalibrationBedDialog::create_geometry, this);
|
||||
buttons->Add(bt);
|
||||
wxButton* close = new wxButton(this, wxID_CLOSE, _(L("Close")));
|
||||
close->Bind(wxEVT_BUTTON, &CalibrationBedDialog::closeMe, this);
|
||||
buttons->AddButton(close);
|
||||
close->SetDefault();
|
||||
close->SetFocus();
|
||||
SetAffirmativeId(wxID_CLOSE);
|
||||
buttons->Realize();
|
||||
main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
void CalibrationBedDialog::closeMe(wxCommandEvent& event_args) {
|
||||
gui_app->delete_calibration_dialog();
|
||||
}
|
||||
|
||||
void CalibrationBedDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
Plater* plat = this->main_frame->plater();
|
||||
Model& model = plat->model();
|
||||
plat->reset();
|
||||
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf"}, true, false);
|
||||
|
||||
assert(objs_idx.size() == 5);
|
||||
const DynamicPrintConfig* printConfig = this->gui_app->get_tab(Preset::TYPE_PRINT)->get_config();
|
||||
const DynamicPrintConfig* printerConfig = this->gui_app->get_tab(Preset::TYPE_PRINTER)->get_config();
|
||||
|
||||
/// --- scale ---
|
||||
//model is created for a 0.4 nozzle, scale xy with nozzle size.
|
||||
const ConfigOptionFloats* nozzle_diameter = printerConfig->option<ConfigOptionFloats>("nozzle_diameter");
|
||||
assert(nozzle_diameter->values.size() > 0);
|
||||
float xyScale = nozzle_diameter->values[0] / 0.4;
|
||||
//scale z with the first_layer_height
|
||||
const ConfigOptionFloatOrPercent* first_layer_height = printConfig->option<ConfigOptionFloatOrPercent>("first_layer_height");
|
||||
float zscale = first_layer_height->get_abs_value(nozzle_diameter->values[0]) / 0.2;
|
||||
//do scaling
|
||||
if (xyScale < 0.9 || 1.2 < xyScale) {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(xyScale, xyScale, zscale);
|
||||
} else {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(1, 1, zscale);
|
||||
}
|
||||
|
||||
/// --- rotate ---
|
||||
const ConfigOptionPoints* bed_shape = printerConfig->option<ConfigOptionPoints>("bed_shape");
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->rotate(PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[1]]->rotate(5 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[3]]->rotate(3 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(7 * PI / 4, { 0,0,1 });
|
||||
} else {
|
||||
model.objects[objs_idx[3]]->rotate(PI / 2, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(PI / 2, { 0,0,1 });
|
||||
}
|
||||
|
||||
/// --- translate ---
|
||||
//three first will stay with this orientation (top left, middle, bottom right)
|
||||
//last two with 90deg (top left, middle, bottom right)
|
||||
//get position for patches
|
||||
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
|
||||
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
|
||||
float offsetx = 10 + 10 * xyScale;
|
||||
float offsety = 10 + 10 * xyScale;
|
||||
if (bed_shape->values.size() > 4) {
|
||||
offsetx = bed_size.x() / 2 - bed_size.x() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
offsety = bed_size.y() / 2 - bed_size.y() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
}
|
||||
bool large_enough = bed_shape->values.size() == 4 ?
|
||||
(bed_size.x() > offsetx * 3 && bed_size.y() > offsety * 3) :
|
||||
(bed_size.x() > offsetx * 2 + 10 * xyScale && bed_size.y() > offsety * 2 + 10 * xyScale);
|
||||
if (!large_enough){
|
||||
//problem : too small, use arrange instead and let the user place them.
|
||||
plat->arrange();
|
||||
//TODO add message
|
||||
} else {
|
||||
model.objects[objs_idx[0]]->translate({ bed_min.x() + offsetx, bed_min.y() + bed_size.y() - offsety,0 });
|
||||
model.objects[objs_idx[1]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + offsety , 0 });
|
||||
model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x()/2, bed_min.y() + bed_size.y() / 2, 0 });
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + offsetx, bed_min.y() + offsety, 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + bed_size.y() - offsety,0 });
|
||||
}
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *printConfig; //make a copy
|
||||
new_print_config.set_key_value("complete_objects", new ConfigOptionBool(true));
|
||||
new_print_config.set_key_value("skirts", new ConfigOptionInt(2));
|
||||
|
||||
/// --- custom config ---
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
model.objects[objs_idx[i]]->config.set_key_value("perimeters", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_solid_layers", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(140, true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinearWGapFill));
|
||||
}
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[1]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[2]]->config.set_key_value("fill_angle", new ConfigOptionFloat(45));
|
||||
model.objects[objs_idx[3]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
model.objects[objs_idx[4]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
} else {
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t i = 3; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->config.set_key_value("fill_angle", new ConfigOptionFloat(135));
|
||||
}
|
||||
|
||||
//update plater
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config);
|
||||
plat->on_config_change(new_print_config);
|
||||
plat->changed_objects(objs_idx);
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->update_dirty();
|
||||
//update everything, easier to code.
|
||||
this->gui_app->obj_list()->update_after_undo_redo();
|
||||
//if(!plat->is_background_process_update_scheduled())
|
||||
// plat->schedule_background_process();
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
|
||||
}
|
||||
|
||||
void CalibrationBedDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
msw_buttons_rescale(this, em_unit(), { wxID_OK });
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
wxPanel* CalibrationBedDialog::create_header(wxWindow* parent, const wxFont& bold_font)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxFont header_font = bold_font;
|
||||
#ifdef __WXOSX__
|
||||
header_font.SetPointSize(14);
|
||||
#else
|
||||
header_font.SetPointSize(bold_font.GetPointSize() + 2);
|
||||
#endif // __WXOSX__
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
// text
|
||||
wxStaticText* text = new wxStaticText(panel, wxID_ANY, _(L("Keyboard shortcuts")));
|
||||
text->SetFont(header_font);
|
||||
sizer->Add(text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
panel->SetSizer(sizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
41
src/slic3r/GUI/CalibrationBedDialog.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef slic3r_GUI_CalibrationBedDialog_hpp_
|
||||
#define slic3r_GUI_CalibrationBedDialog_hpp_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include <wx/html/htmlwin.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class CalibrationBedDialog : public DPIDialog
|
||||
{
|
||||
|
||||
public:
|
||||
CalibrationBedDialog(GUI_App* app, MainFrame* mainframe);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
|
||||
void closeMe(wxCommandEvent& event_args);
|
||||
void create_geometry(wxCommandEvent& event_args);
|
||||
wxPanel* create_header(wxWindow* parent, const wxFont& bold_font);
|
||||
|
||||
wxHtmlWindow* html_viewer;
|
||||
MainFrame* main_frame;
|
||||
GUI_App* gui_app;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
196
src/slic3r/GUI/CalibrationBridgeDialog.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "CalibrationBridgeDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "tab.hpp"
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/file.h>
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#if ENABLE_SCROLLABLE
|
||||
static wxSize get_screen_size(wxWindow* window)
|
||||
{
|
||||
const auto idx = wxDisplay::GetFromWindow(window);
|
||||
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
|
||||
return display.GetClientArea().GetSize();
|
||||
}
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
CalibrationBridgeDialog::CalibrationBridgeDialog(GUI_App* app, MainFrame* mainframe)
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Bridge calibration - test objects generation")),
|
||||
#if ENABLE_SCROLLABLE
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
{
|
||||
this->gui_app = app;
|
||||
this->main_frame = mainframe;
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
||||
// fonts
|
||||
const wxFont& font = wxGetApp().normal_font();
|
||||
const wxFont& bold_font = wxGetApp().bold_font();
|
||||
SetFont(font);
|
||||
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//html
|
||||
std::cout << "display test.html\n";
|
||||
html_viewer = new wxHtmlWindow(this, wxID_ANY,
|
||||
wxDefaultPosition, wxSize(400, 400), wxHW_SCROLLBAR_AUTO);
|
||||
html_viewer->LoadPage("./resources/calibration/bed_leveling/bed_leveling.html");
|
||||
main_sizer->Add(html_viewer, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxAPPLY| wxCLOSE);
|
||||
buttons->GetApplyButton()->Bind(wxEVT_BUTTON, &CalibrationBridgeDialog::create_geometry, this);
|
||||
this->SetEscapeId(wxCLOSE);
|
||||
main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
void CalibrationBridgeDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
Plater* plat = this->main_frame->plater();
|
||||
Model& model = plat->model();
|
||||
plat->reset();
|
||||
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf"}, true, false);
|
||||
|
||||
assert(objs_idx.size() == 5);
|
||||
const DynamicPrintConfig* printConfig = this->gui_app->get_tab(Preset::TYPE_PRINT)->get_config();
|
||||
const DynamicPrintConfig* printerConfig = this->gui_app->get_tab(Preset::TYPE_PRINTER)->get_config();
|
||||
|
||||
/// --- scale ---
|
||||
//model is created for a 0.4 nozzle, scale xy with nozzle size.
|
||||
const ConfigOptionFloats* nozzle_diameter = printerConfig->option<ConfigOptionFloats>("nozzle_diameter");
|
||||
assert(nozzle_diameter->values.size() > 0);
|
||||
float xyScale = nozzle_diameter->values[0] / 0.4;
|
||||
//scale z with the first_layer_height
|
||||
const ConfigOptionFloatOrPercent* first_layer_height = printConfig->option<ConfigOptionFloatOrPercent>("first_layer_height");
|
||||
float zscale = first_layer_height->get_abs_value(nozzle_diameter->values[0]) / 0.2;
|
||||
//do scaling
|
||||
if (xyScale < 0.9 || 1.2 < xyScale) {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(xyScale, xyScale, zscale);
|
||||
}
|
||||
|
||||
/// --- rotate ---
|
||||
const ConfigOptionPoints* bed_shape = printerConfig->option<ConfigOptionPoints>("bed_shape");
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->rotate(PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[1]]->rotate(5 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[3]]->rotate(3 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(7 * PI / 4, { 0,0,1 });
|
||||
} else {
|
||||
model.objects[objs_idx[3]]->rotate(PI / 2, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(PI / 2, { 0,0,1 });
|
||||
}
|
||||
|
||||
/// --- translate ---
|
||||
//three first will stay with this orientation (top left, middle, bottom right)
|
||||
//last two with 90deg (top left, middle, bottom right)
|
||||
//get position for patches
|
||||
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
|
||||
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
|
||||
float offsetx = 10 + 10 * xyScale;
|
||||
float offsety = 10 + 10 * xyScale;
|
||||
if (bed_shape->values.size() > 4) {
|
||||
offsetx = bed_size.x() / 2 - bed_size.x() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
offsety = bed_size.y() / 2 - bed_size.y() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
}
|
||||
bool large_enough = bed_shape->values.size() == 4 ?
|
||||
(bed_size.x() > offsetx * 3 && bed_size.y() > offsety * 3) :
|
||||
(bed_size.x() > offsetx * 2 + 10 * xyScale && bed_size.y() > offsety * 2 + 10 * xyScale);
|
||||
if (!large_enough){
|
||||
//problem : too small, use arrange instead and let the user place them.
|
||||
model.arrange_objects(20);
|
||||
//TODO add message
|
||||
} else {
|
||||
model.objects[objs_idx[0]]->translate({ bed_min.x() + offsetx, bed_min.y() + bed_size.y() - offsety,0 });
|
||||
model.objects[objs_idx[1]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + offsety , 0 });
|
||||
model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x()/2, bed_min.y() + bed_size.y() / 2, 0 });
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + offsetx, bed_min.y() + offsety, 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + bed_size.y() - offsety,0 });
|
||||
}
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *printConfig; //make a copy
|
||||
new_print_config.set_key_value("complete_objects", new ConfigOptionBool(true));
|
||||
new_print_config.set_key_value("skirts", new ConfigOptionInt(0));
|
||||
|
||||
/// --- custom config ---
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
model.objects[objs_idx[i]]->config.set_key_value("perimeters", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_solid_layers", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(140, true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinearWGapFill));
|
||||
}
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[1]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[2]]->config.set_key_value("fill_angle", new ConfigOptionFloat(45));
|
||||
model.objects[objs_idx[3]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
model.objects[objs_idx[4]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
} else {
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t i = 3; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->config.set_key_value("fill_angle", new ConfigOptionFloat(135));
|
||||
}
|
||||
|
||||
//update plater
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config);
|
||||
plat->on_config_change(new_print_config);
|
||||
plat->changed_objects(objs_idx);
|
||||
//if(!plat->is_background_process_update_scheduled())
|
||||
// plat->schedule_background_process();
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
}
|
||||
|
||||
void CalibrationBridgeDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
msw_buttons_rescale(this, em_unit(), { wxID_OK });
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
wxPanel* CalibrationBridgeDialog::create_header(wxWindow* parent, const wxFont& bold_font)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxFont header_font = bold_font;
|
||||
#ifdef __WXOSX__
|
||||
header_font.SetPointSize(14);
|
||||
#else
|
||||
header_font.SetPointSize(bold_font.GetPointSize() + 2);
|
||||
#endif // __WXOSX__
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
// text
|
||||
wxStaticText* text = new wxStaticText(panel, wxID_ANY, _(L("Keyboard shortcuts")));
|
||||
text->SetFont(header_font);
|
||||
sizer->Add(text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
panel->SetSizer(sizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
39
src/slic3r/GUI/CalibrationBridgeDialog.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef slic3r_GUI_CalibrationBridgeDialog_hpp_
|
||||
#define slic3r_GUI_CalibrationBridgeDialog_hpp_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include <wx/html/htmlwin.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class CalibrationBridgeDialog : public DPIDialog
|
||||
{
|
||||
|
||||
public:
|
||||
CalibrationBridgeDialog(GUI_App* app, MainFrame* mainframe);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
void create_geometry(wxCommandEvent& event_args);
|
||||
wxPanel* create_header(wxWindow* parent, const wxFont& bold_font);
|
||||
|
||||
wxHtmlWindow* html_viewer;
|
||||
MainFrame* main_frame;
|
||||
GUI_App* gui_app;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
272
src/slic3r/GUI/CalibrationFlowDialog.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
#include "CalibrationFlowDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "GLCanvas3D.hpp "
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "tab.hpp"
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/file.h>
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#if ENABLE_SCROLLABLE
|
||||
static wxSize get_screen_size(wxWindow* window)
|
||||
{
|
||||
const auto idx = wxDisplay::GetFromWindow(window);
|
||||
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
|
||||
return display.GetClientArea().GetSize();
|
||||
}
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
CalibrationFlowDialog::CalibrationFlowDialog(GUI_App* app, MainFrame* mainframe)
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Flow calibration - test objects generation")),
|
||||
#if ENABLE_SCROLLABLE
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
{
|
||||
this->gui_app = app;
|
||||
this->main_frame = mainframe;
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
||||
// fonts
|
||||
const wxFont& font = wxGetApp().normal_font();
|
||||
const wxFont& bold_font = wxGetApp().bold_font();
|
||||
SetFont(font);
|
||||
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//html
|
||||
html_viewer = new wxHtmlWindow(this, wxID_ANY,
|
||||
wxDefaultPosition, wxSize(600, 500), wxHW_SCROLLBAR_AUTO);
|
||||
html_viewer->SetMinSize(wxSize(1000, 500));
|
||||
html_viewer->LoadPage("./resources/calibration/filament_flow/filament_flow.html");
|
||||
main_sizer->Add(html_viewer, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
wxStdDialogButtonSizer* buttons = new wxStdDialogButtonSizer();
|
||||
wxButton* bt = new wxButton(this, wxID_FILE1, _(L("Generate 10% intervals")));
|
||||
bt->Bind(wxEVT_BUTTON, &CalibrationFlowDialog::create_geometry_10, this);
|
||||
buttons->Add(bt);
|
||||
bt = new wxButton(this, wxID_FILE2, _(L("Generate 2.5% intervals")));
|
||||
bt->Bind(wxEVT_BUTTON, &CalibrationFlowDialog::create_geometry_2_5, this);
|
||||
buttons->Add(bt);
|
||||
wxButton* close = new wxButton(this, wxID_CLOSE, _(L("Close")));
|
||||
close->Bind(wxEVT_BUTTON, &CalibrationFlowDialog::closeMe, this);
|
||||
buttons->AddButton(close);
|
||||
close->SetDefault();
|
||||
close->SetFocus();
|
||||
SetAffirmativeId(wxID_CLOSE);
|
||||
buttons->Realize();
|
||||
main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
|
||||
this->SetEscapeId(wxCLOSE);
|
||||
this->SetAffirmativeId(wxCLOSE);
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::closeMe(wxCommandEvent& event_args) {
|
||||
gui_app->delete_calibration_dialog();
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::create_geometry_10(wxCommandEvent& event_args) {
|
||||
create_geometry(80.f, 10.f);
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::create_geometry_2_5(wxCommandEvent& event_args) {
|
||||
create_geometry(92.f, 2.F);
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::add_part(ModelObject* model_object, std::string input_file, Vec3d move, Vec3d scale) {
|
||||
Model model;
|
||||
try {
|
||||
model = Model::read_from_file(input_file);
|
||||
}
|
||||
catch (std::exception & e) {
|
||||
auto msg = _(L("Error!")) + " " + input_file + " : " + e.what() + ".";
|
||||
show_error(this, msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (ModelObject *object : model.objects) {
|
||||
Vec3d delta = Vec3d::Zero();
|
||||
if (model_object->origin_translation != Vec3d::Zero())
|
||||
{
|
||||
object->center_around_origin();
|
||||
delta = model_object->origin_translation - object->origin_translation;
|
||||
}
|
||||
for (ModelVolume *volume : object->volumes) {
|
||||
volume->translate(delta + move);
|
||||
if (scale != Vec3d{ 1,1,1 })
|
||||
volume->scale(scale);
|
||||
ModelVolume* new_volume = model_object->add_volume(*volume);
|
||||
new_volume->set_type(ModelVolumeType::MODEL_PART);
|
||||
new_volume->name = boost::filesystem::path(input_file).filename().string();
|
||||
|
||||
//volumes_info.push_back(std::make_pair(from_u8(new_volume->name), new_volume->get_mesh_errors_count() > 0));
|
||||
|
||||
// set a default extruder value, since user can't add it manually
|
||||
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||
|
||||
//move to bed
|
||||
/* const TriangleMesh& hull = new_volume->get_convex_hull();
|
||||
float min_z = std::numeric_limits<float>::max();
|
||||
for (const stl_facet& facet : hull.stl.facet_start) {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
min_z = std::min(min_z, Vec3f::UnitZ().dot(facet.vertex[i]));
|
||||
}
|
||||
volume->translate(Vec3d(0,0,-min_z));*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::create_geometry(float start, float delta) {
|
||||
Plater* plat = this->main_frame->plater();
|
||||
Model& model = plat->model();
|
||||
plat->reset();
|
||||
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
|
||||
"./resources/calibration/filament_flow/filament_flow_test_cube.amf",
|
||||
"./resources/calibration/filament_flow/filament_flow_test_cube.amf",
|
||||
"./resources/calibration/filament_flow/filament_flow_test_cube.amf",
|
||||
"./resources/calibration/filament_flow/filament_flow_test_cube.amf",
|
||||
"./resources/calibration/filament_flow/filament_flow_test_cube.amf"}, true, false);
|
||||
|
||||
|
||||
assert(objs_idx.size() == 5);
|
||||
const DynamicPrintConfig* printConfig = this->gui_app->get_tab(Preset::TYPE_PRINT)->get_config();
|
||||
const DynamicPrintConfig* printerConfig = this->gui_app->get_tab(Preset::TYPE_PRINTER)->get_config();
|
||||
|
||||
/// --- scale ---
|
||||
// model is created for a 0.4 nozzle, scale xy with nozzle size.
|
||||
const ConfigOptionFloats* nozzle_diameter = printerConfig->option<ConfigOptionFloats>("nozzle_diameter");
|
||||
assert(nozzle_diameter->values.size() > 0);
|
||||
float xyScale = nozzle_diameter->values[0] / 0.4;
|
||||
//scale z to have 6 layers
|
||||
const ConfigOptionFloatOrPercent* first_layer_height = printConfig->option<ConfigOptionFloatOrPercent>("first_layer_height");
|
||||
const ConfigOptionFloat* layer_height = printConfig->option<ConfigOptionFloat>("layer_height");
|
||||
float zscale = first_layer_height->get_abs_value(nozzle_diameter->values[0]) + 5 * layer_height->value;
|
||||
zscale *= (1 + 0.3 * (10. / delta));
|
||||
//do scaling
|
||||
if (xyScale < 0.9 || 1.2 < xyScale) {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(xyScale, xyScale, zscale);
|
||||
} else {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(1, 1, zscale);
|
||||
}
|
||||
|
||||
//add sub-part after scale
|
||||
float zshift = (1 - zscale) / 2;
|
||||
if (delta == 10.f && start == 80.f) {
|
||||
add_part(model.objects[objs_idx[0]], "./resources/calibration/filament_flow/m20.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[1]], "./resources/calibration/filament_flow/m10.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[2]], "./resources/calibration/filament_flow/_0.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[3]], "./resources/calibration/filament_flow/p10.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[4]], "./resources/calibration/filament_flow/p20.amf", Vec3d{ 9,0,zshift });
|
||||
} else if (delta == 2.f && start == 92.f) {
|
||||
add_part(model.objects[objs_idx[0]], "./resources/calibration/filament_flow/m8.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[1]], "./resources/calibration/filament_flow/m6.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[2]], "./resources/calibration/filament_flow/m4.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[3]], "./resources/calibration/filament_flow/m2.amf", Vec3d{ 9,0,zshift });
|
||||
add_part(model.objects[objs_idx[4]], "./resources/calibration/filament_flow/_0.amf", Vec3d{ 9,0,zshift });
|
||||
}
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
add_part(model.objects[objs_idx[i]], "./resources/calibration/filament_flow/O.amf", Vec3d{ 0,0,zscale/2.f + 0.5 }, Vec3d{1,1,xyScale });
|
||||
}
|
||||
|
||||
/// --- translate ---;
|
||||
const ConfigOptionFloat* extruder_clearance_radius = printConfig->option<ConfigOptionFloat>("extruder_clearance_radius");
|
||||
const ConfigOptionPoints* bed_shape = printerConfig->option<ConfigOptionPoints>("bed_shape");
|
||||
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
|
||||
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
|
||||
float offsetx = 5 + extruder_clearance_radius->value + 10 * xyScale;
|
||||
float offsety = 5 + extruder_clearance_radius->value + 10 * xyScale;
|
||||
model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2 - offsetx, bed_min.y() + bed_size.y() / 2 - offsety * 1.5, 0 });
|
||||
model.objects[objs_idx[1]]->translate({ bed_min.x() + bed_size.x() / 2 - offsetx, bed_min.y() + bed_size.y() / 2 , 0 });
|
||||
model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x() / 2 - offsetx, bed_min.y() + bed_size.y() / 2 + offsety * 1.5, 0 });
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx, bed_min.y() + bed_size.y() / 2 - offsety , 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx, bed_min.y() + bed_size.y() / 2 + offsety , 0 });
|
||||
//TODO: if not enough space, forget about complete_objects
|
||||
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *printConfig; //make a copy
|
||||
new_print_config.set_key_value("complete_objects", new ConfigOptionBool(true));
|
||||
|
||||
/// --- custom config ---
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
model.objects[objs_idx[i]]->config.set_key_value("brim_width", new ConfigOptionFloat(nozzle_diameter->values[0] * 3));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("brim_ears", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("perimeters", new ConfigOptionInt(3));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("only_one_perimeter_top", new ConfigOptionBool(true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("enforce_full_fill_volume", new ConfigOptionBool(true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_solid_layers", new ConfigOptionInt(5));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("top_solid_layers", new ConfigOptionInt(100));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("thin_walls", new ConfigOptionBool(true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("thin_walls_min_width", new ConfigOptionFloatOrPercent(50,true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("layer_height", new ConfigOptionFloat(nozzle_diameter->values[0]/2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(nozzle_diameter->values[0] / 2, false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("external_infill_margin", new ConfigOptionFloatOrPercent(100, true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("solid_fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinearWGapFill));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("top_fill_pattern", new ConfigOptionEnum<InfillPattern>(ipSmooth));
|
||||
//set extrusion mult : 80 90 100 110 120
|
||||
model.objects[objs_idx[i]]->config.set_key_value("print_extrusion_multiplier", new ConfigOptionPercent(start + (float)i * delta));
|
||||
}
|
||||
|
||||
//update plater
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config);
|
||||
plat->on_config_change(new_print_config);
|
||||
plat->changed_objects(objs_idx);
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->update_dirty();
|
||||
//update everything, easier to code.
|
||||
ObjectList* obj = this->gui_app->obj_list();
|
||||
obj->update_after_undo_redo();
|
||||
|
||||
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
}
|
||||
|
||||
void CalibrationFlowDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
msw_buttons_rescale(this, em_unit(), { wxID_OK });
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
wxPanel* CalibrationFlowDialog::create_header(wxWindow* parent, const wxFont& bold_font)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxFont header_font = bold_font;
|
||||
#ifdef __WXOSX__
|
||||
header_font.SetPointSize(14);
|
||||
#else
|
||||
header_font.SetPointSize(bold_font.GetPointSize() + 2);
|
||||
#endif // __WXOSX__
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
// text
|
||||
wxStaticText* text = new wxStaticText(panel, wxID_ANY, _(L("Keyboard shortcuts")));
|
||||
text->SetFont(header_font);
|
||||
sizer->Add(text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
panel->SetSizer(sizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
43
src/slic3r/GUI/CalibrationFlowDialog.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef slic3r_GUI_CalibrationFlowDialog_hpp_
|
||||
#define slic3r_GUI_CalibrationFlowDialog_hpp_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include <wx/html/htmlwin.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class CalibrationFlowDialog : public DPIDialog
|
||||
{
|
||||
|
||||
public:
|
||||
CalibrationFlowDialog(GUI_App* app, MainFrame* mainframe);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
void closeMe(wxCommandEvent& event_args);
|
||||
void create_geometry_10(wxCommandEvent& event_args);
|
||||
void create_geometry_2_5(wxCommandEvent& event_args);
|
||||
void add_part(ModelObject* model_object, std::string input_file, Vec3d move, Vec3d scale = Vec3d{ 1,1,1 });
|
||||
void create_geometry(float start, float delta);
|
||||
wxPanel* create_header(wxWindow* parent, const wxFont& bold_font);
|
||||
|
||||
wxHtmlWindow* html_viewer;
|
||||
MainFrame* main_frame;
|
||||
GUI_App* gui_app;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
196
src/slic3r/GUI/CalibrationTempDialog.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "CalibrationTempDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "tab.hpp"
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/file.h>
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#if ENABLE_SCROLLABLE
|
||||
static wxSize get_screen_size(wxWindow* window)
|
||||
{
|
||||
const auto idx = wxDisplay::GetFromWindow(window);
|
||||
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
|
||||
return display.GetClientArea().GetSize();
|
||||
}
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
CalibrationTempDialog::CalibrationTempDialog(GUI_App* app, MainFrame* mainframe)
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Temp calibration - test objects generation")),
|
||||
#if ENABLE_SCROLLABLE
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
|
||||
#endif // ENABLE_SCROLLABLE
|
||||
{
|
||||
this->gui_app = app;
|
||||
this->main_frame = mainframe;
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
||||
// fonts
|
||||
const wxFont& font = wxGetApp().normal_font();
|
||||
const wxFont& bold_font = wxGetApp().bold_font();
|
||||
SetFont(font);
|
||||
|
||||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//html
|
||||
std::cout << "display test.html\n";
|
||||
html_viewer = new wxHtmlWindow(this, wxID_ANY,
|
||||
wxDefaultPosition, wxSize(400, 400), wxHW_SCROLLBAR_AUTO);
|
||||
html_viewer->LoadPage("./resources/calibration/bed_leveling/bed_leveling.html");
|
||||
main_sizer->Add(html_viewer, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxAPPLY| wxCLOSE);
|
||||
buttons->GetApplyButton()->Bind(wxEVT_BUTTON, &CalibrationTempDialog::create_geometry, this);
|
||||
this->SetEscapeId(wxCLOSE);
|
||||
main_sizer->Add(buttons, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
void CalibrationTempDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
Plater* plat = this->main_frame->plater();
|
||||
Model& model = plat->model();
|
||||
plat->reset();
|
||||
std::vector<size_t> objs_idx = plat->load_files(std::vector<std::string>{
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf",
|
||||
"./resources/calibration/bed_leveling/patch.amf"}, true, false);
|
||||
|
||||
assert(objs_idx.size() == 5);
|
||||
const DynamicPrintConfig* printConfig = this->gui_app->get_tab(Preset::TYPE_PRINT)->get_config();
|
||||
const DynamicPrintConfig* printerConfig = this->gui_app->get_tab(Preset::TYPE_PRINTER)->get_config();
|
||||
|
||||
/// --- scale ---
|
||||
//model is created for a 0.4 nozzle, scale xy with nozzle size.
|
||||
const ConfigOptionFloats* nozzle_diameter = printerConfig->option<ConfigOptionFloats>("nozzle_diameter");
|
||||
assert(nozzle_diameter->values.size() > 0);
|
||||
float xyScale = nozzle_diameter->values[0] / 0.4;
|
||||
//scale z with the first_layer_height
|
||||
const ConfigOptionFloatOrPercent* first_layer_height = printConfig->option<ConfigOptionFloatOrPercent>("first_layer_height");
|
||||
float zscale = first_layer_height->get_abs_value(nozzle_diameter->values[0]) / 0.2;
|
||||
//do scaling
|
||||
if (xyScale < 0.9 || 1.2 < xyScale) {
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->scale(xyScale, xyScale, zscale);
|
||||
}
|
||||
|
||||
/// --- rotate ---
|
||||
const ConfigOptionPoints* bed_shape = printerConfig->option<ConfigOptionPoints>("bed_shape");
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->rotate(PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[1]]->rotate(5 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[3]]->rotate(3 * PI / 4, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(7 * PI / 4, { 0,0,1 });
|
||||
} else {
|
||||
model.objects[objs_idx[3]]->rotate(PI / 2, { 0,0,1 });
|
||||
model.objects[objs_idx[4]]->rotate(PI / 2, { 0,0,1 });
|
||||
}
|
||||
|
||||
/// --- translate ---
|
||||
//three first will stay with this orientation (top left, middle, bottom right)
|
||||
//last two with 90deg (top left, middle, bottom right)
|
||||
//get position for patches
|
||||
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
|
||||
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
|
||||
float offsetx = 10 + 10 * xyScale;
|
||||
float offsety = 10 + 10 * xyScale;
|
||||
if (bed_shape->values.size() > 4) {
|
||||
offsetx = bed_size.x() / 2 - bed_size.x() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
offsety = bed_size.y() / 2 - bed_size.y() * std::sqrtf(2) / 4 + 10 * xyScale;
|
||||
}
|
||||
bool large_enough = bed_shape->values.size() == 4 ?
|
||||
(bed_size.x() > offsetx * 3 && bed_size.y() > offsety * 3) :
|
||||
(bed_size.x() > offsetx * 2 + 10 * xyScale && bed_size.y() > offsety * 2 + 10 * xyScale);
|
||||
if (!large_enough){
|
||||
//problem : too small, use arrange instead and let the user place them.
|
||||
model.arrange_objects(20);
|
||||
//TODO add message
|
||||
} else {
|
||||
model.objects[objs_idx[0]]->translate({ bed_min.x() + offsetx, bed_min.y() + bed_size.y() - offsety,0 });
|
||||
model.objects[objs_idx[1]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + offsety , 0 });
|
||||
model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x()/2, bed_min.y() + bed_size.y() / 2, 0 });
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + offsetx, bed_min.y() + offsety, 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() - offsetx,bed_min.y() + bed_size.y() - offsety,0 });
|
||||
}
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *printConfig; //make a copy
|
||||
new_print_config.set_key_value("complete_objects", new ConfigOptionBool(true));
|
||||
new_print_config.set_key_value("skirts", new ConfigOptionInt(0));
|
||||
|
||||
/// --- custom config ---
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
model.objects[objs_idx[i]]->config.set_key_value("perimeters", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_solid_layers", new ConfigOptionInt(2));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("gap_fill", new ConfigOptionBool(false));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("first_layer_extrusion_width", new ConfigOptionFloatOrPercent(140, true));
|
||||
model.objects[objs_idx[i]]->config.set_key_value("bottom_fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinearWGapFill));
|
||||
}
|
||||
if (bed_shape->values.size() == 4) {
|
||||
model.objects[objs_idx[0]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[1]]->config.set_key_value("fill_angle", new ConfigOptionFloat(90));
|
||||
model.objects[objs_idx[2]]->config.set_key_value("fill_angle", new ConfigOptionFloat(45));
|
||||
model.objects[objs_idx[3]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
model.objects[objs_idx[4]]->config.set_key_value("fill_angle", new ConfigOptionFloat(0));
|
||||
} else {
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t i = 3; i < 5; i++)
|
||||
model.objects[objs_idx[i]]->config.set_key_value("fill_angle", new ConfigOptionFloat(135));
|
||||
}
|
||||
|
||||
//update plater
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config);
|
||||
plat->on_config_change(new_print_config);
|
||||
plat->changed_objects(objs_idx);
|
||||
//if(!plat->is_background_process_update_scheduled())
|
||||
// plat->schedule_background_process();
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
}
|
||||
|
||||
void CalibrationTempDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
msw_buttons_rescale(this, em_unit(), { wxID_OK });
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
wxPanel* CalibrationTempDialog::create_header(wxWindow* parent, const wxFont& bold_font)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxFont header_font = bold_font;
|
||||
#ifdef __WXOSX__
|
||||
header_font.SetPointSize(14);
|
||||
#else
|
||||
header_font.SetPointSize(bold_font.GetPointSize() + 2);
|
||||
#endif // __WXOSX__
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
// text
|
||||
wxStaticText* text = new wxStaticText(panel, wxID_ANY, _(L("Keyboard shortcuts")));
|
||||
text->SetFont(header_font);
|
||||
sizer->Add(text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
sizer->AddStretchSpacer();
|
||||
|
||||
panel->SetSizer(sizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
39
src/slic3r/GUI/CalibrationTempDialog.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef slic3r_GUI_CalibrationTempDialog_hpp_
|
||||
#define slic3r_GUI_CalibrationTempDialog_hpp_
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include <wx/html/htmlwin.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class CalibrationTempDialog : public DPIDialog
|
||||
{
|
||||
|
||||
public:
|
||||
CalibrationTempDialog(GUI_App* app, MainFrame* mainframe);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
void create_geometry(wxCommandEvent& event_args);
|
||||
wxPanel* create_header(wxWindow* parent, const wxFont& bold_font);
|
||||
|
||||
wxHtmlWindow* html_viewer;
|
||||
MainFrame* main_frame;
|
||||
GUI_App* gui_app;
|
||||
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
@ -40,6 +40,10 @@
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#include "slic3r/Config/Snapshot.hpp"
|
||||
#include "CalibrationBedDialog.hpp"
|
||||
#include "CalibrationBridgeDialog.hpp"
|
||||
#include "CalibrationFlowDialog.hpp"
|
||||
#include "CalibrationTempDialog.hpp"
|
||||
#include "ConfigSnapshotDialog.hpp"
|
||||
#include "FirmwareDialog.hpp"
|
||||
#include "Preferences.hpp"
|
||||
@ -206,6 +210,8 @@ GUI_App::GUI_App()
|
||||
|
||||
GUI_App::~GUI_App()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
|
||||
if (app_config != nullptr)
|
||||
delete app_config;
|
||||
|
||||
@ -280,6 +286,7 @@ bool GUI_App::on_init_inner()
|
||||
// initialize label colors and fonts
|
||||
init_label_colours();
|
||||
init_fonts();
|
||||
wxImage::AddHandler(new wxJPEGHandler());
|
||||
|
||||
// If load_language() fails, the application closes.
|
||||
load_language(wxString(), true);
|
||||
@ -532,6 +539,44 @@ void GUI_App::keyboard_shortcuts()
|
||||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
void GUI_App::delete_calibration_dialog() {
|
||||
if (not_modal_dialog.get() != nullptr) {
|
||||
not_modal_dialog->Destroy();
|
||||
}
|
||||
not_modal_dialog.release();
|
||||
}
|
||||
|
||||
void GUI_App::bed_leveling_dialog()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
not_modal_dialog.reset(new CalibrationBedDialog(this, mainframe));
|
||||
not_modal_dialog->Show();
|
||||
}
|
||||
void GUI_App::flow_ratio_dialog()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
not_modal_dialog.reset(new CalibrationFlowDialog(this, mainframe));
|
||||
not_modal_dialog->Show();
|
||||
}
|
||||
void GUI_App::over_bridge_dialog()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
not_modal_dialog.reset(new CalibrationFlowDialog(this, mainframe));
|
||||
not_modal_dialog->Show();
|
||||
}
|
||||
void GUI_App::bridge_tuning_dialog()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
not_modal_dialog.reset(new CalibrationBridgeDialog(this, mainframe));
|
||||
not_modal_dialog->Show();
|
||||
}
|
||||
void GUI_App::filament_temperature_dialog()
|
||||
{
|
||||
delete_calibration_dialog();
|
||||
not_modal_dialog.reset(new CalibrationTempDialog(this, mainframe));
|
||||
not_modal_dialog->Show();
|
||||
}
|
||||
|
||||
// static method accepting a wxWindow object as first parameter
|
||||
bool GUI_App::catch_error(std::function<void()> cb,
|
||||
// wxMessageDialog* message_dialog,
|
||||
|
@ -131,6 +131,13 @@ public:
|
||||
void recreate_GUI();
|
||||
void system_info();
|
||||
void keyboard_shortcuts();
|
||||
void delete_calibration_dialog();
|
||||
void bed_leveling_dialog();
|
||||
void flow_ratio_dialog();
|
||||
void filament_temperature_dialog();
|
||||
void bridge_tuning_dialog();
|
||||
void over_bridge_dialog();
|
||||
//void support_tuning(); //have to do multiple, in a submenu
|
||||
void load_project(wxWindow *parent, wxString& input_file) const;
|
||||
void import_model(wxWindow *parent, wxArrayString& input_files) const;
|
||||
static bool catch_error(std::function<void()> cb, const std::string& err);
|
||||
@ -175,6 +182,7 @@ public:
|
||||
PresetUpdater* preset_updater{ nullptr };
|
||||
MainFrame* mainframe{ nullptr };
|
||||
Plater* plater_{ nullptr };
|
||||
std::unique_ptr<wxDialog> not_modal_dialog;
|
||||
|
||||
wxNotebook* tab_panel() const ;
|
||||
int extruders_cnt() const;
|
||||
|
@ -759,6 +759,22 @@ void MainFrame::init_menubar()
|
||||
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
|
||||
}
|
||||
|
||||
// objects menu
|
||||
auto objectsMenu = new wxMenu();
|
||||
{
|
||||
append_menu_item(objectsMenu, wxID_ANY, _(L("Bed/Extruder levelling")), _(L("Create a test print to help you to level your printer bed.")),
|
||||
[this](wxCommandEvent&) { wxGetApp().bed_leveling_dialog(); });
|
||||
append_menu_item(objectsMenu, wxID_ANY, _(L("Flow tuning")), _(L("Create a test print to help you to set your filament extrusion multiplier.")),
|
||||
[this](wxCommandEvent&) { wxGetApp().flow_ratio_dialog(); });
|
||||
//append_menu_item(objectsMenu, wxID_ANY, _(L("Ironing pattern tuning")), _(L("Create a test print to help you to set your over-bridge flow ratio.")),
|
||||
// [this](wxCommandEvent&) { wxGetApp().over_bridge_dialog(); });
|
||||
//append_menu_item(objectsMenu, wxID_ANY, _(L("Filament temperature tuning")), _(L("Create a test print to help you to set your filament temperature.")),
|
||||
// [this](wxCommandEvent&) { wxGetApp().filament_temperature_dialog(); });
|
||||
//append_menu_item(objectsMenu, wxID_ANY, _(L("Bridge pattern tuning")), _(L("Create a test print to help you to set your over-bridge flow ratio.")),
|
||||
// [this](wxCommandEvent&) { wxGetApp().bridge_tuning_dialog(); });
|
||||
|
||||
}
|
||||
|
||||
// Help menu
|
||||
auto helpMenu = new wxMenu();
|
||||
{
|
||||
@ -809,6 +825,7 @@ void MainFrame::init_menubar()
|
||||
if (viewMenu) menubar->Append(viewMenu, _(L("&View")));
|
||||
// Add additional menus from C++
|
||||
wxGetApp().add_config_menu(menubar);
|
||||
menubar->Append(objectsMenu, _(L("C&alibration")));
|
||||
menubar->Append(helpMenu, _(L("&Help")));
|
||||
SetMenuBar(menubar);
|
||||
|
||||
|
@ -4779,6 +4779,9 @@ void Plater::remove_selected()
|
||||
Plater::TakeSnapshot snapshot(this, _(L("Delete Selected Objects")));
|
||||
this->p->view3D->delete_selected();
|
||||
}
|
||||
void Plater::arrange() {
|
||||
p->arrange();
|
||||
}
|
||||
|
||||
void Plater::increase_instances(size_t num)
|
||||
{
|
||||
|
@ -213,6 +213,7 @@ public:
|
||||
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
|
||||
void send_gcode();
|
||||
void eject_drive();
|
||||
void arrange();
|
||||
|
||||
void take_snapshot(const std::string &snapshot_name);
|
||||
void take_snapshot(const wxString &snapshot_name);
|
||||
|
@ -519,7 +519,8 @@ const std::vector<std::string>& Preset::print_options()
|
||||
, "curve_smoothing_precision"
|
||||
, "curve_smoothing_cutoff_dist"
|
||||
, "curve_smoothing_angle_convex"
|
||||
, "curve_smoothing_angle_concave"
|
||||
, "curve_smoothing_angle_concave",
|
||||
"print_extrusion_multiplier"
|
||||
};
|
||||
return s_opts;
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ void Tab::update_tab_ui()
|
||||
void Tab::load_config(const DynamicPrintConfig& config)
|
||||
{
|
||||
bool modified = 0;
|
||||
for(auto opt_key : m_config->diff(config)) {
|
||||
for (auto opt_key : m_config->diff(config)) {
|
||||
m_config->set_key_value(opt_key, config.option(opt_key)->clone());
|
||||
modified = 1;
|
||||
}
|
||||
|