diff --git a/resources/calibration/bed_leveling/bed_leveling.html b/resources/calibration/bed_leveling/bed_leveling.html new file mode 100644 index 000000000..b102b3dcf --- /dev/null +++ b/resources/calibration/bed_leveling/bed_leveling.html @@ -0,0 +1,51 @@ + + + + + Bed level calibration + + +

Bed level calibration

+

This calibration is the first one to do, because it's mandatory to make a print stick on the build plate.

+

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.

+

How it works

+

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.

+

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.

+

Results

+ + + + + + + + + + + + + + + + + + + + +
too low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by far
Too far awayToo farToo far:
You can spot
a little gap
perfectToo nearTrap!
It's too near:
check the thickness
with your fingers!
Far too near
Dangerous
for the bed
+

How to tune your printer

+

If your printer has screws, 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.

+

If it doesn’t, you have to use the software or modify the firmware configuration, refer to the manual of your printer.

+

Advices

+

If your filament have a hard time sticking to the bed, you can try to :

+ +

Notes

+

After the filament flow calibration, if it appears that the flow was very wrong, you may want to redo this calibration just after.

+

Most of the calibrations need to done is the right order. This one is the first to do.

+ + + \ No newline at end of file diff --git a/resources/calibration/bed_leveling/good.jpg b/resources/calibration/bed_leveling/good.jpg new file mode 100644 index 000000000..5ee032e80 Binary files /dev/null and b/resources/calibration/bed_leveling/good.jpg differ diff --git a/resources/calibration/bed_leveling/high.jpg b/resources/calibration/bed_leveling/high.jpg new file mode 100644 index 000000000..63db23fff Binary files /dev/null and b/resources/calibration/bed_leveling/high.jpg differ diff --git a/resources/calibration/bed_leveling/high_h.jpg b/resources/calibration/bed_leveling/high_h.jpg new file mode 100644 index 000000000..ea7ed9d36 Binary files /dev/null and b/resources/calibration/bed_leveling/high_h.jpg differ diff --git a/resources/calibration/bed_leveling/high_hh.jpg b/resources/calibration/bed_leveling/high_hh.jpg new file mode 100644 index 000000000..66a1fe241 Binary files /dev/null and b/resources/calibration/bed_leveling/high_hh.jpg differ diff --git a/resources/calibration/bed_leveling/low.jpg b/resources/calibration/bed_leveling/low.jpg new file mode 100644 index 000000000..4c33b2b9a Binary files /dev/null and b/resources/calibration/bed_leveling/low.jpg differ diff --git a/resources/calibration/bed_leveling/low_l.jpg b/resources/calibration/bed_leveling/low_l.jpg new file mode 100644 index 000000000..e708d1c1f Binary files /dev/null and b/resources/calibration/bed_leveling/low_l.jpg differ diff --git a/resources/calibration/bed_leveling/low_ll.jpg b/resources/calibration/bed_leveling/low_ll.jpg new file mode 100644 index 000000000..f54ad6219 Binary files /dev/null and b/resources/calibration/bed_leveling/low_ll.jpg differ diff --git a/resources/calibration/bed_leveling/patch.amf b/resources/calibration/bed_leveling/patch.amf new file mode 100644 index 000000000..172cb018d Binary files /dev/null and b/resources/calibration/bed_leveling/patch.amf differ diff --git a/resources/calibration/bridge_flow/bridge_flow.html b/resources/calibration/bridge_flow/bridge_flow.html new file mode 100644 index 000000000..dfc4dae70 --- /dev/null +++ b/resources/calibration/bridge_flow/bridge_flow.html @@ -0,0 +1,12 @@ + + + + + Document HTML + + +

hello you

+bonjour le monde + + + \ No newline at end of file diff --git a/resources/calibration/calibration_cube.amf b/resources/calibration/calibration_cube.amf new file mode 100644 index 000000000..d0d300547 Binary files /dev/null and b/resources/calibration/calibration_cube.amf differ diff --git a/resources/calibration/filament_flow/0_v1.jpg b/resources/calibration/filament_flow/0_v1.jpg new file mode 100644 index 000000000..ab198cde3 Binary files /dev/null and b/resources/calibration/filament_flow/0_v1.jpg differ diff --git a/resources/calibration/filament_flow/O.amf b/resources/calibration/filament_flow/O.amf new file mode 100644 index 000000000..702e8b729 Binary files /dev/null and b/resources/calibration/filament_flow/O.amf differ diff --git a/resources/calibration/filament_flow/_0.amf b/resources/calibration/filament_flow/_0.amf new file mode 100644 index 000000000..8f4e38f90 Binary files /dev/null and b/resources/calibration/filament_flow/_0.amf differ diff --git a/resources/calibration/filament_flow/filament_flow.html b/resources/calibration/filament_flow/filament_flow.html new file mode 100644 index 000000000..8e4a93f65 --- /dev/null +++ b/resources/calibration/filament_flow/filament_flow.html @@ -0,0 +1,57 @@ + + + + + Filament flow calibration + + +

Filament flow calibration

+

You need to do the bed level calibration before this one.

+

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.

+

Results

+ + +

Exemple:

+ + + + + + + + + + + + + + +

So here, I should

+
too low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by far
not flatnot flatnot flatflat
But the circle
isn't flat enough
Flat surface
and good circle
+

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).

+

How to tune your printer

+

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
+Exemple: first step, i choose the -10, so i have ((100-10)/100) * 1 = (0.9) * 1 = 0.9
+second step i chooe +5, so i have ((100+5)/100) * 0.9 = (1.05) * 0.9 = 0.945 +

+

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.

+

Advice

+

Before doing this test, it's preferable to calibrate your extruder (it's easier on bowden setup):

+ +

Notes

+

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.

+

Most of the calibrations need to done is the right order. This one should be the second.

+

You may want to re-do the bed level calibration is the result is below 0.9 or higher than 1.1.

+

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.

+

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)

+ + + \ No newline at end of file diff --git a/resources/calibration/filament_flow/filament_flow_test_cube.amf b/resources/calibration/filament_flow/filament_flow_test_cube.amf new file mode 100644 index 000000000..6f5618272 Binary files /dev/null and b/resources/calibration/filament_flow/filament_flow_test_cube.amf differ diff --git a/resources/calibration/filament_flow/m10.amf b/resources/calibration/filament_flow/m10.amf new file mode 100644 index 000000000..048b72a48 Binary files /dev/null and b/resources/calibration/filament_flow/m10.amf differ diff --git a/resources/calibration/filament_flow/m10.jpg b/resources/calibration/filament_flow/m10.jpg new file mode 100644 index 000000000..0be0c3711 Binary files /dev/null and b/resources/calibration/filament_flow/m10.jpg differ diff --git a/resources/calibration/filament_flow/m2.amf b/resources/calibration/filament_flow/m2.amf new file mode 100644 index 000000000..52b82d69c Binary files /dev/null and b/resources/calibration/filament_flow/m2.amf differ diff --git a/resources/calibration/filament_flow/m20.amf b/resources/calibration/filament_flow/m20.amf new file mode 100644 index 000000000..ba06e318a Binary files /dev/null and b/resources/calibration/filament_flow/m20.amf differ diff --git a/resources/calibration/filament_flow/m20.jpg b/resources/calibration/filament_flow/m20.jpg new file mode 100644 index 000000000..c1fce72f6 Binary files /dev/null and b/resources/calibration/filament_flow/m20.jpg differ diff --git a/resources/calibration/filament_flow/m4.amf b/resources/calibration/filament_flow/m4.amf new file mode 100644 index 000000000..3c1c288ef Binary files /dev/null and b/resources/calibration/filament_flow/m4.amf differ diff --git a/resources/calibration/filament_flow/m6.amf b/resources/calibration/filament_flow/m6.amf new file mode 100644 index 000000000..5b65502c6 Binary files /dev/null and b/resources/calibration/filament_flow/m6.amf differ diff --git a/resources/calibration/filament_flow/m8.amf b/resources/calibration/filament_flow/m8.amf new file mode 100644 index 000000000..48543e259 Binary files /dev/null and b/resources/calibration/filament_flow/m8.amf differ diff --git a/resources/calibration/filament_flow/p10.amf b/resources/calibration/filament_flow/p10.amf new file mode 100644 index 000000000..a228f2193 Binary files /dev/null and b/resources/calibration/filament_flow/p10.amf differ diff --git a/resources/calibration/filament_flow/p10.jpg b/resources/calibration/filament_flow/p10.jpg new file mode 100644 index 000000000..024dd672a Binary files /dev/null and b/resources/calibration/filament_flow/p10.jpg differ diff --git a/resources/calibration/filament_flow/p20.amf b/resources/calibration/filament_flow/p20.amf new file mode 100644 index 000000000..e09d23230 Binary files /dev/null and b/resources/calibration/filament_flow/p20.amf differ diff --git a/resources/calibration/filament_flow/p20.jpg b/resources/calibration/filament_flow/p20.jpg new file mode 100644 index 000000000..d2d608035 Binary files /dev/null and b/resources/calibration/filament_flow/p20.jpg differ diff --git a/resources/calibration/filament_temp/filament_temp.html b/resources/calibration/filament_temp/filament_temp.html new file mode 100644 index 000000000..2d75a944e --- /dev/null +++ b/resources/calibration/filament_temp/filament_temp.html @@ -0,0 +1,59 @@ + + + + + Filament temperature calibration + + +

Filament flow calibration

+

You need to do the bed level calibration before this one.

+

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.

+

Results

+ + + + + + + + + + + + + + + + + + + + +
too low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by fartoo low, by far
not enough flowToo farToo far:
You can spot
a little gap
okokTrap!
It's too near:
check the thickness
of the patch!
Far too near.
Dangerous
for the bed
+

The flow you want to choose is the lowest that don't create gaps in the top surface.

+

How to tune your printer

+

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
+Exemple: first step, i choose the -10, so i have ((100-10)/100) * 1 = (0.9) * 1 = 0.9
+second step i chooe +5, so i have ((100+5)/100) * 0.9 = (1.05) * 0.9 = 0.945 +

+

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.

+

Advice

+

Before doing this test, it's preferable to calibrate your extruder (it's easier on bowden setup):

+ +

Notes

+

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.

+

Most of the calibrations need to done is the right order. This one should be the second.

+

You may want to re-do the bed level calibration is the result is below 0.9 or higher than 1.1.

+

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.

+

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)

+ + + \ No newline at end of file diff --git a/resources/calibration/filament_temp/overhang_test.amf b/resources/calibration/filament_temp/overhang_test.amf new file mode 100644 index 000000000..10a992bc9 Binary files /dev/null and b/resources/calibration/filament_temp/overhang_test.amf differ diff --git a/resources/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf b/resources/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf new file mode 100644 index 000000000..d2c344254 Binary files /dev/null and b/resources/calibration/over-bridge_tuning/over-bridge_flow_ratio_test.amf differ diff --git a/resources/calibration/over-bridge_tuning/over-bridge_tuning.html b/resources/calibration/over-bridge_tuning/over-bridge_tuning.html new file mode 100644 index 000000000..dfc4dae70 --- /dev/null +++ b/resources/calibration/over-bridge_tuning/over-bridge_tuning.html @@ -0,0 +1,12 @@ + + + + + Document HTML + + +

hello you

+bonjour le monde + + + \ No newline at end of file diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 5e56b8444..d46b7c736 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -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 diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 98167e139..571eefa0c 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -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) diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 51f862612..eb1714de9 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -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); } } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 2dad5a377..314074af7 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -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.; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a8d0df194..52ade128b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -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 { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 49c13b9f1..85ba6f145 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -631,6 +631,7 @@ public: ConfigOptionFloat perimeter_speed; // Total number of perimeters. ConfigOptionInt perimeters; + ConfigOptionPercent print_extrusion_multiplier; ConfigOptionFloatOrPercent small_perimeter_speed; ConfigOptionEnum 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); diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 5e0c34da0..f4943de55 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -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 diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index a909b9a54..228824a06 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -163,8 +163,8 @@ void GLIndexedVertexArray::render( const std::pair& tverts_range, const std::pair& 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)); diff --git a/src/slic3r/GUI/CalibrationBedDialog.cpp b/src/slic3r/GUI/CalibrationBedDialog.cpp new file mode 100644 index 000000000..6fe4d4f01 --- /dev/null +++ b/src/slic3r/GUI/CalibrationBedDialog.cpp @@ -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 +#include +#include +#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 objs_idx = plat->load_files(std::vector{ + "./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("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("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("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(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 diff --git a/src/slic3r/GUI/CalibrationBedDialog.hpp b/src/slic3r/GUI/CalibrationBedDialog.hpp new file mode 100644 index 000000000..9b48dad70 --- /dev/null +++ b/src/slic3r/GUI/CalibrationBedDialog.hpp @@ -0,0 +1,41 @@ +#ifndef slic3r_GUI_CalibrationBedDialog_hpp_ +#define slic3r_GUI_CalibrationBedDialog_hpp_ + +#include +#include +#include + +#include "GUI_App.hpp" +#include "GUI_Utils.hpp" +#include "MainFrame.hpp" +#include "wxExtensions.hpp" +#include + +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 diff --git a/src/slic3r/GUI/CalibrationBridgeDialog.cpp b/src/slic3r/GUI/CalibrationBridgeDialog.cpp new file mode 100644 index 000000000..5c0251889 --- /dev/null +++ b/src/slic3r/GUI/CalibrationBridgeDialog.cpp @@ -0,0 +1,196 @@ +#include "CalibrationBridgeDialog.hpp" +#include "I18N.hpp" +#include "libslic3r/Utils.hpp" +#include "GUI.hpp" +#include "tab.hpp" +#include +#include +#include +#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 objs_idx = plat->load_files(std::vector{ + "./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("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("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("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(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 diff --git a/src/slic3r/GUI/CalibrationBridgeDialog.hpp b/src/slic3r/GUI/CalibrationBridgeDialog.hpp new file mode 100644 index 000000000..6d255d32d --- /dev/null +++ b/src/slic3r/GUI/CalibrationBridgeDialog.hpp @@ -0,0 +1,39 @@ +#ifndef slic3r_GUI_CalibrationBridgeDialog_hpp_ +#define slic3r_GUI_CalibrationBridgeDialog_hpp_ + +#include +#include +#include + +#include "GUI_App.hpp" +#include "GUI_Utils.hpp" +#include "MainFrame.hpp" +#include "wxExtensions.hpp" +#include + +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 diff --git a/src/slic3r/GUI/CalibrationFlowDialog.cpp b/src/slic3r/GUI/CalibrationFlowDialog.cpp new file mode 100644 index 000000000..e910e6a94 --- /dev/null +++ b/src/slic3r/GUI/CalibrationFlowDialog.cpp @@ -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 +#include +#include +#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::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 objs_idx = plat->load_files(std::vector{ + "./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("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("first_layer_height"); + const ConfigOptionFloat* layer_height = printConfig->option("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("extruder_clearance_radius"); + const ConfigOptionPoints* bed_shape = printerConfig->option("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(ipRectilinearWGapFill)); + model.objects[objs_idx[i]]->config.set_key_value("top_fill_pattern", new ConfigOptionEnum(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 diff --git a/src/slic3r/GUI/CalibrationFlowDialog.hpp b/src/slic3r/GUI/CalibrationFlowDialog.hpp new file mode 100644 index 000000000..ef0693bd1 --- /dev/null +++ b/src/slic3r/GUI/CalibrationFlowDialog.hpp @@ -0,0 +1,43 @@ +#ifndef slic3r_GUI_CalibrationFlowDialog_hpp_ +#define slic3r_GUI_CalibrationFlowDialog_hpp_ + +#include +#include +#include + +#include "GUI_App.hpp" +#include "GUI_Utils.hpp" +#include "MainFrame.hpp" +#include "wxExtensions.hpp" +#include + +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 diff --git a/src/slic3r/GUI/CalibrationTempDialog.cpp b/src/slic3r/GUI/CalibrationTempDialog.cpp new file mode 100644 index 000000000..2d7bea034 --- /dev/null +++ b/src/slic3r/GUI/CalibrationTempDialog.cpp @@ -0,0 +1,196 @@ +#include "CalibrationTempDialog.hpp" +#include "I18N.hpp" +#include "libslic3r/Utils.hpp" +#include "GUI.hpp" +#include "tab.hpp" +#include +#include +#include +#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 objs_idx = plat->load_files(std::vector{ + "./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("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("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("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(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 diff --git a/src/slic3r/GUI/CalibrationTempDialog.hpp b/src/slic3r/GUI/CalibrationTempDialog.hpp new file mode 100644 index 000000000..2de42fdc4 --- /dev/null +++ b/src/slic3r/GUI/CalibrationTempDialog.hpp @@ -0,0 +1,39 @@ +#ifndef slic3r_GUI_CalibrationTempDialog_hpp_ +#define slic3r_GUI_CalibrationTempDialog_hpp_ + +#include +#include +#include + +#include "GUI_App.hpp" +#include "GUI_Utils.hpp" +#include "MainFrame.hpp" +#include "wxExtensions.hpp" +#include + +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 diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1328937e1..89ba2d4a4 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -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 cb, // wxMessageDialog* message_dialog, diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index d02a60ba9..068b92613 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -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 cb, const std::string& err); @@ -175,6 +182,7 @@ public: PresetUpdater* preset_updater{ nullptr }; MainFrame* mainframe{ nullptr }; Plater* plater_{ nullptr }; + std::unique_ptr not_modal_dialog; wxNotebook* tab_panel() const ; int extruders_cnt() const; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 9ea306979..3bd78e396 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -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); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b5cdcca4e..a76ae3c2b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -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) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 32709a4bd..d1256f7b1 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -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); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index a0dc06a35..2e20a376d 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -519,7 +519,8 @@ const std::vector& 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; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 162c9293e..9cc4aa095 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -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; }