diff --git a/.github/ISSUE_TEMPLATE/bug_report_form.yml b/.github/ISSUE_TEMPLATE/bug_report_form.yml
new file mode 100644
index 0000000000..7cbaddc49f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report_form.yml
@@ -0,0 +1,65 @@
+name: Bug Report
+description: File a bug report
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Before filing, please check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: Description of the bug
+ description: What happened? Please, enclose a screenshot whenever possible (even when you think the description is clear). What did you expect to happen? In case of 3D rendering issues, please attach the content of menu Help -> System Info dialog.
+ placeholder: |
+ What is the problem?
+ What did you expect?
+ You paste or drop screenshots here
+ validations:
+ required: true
+ - type: textarea
+ id: to_reproduce
+ attributes:
+ label: Project file & How to reproduce
+ description: "*Please* upload a ZIP archive containing the project file used when the problem arise. Please export it just before the problem occurs. Even if you did nothing and/or there is no object, export it! (it contains your current configuration)."
+ placeholder: |
+ `File`->`Export project as...` then zip it & drop it here
+ Also, if needed include the steps to reproduce the bug:
+ 1. Go to '...'
+ 2. Click on '....'
+ 3. Scroll down to '....'
+ 4. See error
+ validations:
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Checklist of files included above
+ options:
+ - label: Project file
+ - label: Screenshot
+ validations:
+ required: true
+ - type: input
+ id: version
+ attributes:
+ label: Version of PrusaSlicer
+ description: What version of PrusaSlicer are you running? You can see the full version in `Help` -> `About PrusaSlicer`.
+ placeholder: e.g. 2.4.1-alpha2-win64 / 2.3.3-linux / 2.4.1-alpha0+61-win64-gcd2459455 ...
+ validations:
+ required: true
+ - type: input
+ id: os
+ attributes:
+ label: Operating system
+ description: with the version if possible
+ placeholder: e.g. Windows 7/8/10/11 ... , Ubuntu 22.04/Debian ... , macOS 10.15/11.1 ...
+ validations:
+ required: true
+ - type: input
+ id: printer
+ attributes:
+ label: Printer model
+ description: Please, fill this in even when it seems irrelevant.
+ placeholder: voron 2.4 with afterburner
+ validations:
+ required: true
+
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..d373b69eea
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,9 @@
+contact_links:
+ - name: PrusaSlicer Manual and Support
+ url: https://help.prusa3d.com/en/article/customer-support_2287/
+ about: If you are not sure that what you are reporting is really a bug, please, consult the manual first.
+ - name: PrusaPrinters Forum
+ url: https://forum.prusaprinters.org/forum/prusaslicer/
+ about: Please get in touch on our PrusaPrinters Community Forum! (Not an official support channel.)
+
+blank_issues_enabled: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000..aed1846872
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe how it would work**
+Be as descriptive as your skill level allows you.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or paint drawing about the feature request here.
diff --git a/build_win.bat b/build_win.bat
index de5030ee50..3dbdb0ad6e 100644
--- a/build_win.bat
+++ b/build_win.bat
@@ -164,6 +164,9 @@ IF NOT EXIST "%MSVC_DIR%" (
@ECHO ERROR: Compatible Visual Studio installation not found. 1>&2
GOTO :HELP
)
+REM Cmake always defaults to latest supported MSVC generator. Let's make sure it uses what we select.
+FOR /F "tokens=* USEBACKQ" %%I IN (`^""%VSWHERE%" %MSVC_FILTER% -nologo -property catalog_productLineVersion^"`) DO SET PS_PRODUCT_VERSION=%%I
+
REM Give the user a chance to cancel if we found something odd.
IF "%PS_ASK_TO_CONTINUE%" EQU "" GOTO :BUILD_ENV
@ECHO.
@@ -183,6 +186,7 @@ SET PS_CURRENT_STEP=environment
@ECHO ** Deps path: %PS_DESTDIR%
@ECHO ** Using Microsoft Visual Studio installation found at:
@ECHO ** %MSVC_DIR%
+SET CMAKE_GENERATOR=Visual Studio %PS_VERSION% %PS_PRODUCT_VERSION%
CALL "%MSVC_DIR%\Common7\Tools\vsdevcmd.bat" -arch=%PS_ARCH% -host_arch=%PS_ARCH_HOST% -app_platform=Desktop
IF %ERRORLEVEL% NEQ 0 GOTO :END
REM Need to reset the echo state after vsdevcmd.bat clobbers it.
diff --git a/resources/profiles/Anycubic.idx b/resources/profiles/Anycubic.idx
index 47bdd8c271..232d534256 100644
--- a/resources/profiles/Anycubic.idx
+++ b/resources/profiles/Anycubic.idx
@@ -1,4 +1,5 @@
min_slic3r_version = 2.4.1-rc1
+0.1.1 Fixed before layer change g-code for Mega Zero.
0.1.0 Added Anycubic 4Max Pro 2.0
min_slic3r_version = 2.3.2-alpha0
0.0.12 Updated Anycubic i3 MEGA(S) profiles.
diff --git a/resources/profiles/Anycubic.ini b/resources/profiles/Anycubic.ini
index fd73c063e8..e8fd89bf4a 100644
--- a/resources/profiles/Anycubic.ini
+++ b/resources/profiles/Anycubic.ini
@@ -1,2329 +1,2329 @@
-# Print profiles for the Anycubic printers.
-
-[vendor]
-# Vendor name will be shown by the Config Wizard.
-name = Anycubic
-# Configuration version of this file. Config file will only be installed, if the config_version differs.
-# This means, the server may force the PrusaSlicer configuration to be downgraded.
-config_version = 0.1.0
-# Where to get the updates from?
-config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/
-# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
-
-# The printer models will be shown by the Configuration Wizard in this order,
-# also the first model installed & the first nozzle installed will be activated after install.
-# Printer model name will be shown by the installation wizard.
-
-[printer_model:AKLP]
-name = Anycubic Kossel Linear Plus
-variants = 0.4
-technology = FFF
-family = KOSSEL
-bed_model = AKLP_Bed.stl
-bed_texture = AK.svg
-default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL
-
-[printer_model:AK]
-name = Anycubic Kossel Pulley (Linear)
-variants = 0.4
-technology = FFF
-family = KOSSEL
-bed_model = AK_Bed.stl
-bed_texture = AK.svg
-default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL
-
-[printer_model:MEGA0]
-name = Anycubic Mega Zero
-variants = 0.4
-technology = FFF
-family = MEGA
-bed_model = mega0_bed.stl
-bed_texture = mega0.svg
-default_materials = Generic PLA @MEGA0; Generic PETG @MEGA0; Anycubic PLA @MEGA0; Prusament PLA @MEGA0; Prusament PETG @MEGA0
-
-[printer_model:I3MEGA]
-name = Anycubic i3 Mega
-variants = 0.4
-technology = FFF
-family = MEGA
-bed_model = i3megas_bed.stl
-bed_texture = i3megas.svg
-
-[printer_model:I3MEGAS]
-name = Anycubic i3 Mega S
-variants = 0.4
-technology = FFF
-family = MEGA
-bed_model = i3megas_bed.stl
-bed_texture = i3megas.svg
-
-[printer_model:4MAXPRO20]
-name = Anycubic 4Max Pro 2.0
-variants = 0.4
-technology = FFF
-family = 4Max
-bed_model = 4MAXPRO20_bed.stl
-bed_texture = 4MAXPRO20_texture.svg
-default_materials = Generic PLA @4Max Pro 2.0; Generic TPU @4Max Pro 2.0; Generic ABS @4Max Pro 2.0
-
-[printer_model:PREDATOR]
-name = Anycubic Predator
-variants = 0.4; 0.6; 0.8
-technology = FFF
-family = PREDATOR
-default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR
-
-[printer_model:PHOTON MONO X]
-name = Photon Mono X
-variants = default
-technology = SLA
-family = PHOTON MONO
-default_materials = Generic Blue Resin @MONO 0.05
-
-# All presets starting with asterisk, for example *common*, are intermediate and they will
-# not make it into the user interface.
-
-## Anycubic KOSSEL
-## Author: https://github.com/tc0fh
-## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4220
-
-# Common print preset
-[print:*common_akossel*]
-avoid_crossing_perimeters = 0
-bottom_solid_min_thickness = 0.5
-bridge_angle = 0
-bridge_flow_ratio = 0.8
-bridge_speed = 30
-brim_width = 0
-clip_multipart_objects = 1
-compatible_printers =
-complete_objects = 0
-dont_support_bridges = 1
-elefant_foot_compensation = 0
-ensure_vertical_shell_thickness = 1
-external_fill_pattern = rectilinear
-external_perimeters_first = 0
-external_perimeter_extrusion_width = 0.45
-extra_perimeters = 0
-extruder_clearance_height = 25
-extruder_clearance_radius = 45
-extrusion_width = 0.45
-fill_angle = 45
-fill_density = 20%
-fill_pattern = grid
-first_layer_extrusion_width = 0.42
-first_layer_height = 0.2
-first_layer_speed = 20
-gap_fill_speed = 40
-gcode_comments = 0
-infill_every_layers = 1
-infill_extruder = 1
-infill_extrusion_width = 0.45
-infill_first = 0
-infill_only_where_needed = 0
-infill_overlap = 25%
-interface_shells = 0
-max_print_speed = 200
-max_volumetric_extrusion_rate_slope_negative = 0
-max_volumetric_extrusion_rate_slope_positive = 0
-max_volumetric_speed = 0
-min_skirt_length = 4
-notes =
-overhangs = 0
-only_retract_when_crossing_perimeters = 0
-ooze_prevention = 0
-output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
-perimeters = 2
-perimeter_extruder = 1
-perimeter_extrusion_width = 0.45
-perimeter_speed = 45
-post_process =
-print_settings_id =
-raft_layers = 0
-resolution = 0
-seam_position = nearest
-single_extruder_multi_material_priming = 0
-skirts = 2
-skirt_distance = 5
-skirt_height = 1
-small_perimeter_speed = 25
-solid_infill_below_area = 0
-solid_infill_every_layers = 0
-solid_infill_extruder = 1
-solid_infill_extrusion_width = 0.45
-spiral_vase = 0
-standby_temperature_delta = -5
-support_material = 0
-support_material_extruder = 0
-support_material_extrusion_width = 0.38
-support_material_interface_extruder = 0
-support_material_angle = 0
-support_material_buildplate_only = 0
-support_material_enforce_layers = 0
-support_material_contact_distance = 0.15
-support_material_interface_contact_loops = 0
-support_material_interface_layers = 2
-support_material_interface_spacing = 0.2
-support_material_interface_speed = 100%
-support_material_pattern = rectilinear
-support_material_spacing = 2
-support_material_speed = 50
-support_material_synchronize_layers = 0
-support_material_threshold = 45
-support_material_with_sheath = 0
-support_material_xy_spacing = 60%
-thin_walls = 0
-top_infill_extrusion_width = 0.4
-top_solid_infill_speed = 40
-top_solid_min_thickness = 0.6
-travel_speed = 180
-wipe_tower = 1
-wipe_tower_bridging = 10
-wipe_tower_rotation_angle = 0
-wipe_tower_width = 60
-wipe_tower_x = 170
-wipe_tower_y = 140
-xy_size_compensation = 0
-bridge_acceleration = 1000
-default_acceleration = 1500
-first_layer_acceleration = 1000
-infill_acceleration = 1500
-perimeter_acceleration = 800
-
-[print:*0.08mm_akossel*]
-inherits = *common_akossel*
-bottom_solid_layers = 10
-bridge_acceleration = 300
-bridge_flow_ratio = 0.7
-bridge_speed = 20
-external_perimeter_speed = 20
-first_layer_acceleration = 500
-gap_fill_speed = 20
-infill_acceleration = 800
-infill_speed = 40
-layer_height = 0.08
-max_print_speed = 80
-perimeter_acceleration = 300
-perimeter_speed = 30
-perimeters = 3
-small_perimeter_speed = 20
-solid_infill_speed = 40
-support_material_extrusion_width = 0.3
-support_material_spacing = 1.5
-support_material_speed = 40
-top_solid_infill_speed = 30
-top_solid_layers = 12
-
-[print:*0.16mm_akossel*]
-inherits = *common_akossel*
-bottom_solid_layers = 5
-layer_height = 0.16
-top_solid_layers = 6
-
-[print:*0.20mm_akossel*]
-inherits = *common_akossel*
-bottom_solid_layers = 4
-bridge_flow_ratio = 0.95
-layer_height = 0.20
-top_solid_layers = 5
-
-[print:*0.24mm_akossel*]
-inherits = *common_akossel*
-bottom_solid_layers = 4
-bridge_flow_ratio = 0.95
-layer_height = 0.24
-perimeter_speed = 50
-external_perimeter_speed = 35
-top_solid_layers = 4
-infill_speed = 100
-solid_infill_speed = 100
-top_solid_infill_speed = 40
-
-[print:*0.30mm_akossel*]
-inherits = *common_akossel*
-bottom_solid_layers = 3
-bridge_flow_ratio = 0.95
-external_perimeter_extrusion_width = 0.6
-external_perimeter_speed = 35
-extrusion_width = 0.5
-infill_extrusion_width = 0.5
-infill_speed = 70
-layer_height = 0.30
-perimeter_extrusion_width = 0.5
-perimeter_speed = 50
-small_perimeter_speed = 30
-solid_infill_extrusion_width = 0.5
-solid_infill_speed = 70
-support_material_speed = 45
-top_infill_extrusion_width = 0.45
-top_solid_infill_speed = 50
-top_solid_layers = 3
-
-[print:0.08mm ULTRADETAIL @AKOSSEL]
-inherits = *0.08mm_akossel*
-fill_density = 15%
-fill_pattern = gyroid
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.16mm QUALITY @AKOSSEL]
-inherits = *0.16mm_akossel*
-external_perimeter_speed = 25
-fill_density = 15%
-fill_pattern = gyroid
-infill_speed = 80
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.16mm SPEED @AKOSSEL]
-inherits = *0.16mm_akossel*
-external_perimeter_speed = 35
-infill_speed = 120
-perimeter_speed = 60
-solid_infill_speed = 120
-top_solid_infill_speed = 50
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.20mm QUALITY @AKOSSEL]
-inherits = *0.20mm_akossel*
-external_perimeter_speed = 25
-fill_density = 15%
-fill_pattern = gyroid
-infill_speed = 80
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.20mm SPEED @AKOSSEL]
-inherits = *0.20mm_akossel*
-external_perimeter_speed = 35
-infill_speed = 120
-perimeter_speed = 60
-solid_infill_speed = 120
-top_solid_infill_speed = 50
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.24mm DRAFT @AKOSSEL]
-inherits = *0.24mm_akossel*
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-[print:0.30mm FAST @AKOSSEL]
-inherits = *0.30mm_akossel*
-compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
-
-# Common filament preset
-[filament:*common_akossel*]
-cooling = 0
-compatible_printers =
-extrusion_multiplier = 1
-filament_cost = 0
-filament_density = 0
-filament_diameter = 1.75
-filament_notes = ""
-filament_settings_id = ""
-filament_soluble = 0
-min_print_speed = 15
-slowdown_below_layer_time = 20
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Anycubic.*/ and printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/
-
-[filament:*PLA_akossel*]
-inherits = *common_akossel*
-bed_temperature = 60
-fan_below_layer_time = 100
-filament_colour = #FF3232
-filament_max_volumetric_speed = 10
-filament_type = PLA
-filament_density = 1.24
-filament_cost = 20
-first_layer_bed_temperature = 60
-first_layer_temperature = 200
-fan_always_on = 1
-cooling = 1
-max_fan_speed = 100
-min_fan_speed = 100
-bridge_fan_speed = 100
-disable_fan_first_layers = 1
-temperature = 200
-
-[filament:*PET_akossel*]
-inherits = *common_akossel*
-bed_temperature = 70
-cooling = 1
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #FF8000
-filament_max_volumetric_speed = 8
-filament_type = PETG
-filament_density = 1.27
-filament_cost = 30
-first_layer_bed_temperature =70
-first_layer_temperature = 240
-fan_always_on = 1
-max_fan_speed = 50
-min_fan_speed = 20
-bridge_fan_speed = 100
-temperature = 240
-
-[filament:*ABS_akossel*]
-inherits = *common_akossel*
-bed_temperature = 100
-cooling = 0
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #3A80CA
-filament_max_volumetric_speed = 10
-filament_type = ABS
-filament_density = 1.04
-filament_cost = 20
-first_layer_bed_temperature = 100
-first_layer_temperature = 245
-fan_always_on = 0
-max_fan_speed = 0
-min_fan_speed = 0
-bridge_fan_speed = 30
-top_fan_speed = 0
-temperature = 245
-
-[filament:Generic PLA @AKOSSEL]
-inherits = *PLA_akossel*
-filament_vendor = Generic
-
-[filament:Generic PETG @AKOSSEL]
-inherits = *PET_akossel*
-filament_vendor = Generic
-
-[filament:Generic ABS @AKOSSEL]
-inherits = *ABS_akossel*
-filament_vendor = Generic
-
-# Common printer preset
-[printer:*common_akossel*]
-printer_technology = FFF
-bed_shape =
-before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]
-between_objects_gcode =
-deretract_speed = 40
-extruder_colour = #FFFF00
-extruder_offset = 0x0
-gcode_flavor = marlin
-silent_mode = 0
-remaining_times = 0
-machine_max_acceleration_e = 3000
-machine_max_acceleration_extruding = 1000
-machine_max_acceleration_retracting = 1000
-machine_max_acceleration_x = 1500
-machine_max_acceleration_y = 1500
-machine_max_acceleration_z = 1500
-machine_max_feedrate_e = 60
-machine_max_feedrate_x = 200
-machine_max_feedrate_y = 200
-machine_max_feedrate_z = 200
-machine_max_jerk_e = 5
-machine_max_jerk_x = 5
-machine_max_jerk_y = 5
-machine_max_jerk_z = 5
-machine_min_extruding_rate = 0
-machine_min_travel_rate = 0
-layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
-max_layer_height = 0.3
-min_layer_height = 0.08
-max_print_height = 300
-nozzle_diameter = 0.4
-printer_notes =
-printer_settings_id =
-retract_before_travel = 2
-retract_before_wipe = 70%
-retract_layer_change = 1
-retract_length = 5
-retract_length_toolchange = 1
-retract_lift = 0
-retract_lift_above = 0
-retract_lift_below = 0
-retract_restart_extra = 0
-retract_restart_extra_toolchange = 0
-retract_speed = 60
-single_extruder_multi_material = 0
-start_gcode =
-end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG28 ; home\nM84 ; disable motors
-toolchange_gcode =
-use_firmware_retraction = 0
-use_relative_e_distances = 1
-use_volumetric_e = 0
-variable_layer_height = 1
-wipe = 1
-z_offset = 0
-default_print_profile = 0.20mm QUALITY @AKOSSEL
-default_filament_profile = Generic PLA @AKOSSEL
-
-[printer:Anycubic Kossel Linear Plus]
-inherits = *common_akossel*
-printer_model = AKLP
-printer_variant = 0.4
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n
-bed_shape = 114.562x10.0229,113.253x19.9695,111.081x29.7642,108.065x39.3323,104.225x48.6011,99.5929x57.5,94.2025x65.9613,88.0951x73.9206,81.3173x81.3173,73.9206x88.0951,65.9613x94.2025,57.5x99.5929,48.6011x104.225,39.3323x108.065,29.7642x111.081,19.9695x113.253,10.0229x114.562,7.04172e-15x115,-10.0229x114.562,-19.9695x113.253,-29.7642x111.081,-39.3323x108.065,-48.6011x104.225,-57.5x99.5929,-65.9613x94.2025,-73.9206x88.0951,-81.3173x81.3173,-88.0951x73.9206,-94.2025x65.9613,-99.5929x57.5,-104.225x48.6011,-108.065x39.3323,-111.081x29.7642,-113.253x19.9695,-114.562x10.0229,-115x1.40834e-14,-114.562x-10.0229,-113.253x-19.9695,-111.081x-29.7642,-108.065x-39.3323,-104.225x-48.6011,-99.5929x-57.5,-94.2025x-65.9613,-88.0951x-73.9206,-81.3173x-81.3173,-73.9206x-88.0951,-65.9613x-94.2025,-57.5x-99.5929,-48.6011x-104.225,-39.3323x-108.065,-29.7642x-111.081,-19.9695x-113.253,-10.0229x-114.562,-2.11252e-14x-115,10.0229x-114.562,19.9695x-113.253,29.7642x-111.081,39.3323x-108.065,48.6011x-104.225,57.5x-99.5929,65.9613x-94.2025,73.9206x-88.0951,81.3173x-81.3173,88.0951x-73.9206,94.2025x-65.9613,99.5929x-57.5,104.225x-48.6011,108.065x-39.3323,111.081x-29.7642,113.253x-19.9695,114.562x-10.0229,115x-2.81669e-14
-start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-54.672 Y95.203 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-52.931 Y96.185 E0.300\nG1 X-50.985 Y97.231 E0.331\nG1 X-49.018 Y98.238 E0.331\nG1 X-47.032 Y99.205 E0.331\nG1 X-45.026 Y100.132 E0.331\nG1 X-43.003 Y101.019 E0.331\nG1 X-40.961 Y101.864 E0.331\nG1 X-38.904 Y102.668 E0.331\nG1 X-36.83 Y103.431 E0.331\nG1 X-34.742 Y104.152 E0.331\nG1 X-32.639 Y104.83 E0.331\nG1 X-30.523 Y105.466 E0.331\nG1 X-28.395 Y106.06 E0.331\nG1 X-26.255 Y106.61 E0.331\nG1 X-24.105 Y107.117 E0.331\nG1 X-21.945 Y107.581 E0.331\nG1 X-19.776 Y108.001 E0.331\nG1 X-17.599 Y108.377 E0.331\nG1 X-15.415 Y108.71 E0.331\nG1 X-13.224 Y108.998 E0.331\nG1 X-11.028 Y109.242 E0.331\nG1 X-8.828 Y109.442 E0.331\nG1 X-6.624 Y109.598 E0.331\nG1 X-4.418 Y109.709 E0.331\nG1 X-2.209 Y109.776 E0.332\nG1 X0 Y109.798 E0.331\nG1 X2.209 Y109.776 E0.690\nG1 X4.418 Y109.709 E0.691\nG1 X6.624 Y109.598 E0.690\nG1 X8.828 Y109.442 E0.690\nG1 X11.028 Y109.242 E0.690\nG1 X13.224 Y108.998 E0.690\nG1 X15.415 Y108.71 E0.691\nG1 X17.599 Y108.377 E0.690\nG1 X19.776 Y108.001 E0.690\nG1 X21.945 Y107.581 E0.690\nG1 X24.105 Y107.117 E0.690\nG1 X26.255 Y106.61 E0.690\nG1 X28.395 Y106.06 E0.690\nG1 X30.523 Y105.466 E0.690\nG1 X32.639 Y104.83 E0.690\nG1 X34.742 Y104.152 E0.690\nG1 X36.83 Y103.431 E0.690\nG1 X38.904 Y102.668 E0.691\nG1 X40.961 Y101.864 E0.690\nG1 X43.003 Y101.019 E0.691\nG1 X45.026 Y100.132 E0.690\nG1 X47.032 Y99.205 E0.691\nG1 X49.018 Y98.238 E0.690\nG1 X50.985 Y97.231 E0.691\nG1 X52.931 Y96.185 E0.690\nG1 X54.672 Y95.203 E0.625\nG92 E0.0\nG1 E-5 F3000 ; retract 5mm\nG1 X52.931 Y96.185 F1000 ; wipe\nG1 X50.985 Y97.231 F1000 ; wipe\nG1 X49.018 Y98.238 F1000 ; wipe\nG1 X0 Y109.798 F1000\nG1 E4.8 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\nM221 S{if layer_height<0.075}100{else}95{endif}
-
-[printer:Anycubic Kossel Pulley (Linear)]
-inherits = *common_akossel*
-printer_model = AK
-printer_variant = 0.4
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n
-bed_shape = 89.6575x7.84402,88.6327x15.6283,86.9333x23.2937,84.5723x30.7818,81.5677x38.0356,77.9423x45,73.7237x51.6219,68.944x57.8509,63.6396x63.6396,57.8509x68.944,51.6219x73.7237,45x77.9423,38.0356x81.5677,30.7818x84.5723,23.2937x86.9333,15.6283x88.6327,7.84402x89.6575,5.51091e-15x90,-7.84402x89.6575,-15.6283x88.6327,-23.2937x86.9333,-30.7818x84.5723,-38.0356x81.5677,-45x77.9423,-51.6219x73.7237,-57.8509x68.944,-63.6396x63.6396,-68.944x57.8509,-73.7237x51.6219,-77.9423x45,-81.5677x38.0356,-84.5723x30.7818,-86.9333x23.2937,-88.6327x15.6283,-89.6575x7.84402,-90x1.10218e-14,-89.6575x-7.84402,-88.6327x-15.6283,-86.9333x-23.2937,-84.5723x-30.7818,-81.5677x-38.0356,-77.9423x-45,-73.7237x-51.6219,-68.944x-57.8509,-63.6396x-63.6396,-57.8509x-68.944,-51.6219x-73.7237,-45x-77.9423,-38.0356x-81.5677,-30.7818x-84.5723,-23.2937x-86.9333,-15.6283x-88.6327,-7.84402x-89.6575,-1.65327e-14x-90,7.84402x-89.6575,15.6283x-88.6327,23.2937x-86.9333,30.7818x-84.5723,38.0356x-81.5677,45x-77.9423,51.6219x-73.7237,57.8509x-68.944,63.6396x-63.6396,68.944x-57.8509,73.7237x-51.6219,77.9423x-45,81.5677x-38.0356,84.5723x-30.7818,86.9333x-23.2937,88.6327x-15.6283,89.6575x-7.84402,90x-2.20436e-14
-start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-39.672 Y69.712 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-38.457 Y70.397 E0.209\nG1 X-37.043 Y71.157 E0.241\nG1 X-35.614 Y71.889 E0.241\nG1 X-34.171 Y72.591 E0.241\nG1 X-32.714 Y73.265 E0.241\nG1 X-31.244 Y73.909 E0.241\nG1 X-29.761 Y74.523 E0.241\nG1 X-28.266 Y75.108 E0.241\nG1 X-26.759 Y75.662 E0.241\nG1 X-25.242 Y76.185 E0.241\nG1 X-23.714 Y76.678 E0.241\nG1 X-22.177 Y77.14 E0.241\nG1 X-20.63 Y77.571 E0.241\nG1 X-19.076 Y77.971 E0.241\nG1 X-17.514 Y78.34 E0.241\nG1 X-15.944 Y78.677 E0.241\nG1 X-14.368 Y78.982 E0.241\nG1 X-12.786 Y79.255 E0.241\nG1 X-11.199 Y79.497 E0.241\nG1 X-9.608 Y79.706 E0.241\nG1 X-8.013 Y79.884 E0.241\nG1 X-6.414 Y80.029 E0.241\nG1 X-4.813 Y80.142 E0.241\nG1 X-3.21 Y80.223 E0.241\nG1 X-1.605 Y80.271 E0.241\nG1 X0 Y80.287 E0.241\nG1 X1.605 Y80.271 E0.502\nG1 X3.21 Y80.223 E0.502\nG1 X4.813 Y80.142 E0.502\nG1 X6.414 Y80.029 E0.502\nG1 X8.013 Y79.884 E0.502\nG1 X9.608 Y79.706 E0.502\nG1 X11.199 Y79.497 E0.501\nG1 X12.786 Y79.255 E0.502\nG1 X14.368 Y78.982 E0.502\nG1 X15.944 Y78.677 E0.502\nG1 X17.514 Y78.34 E0.502\nG1 X19.076 Y77.971 E0.502\nG1 X20.63 Y77.571 E0.501\nG1 X22.177 Y77.14 E0.502\nG1 X23.714 Y76.678 E0.502\nG1 X25.242 Y76.185 E0.502\nG1 X26.759 Y75.662 E0.501\nG1 X28.266 Y75.108 E0.502\nG1 X29.761 Y74.523 E0.502\nG1 X31.244 Y73.909 E0.502\nG1 X32.714 Y73.265 E0.502\nG1 X34.171 Y72.591 E0.502\nG1 X35.614 Y71.889 E0.501\nG1 X37.043 Y71.157 E0.502\nG1 X38.457 Y70.397 E0.502\nG1 X39.672 Y69.712 E0.436\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
-
-## Anycubic MEGA ZERO
-## Author: https://github.com/kad
-## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4057
-
-# Common print preset
-[print:*common_mega0*]
-avoid_crossing_perimeters = 1
-bridge_angle = 0
-bridge_flow_ratio = 0.7
-bridge_speed = 25
-brim_width = 0
-clip_multipart_objects = 1
-compatible_printers =
-complete_objects = 0
-dont_support_bridges = 1
-elefant_foot_compensation = 0
-ensure_vertical_shell_thickness = 1
-external_fill_pattern = rectilinear
-external_perimeters_first = 0
-external_perimeter_extrusion_width = 0.45
-extra_perimeters = 0
-extruder_clearance_height = 25
-extruder_clearance_radius = 45
-extrusion_width = 0.45
-fill_angle = 45
-fill_density = 20%
-fill_pattern = grid
-first_layer_extrusion_width = 0.42
-first_layer_height = 0.2
-first_layer_speed = 20
-gap_fill_speed = 30
-gcode_comments = 0
-infill_every_layers = 1
-infill_extruder = 1
-infill_extrusion_width = 0.45
-infill_first = 0
-infill_only_where_needed = 0
-infill_overlap = 25%
-interface_shells = 0
-max_print_speed = 100
-max_volumetric_extrusion_rate_slope_negative = 0
-max_volumetric_extrusion_rate_slope_positive = 0
-max_volumetric_speed = 0
-min_skirt_length = 4
-notes =
-overhangs = 1
-only_retract_when_crossing_perimeters = 0
-ooze_prevention = 0
-output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
-perimeters = 2
-perimeter_extruder = 1
-perimeter_extrusion_width = 0.45
-post_process =
-print_settings_id =
-raft_layers = 0
-resolution = 0
-seam_position = nearest
-single_extruder_multi_material_priming = 1
-skirts = 2
-skirt_distance = 2
-skirt_height = 2
-small_perimeter_speed = 25
-solid_infill_below_area = 0
-solid_infill_every_layers = 0
-solid_infill_extruder = 1
-solid_infill_extrusion_width = 0.45
-spiral_vase = 0
-standby_temperature_delta = -5
-support_material = 0
-support_material_extruder = 0
-support_material_extrusion_width = 0.4
-support_material_interface_extruder = 0
-support_material_angle = 0
-support_material_buildplate_only = 0
-support_material_enforce_layers = 0
-support_material_contact_distance = 0.15
-support_material_interface_contact_loops = 0
-support_material_interface_layers = 2
-support_material_interface_spacing = 0.2
-support_material_interface_speed = 100%
-support_material_pattern = rectilinear
-support_material_spacing = 2
-support_material_speed = 40
-support_material_synchronize_layers = 0
-support_material_threshold = 45
-support_material_with_sheath = 0
-support_material_xy_spacing = 60%
-thin_walls = 0
-top_infill_extrusion_width = 0.45
-top_solid_infill_speed = 40
-travel_speed = 100
-wipe_tower = 0
-wipe_tower_bridging = 10
-wipe_tower_rotation_angle = 0
-wipe_tower_width = 60
-wipe_tower_x = 170
-wipe_tower_y = 140
-xy_size_compensation = 0
-
-[print:*0.10mm_mega0*]
-inherits = *common_mega0*
-perimeter_speed = 40
-external_perimeter_speed = 25
-infill_speed = 50
-solid_infill_speed = 40
-layer_height = 0.10
-perimeters = 3
-top_infill_extrusion_width = 0.4
-bottom_solid_layers = 6
-top_solid_layers = 7
-
-[print:*0.20mm_mega0*]
-inherits = *common_mega0*
-perimeter_speed = 40
-external_perimeter_speed = 25
-infill_speed = 50
-solid_infill_speed = 40
-layer_height = 0.20
-top_infill_extrusion_width = 0.4
-bottom_solid_layers = 4
-top_solid_layers = 5
-
-[print:*0.30mm_mega0*]
-inherits = *common_mega0*
-perimeter_speed = 40
-external_perimeter_speed = 25
-infill_speed = 50
-solid_infill_speed = 40
-layer_height = 0.24
-top_infill_extrusion_width = 0.45
-bottom_solid_layers = 3
-top_solid_layers = 4
-
-[print:0.10mm DETAIL @MEGA0]
-inherits = *0.10mm_mega0*
-travel_speed = 120
-infill_speed = 50
-solid_infill_speed = 40
-top_solid_infill_speed = 30
-support_material_extrusion_width = 0.38
-compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
-
-[print:0.20mm NORMAL @MEGA0]
-inherits = *0.20mm_mega0*
-travel_speed = 120
-infill_speed = 50
-solid_infill_speed = 40
-top_solid_infill_speed = 30
-support_material_extrusion_width = 0.38
-compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
-
-[print:0.30mm DRAFT @MEGA0]
-inherits = *0.30mm_mega0*
-travel_speed = 120
-infill_speed = 50
-solid_infill_speed = 40
-top_solid_infill_speed = 30
-support_material_extrusion_width = 0.38
-compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
-
-# Common filament preset
-[filament:*common_mega0*]
-cooling = 0
-compatible_printers =
-extrusion_multiplier = 1
-filament_cost = 0
-filament_density = 0
-filament_diameter = 1.75
-filament_notes = ""
-filament_settings_id = ""
-filament_soluble = 0
-min_print_speed = 15
-slowdown_below_layer_time = 20
-compatible_printers_condition = printer_model=="MEGA0"
-
-[filament:*PLA_mega0*]
-inherits = *common_mega0*
-bed_temperature = 40
-fan_below_layer_time = 100
-filament_colour = #FF3232
-filament_max_volumetric_speed = 15
-filament_type = PLA
-filament_density = 1.24
-filament_cost = 20
-first_layer_bed_temperature = 40
-first_layer_temperature = 215
-fan_always_on = 1
-cooling = 1
-max_fan_speed = 100
-min_fan_speed = 100
-bridge_fan_speed = 100
-disable_fan_first_layers = 1
-temperature = 210
-
-[filament:*PET_mega0*]
-inherits = *common_mega0*
-bed_temperature = 70
-cooling = 1
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #FF8000
-filament_max_volumetric_speed = 8
-filament_type = PETG
-filament_density = 1.27
-filament_cost = 30
-first_layer_bed_temperature =70
-first_layer_temperature = 240
-fan_always_on = 1
-max_fan_speed = 50
-min_fan_speed = 20
-bridge_fan_speed = 100
-temperature = 240
-
-[filament:*ABS_mega0*]
-inherits = *common_mega0*
-bed_temperature = 100
-cooling = 0
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #3A80CA
-filament_max_volumetric_speed = 11
-filament_type = ABS
-filament_density = 1.04
-filament_cost = 20
-first_layer_bed_temperature = 100
-first_layer_temperature = 245
-fan_always_on = 0
-max_fan_speed = 0
-min_fan_speed = 0
-bridge_fan_speed = 30
-top_fan_speed = 0
-temperature = 245
-
-[filament:Generic PLA @MEGA0]
-inherits = *PLA_mega0*
-filament_vendor = Generic
-
-[filament:Generic PETG @MEGA0]
-inherits = *PET_mega0*
-filament_vendor = Generic
-
-[filament:Generic ABS @MEGA0]
-inherits = *ABS_mega0*
-filament_vendor = Generic
-
-[filament:Anycubic PLA @MEGA0]
-inherits = *PLA_mega0*
-filament_vendor = Anycubic
-temperature = 190
-first_layer_temperature = 195
-filament_cost = 24.99
-filament_density = 1.25
-
-[filament:Prusament PLA @MEGA0]
-inherits = *PLA_mega0*
-filament_vendor = Prusa Polymers
-temperature = 215
-bed_temperature = 40
-first_layer_temperature = 215
-filament_cost = 24.99
-filament_density = 1.24
-
-[filament:Prusament PETG @MEGA0]
-inherits = *PET_mega0*
-filament_vendor = Prusa Polymers
-temperature = 245
-bed_temperature = 70
-first_layer_temperature = 245
-filament_cost = 24.99
-filament_density = 1.27
-
-# Common printer preset
-[printer:*common_mega0*]
-printer_technology = FFF
-bed_shape = 0x0,220x0,220x220,0x220
-before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm
-between_objects_gcode =
-deretract_speed = 0
-extruder_colour = #FFFF00
-extruder_offset = 0x0
-gcode_flavor = marlin
-silent_mode = 0
-remaining_times = 0
-machine_max_acceleration_e = 10000
-machine_max_acceleration_extruding = 2000
-machine_max_acceleration_retracting = 1500
-machine_max_acceleration_x = 3000
-machine_max_acceleration_y = 3000
-machine_max_acceleration_z = 500
-machine_max_feedrate_e = 120
-machine_max_feedrate_x = 500
-machine_max_feedrate_y = 500
-machine_max_feedrate_z = 12
-machine_max_jerk_e = 2.5
-machine_max_jerk_x = 20
-machine_max_jerk_y = 20
-machine_max_jerk_z = 0.4
-machine_min_extruding_rate = 0
-machine_min_travel_rate = 0
-layer_gcode = ; AFTER_LAYER_CHANGE [layer_num] @ [layer_z]mm
-max_layer_height = 0.3
-min_layer_height = 0.1
-max_print_height = 200
-nozzle_diameter = 0.4
-printer_notes =
-printer_settings_id =
-retract_before_travel = 1
-retract_before_wipe = 0%
-retract_layer_change = 1
-retract_length = 6
-retract_length_toolchange = 1
-retract_lift = 0
-retract_lift_above = 0
-retract_lift_below = 0
-retract_restart_extra = 0
-retract_restart_extra_toolchange = 0
-retract_speed = 30
-single_extruder_multi_material = 0
-start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n
-end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM140 S0 ; turn off heatbed\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n
-toolchange_gcode =
-use_firmware_retraction = 0
-use_relative_e_distances = 1
-use_volumetric_e = 0
-variable_layer_height = 1
-wipe = 1
-z_offset = 0
-printer_model =
-default_print_profile =
-default_filament_profile =
-
-[printer:Anycubic Mega Zero]
-inherits = *common_mega0*
-printer_model = MEGA0
-printer_variant = 0.4
-max_layer_height = 0.3
-min_layer_height = 0.1
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0
-bed_shape = 0x0,220x0,220x220,0x220
-max_print_height = 250
-machine_max_acceleration_e = 5000
-machine_max_acceleration_extruding = 500
-machine_max_acceleration_retracting = 500
-machine_max_acceleration_x = 500
-machine_max_acceleration_y = 500
-machine_max_acceleration_z = 100
-machine_max_feedrate_e = 25
-machine_max_feedrate_x = 500
-machine_max_feedrate_y = 500
-machine_max_feedrate_z = 5
-machine_max_jerk_e = 5
-machine_max_jerk_x = 10
-machine_max_jerk_y = 10
-machine_max_jerk_z = 0.4
-machine_min_extruding_rate = 0
-machine_min_travel_rate = 0
-nozzle_diameter = 0.4
-retract_before_travel = 2
-retract_layer_change = 0
-retract_length = 7
-retract_speed = 30
-retract_lift = 0.2
-deretract_speed = 30
-retract_before_wipe = 70%
-default_print_profile = 0.20mm NORMAL @MEGA0
-default_filament_profile = Anycubic PLA @MEGA0
-start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n
-end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n
-
-## Anycubic i3 Mega and i3 Mega S
-## Author: https://github.com/Igami
-## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4619
-
-[print:*common_mega*]
-bottom_solid_min_thickness = 0.5
-bridge_acceleration = 1000
-bridge_flow_ratio = 0.95
-bridge_speed = 25
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ and nozzle_diameter[0]==0.4
-default_acceleration = 1000
-ensure_vertical_shell_thickness = 1
-external_perimeter_extrusion_width = 0.45
-external_perimeter_speed = 40
-extruder_clearance_height = 35
-extruder_clearance_radius = 60
-extrusion_width = 0.45
-fill_density = 15%
-fill_pattern = gyroid
-first_layer_acceleration = 800
-first_layer_extrusion_width = 0.42
-first_layer_height = 0.2
-first_layer_speed = 20
-gap_fill_speed = 40
-gcode_comments = 0
-gcode_label_objects = 1
-infill_acceleration = 1000
-infill_anchor = 2.5
-infill_anchor_max = 12
-infill_extrusion_width = 0.45
-max_print_speed = 100
-min_skirt_length = 4
-only_retract_when_crossing_perimeters = 0
-output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
-perimeter_acceleration = 800
-perimeter_extrusion_width = 0.45
-perimeter_speed = 50
-perimeters = 2
-seam_position = nearest
-skirt_distance = 2
-skirt_height = 3
-skirts = 1
-small_perimeter_speed = 25
-solid_infill_below_area = 0
-solid_infill_extrusion_width = 0.45
-solid_infill_speed = 50
-support_material = 0
-support_material_buildplate_only = 0
-support_material_contact_distance = 0.1
-support_material_extrusion_width = 0.35
-support_material_interface_layers = 2
-support_material_interface_spacing = 0.2
-support_material_interface_speed = 80%
-support_material_spacing = 2
-support_material_speed = 50
-support_material_threshold = 50
-support_material_xy_spacing = 60%
-thin_walls = 0
-top_infill_extrusion_width = 0.4
-top_solid_infill_speed = 40
-top_solid_min_thickness = 0.7
-travel_speed = 180
-
-# XXXXXXXXXXXXXXXXXXXX
-# XXX--- 0.15mm ---XXX
-# XXXXXXXXXXXXXXXXXXXX
-
-[print:*0.15mm_mega*]
-inherits = *common_mega*
-bottom_solid_layers = 5
-bridge_flow_ratio = 1
-infill_speed = 60
-layer_height = 0.15
-top_solid_layers = 7
-
-[print:0.15mm QUALITY @MEGA]
-inherits = *0.15mm_mega*
-
-# XXXXXXXXXXXXXXXXXXXX
-# XXX--- 0.20mm ---XXX
-# XXXXXXXXXXXXXXXXXXXX
-
-[print:*0.20mm_mega*]
-inherits = *common_mega*
-bottom_solid_layers = 4
-infill_speed = 60
-layer_height = 0.2
-top_solid_layers = 5
-
-[print:0.20mm QUALITY @MEGA]
-inherits = *0.20mm_mega*
-
-# XXXXXXXXXXXXXXXXXXXX
-# XXX--- 0.30mm ---XXX
-# XXXXXXXXXXXXXXXXXXXX
-
-[print:*0.30mm_mega*]
-inherits = *common_mega*
-bottom_solid_layers = 4
-external_perimeter_extrusion_width = 0.6
-external_perimeter_speed = 35
-extrusion_width = 0.5
-fill_pattern = cubic
-infill_extrusion_width = 0.5
-infill_speed = 85
-layer_height = 0.3
-perimeter_extrusion_width = 0.5
-small_perimeter_speed = 30
-solid_infill_extrusion_width = 0.5
-support_material_extrusion_width = 0.38
-support_material_speed = 45
-top_solid_layers = 4
-
-[print:0.30mm DRAFT @MEGA]
-inherits = *0.30mm_mega*
-
-# XXXXXXXXXXXXXXXXXXXXXX
-# XXX--- filament ---XXX
-# XXXXXXXXXXXXXXXXXXXXXX
-
-[filament:*common_mega*]
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
-end_filament_gcode = "; Filament-specific end gcode"
-fan_always_on = 1
-fan_below_layer_time = 100
-filament_vendor = Generic
-min_print_speed = 15
-slowdown_below_layer_time = 20
-
-[filament:*ABS_mega*]
- inherits = *common_mega*
- bed_temperature = 110
- bridge_fan_speed = 25
- cooling = 0
- fan_always_on = 0
- fan_below_layer_time = 20
- filament_colour = #3A80CA
- filament_cost = 27.82
- filament_density = 1.04
- filament_max_volumetric_speed = 11
- filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
- filament_type = ABS
- first_layer_bed_temperature = 105
- first_layer_temperature = 255
- max_fan_speed = 30
- min_fan_speed = 20
- temperature = 255
-
-[filament:Generic ABS @MEGA]
-inherits = *ABS_mega*
-
-[filament:*FLEX_mega*]
-inherits = *common_mega*
-bed_temperature = 50
-bridge_fan_speed = 80
-cooling = 0
-extrusion_multiplier = 1.15
-fan_always_on = 0
-filament_colour = #008000
-filament_cost = 82.00
-filament_density = 1.22
-filament_deretract_speed = 25
-filament_max_volumetric_speed = 1.2
-filament_retract_length = 0.8
-filament_type = FLEX
-first_layer_bed_temperature = 55
-first_layer_temperature = 240
-max_fan_speed = 90
-min_fan_speed = 70
-temperature = 240
-
-[filament:Generic FLEX @MEGA]
-inherits = *FLEX_mega*
-
-[filament:SainSmart TPU @MEGA]
-inherits = *FLEX_mega*
-filament_vendor = SainSmart
-bed_temperature = 50
-bridge_fan_speed = 100
-cooling = 1
-disable_fan_first_layers = 4
-filament_cost = 39.99
-filament_density = 1.21
-filament_deretract_speed = 15
-filament_max_volumetric_speed = 1.8
-filament_notes = "SainSmart TPU gains popularity among 3D Printing community for its balance of rigidity and flexibility. In addition, with a 95A Shore Hardness and improved bed adhesion, it is easier to print even with a stock elementary 3D Printer like the Creality Ender 3. SainSmart TPU will not disappoint if you are looking for flexible filament. From drone parts, phone cases, to small toys, all can be printed with ease.\n\nhttps://www.sainsmart.com/collections/tpu-filament/products/all-colors-tpu-flexible-filament-1-75mm-0-8kg-1-76lb"
-filament_retract_before_travel = 5
-filament_retract_length = 4
-filament_retract_speed = 40
-filament_unloading_speed = 90
-first_layer_bed_temperature = 55
-first_layer_temperature = 235
-full_fan_speed_layer = 6
-max_fan_speed = 80
-min_fan_speed = 80
-slowdown_below_layer_time = 10
-temperature = 235
-
-[filament:*PETG_mega*]
-inherits = *common_mega*
-bed_temperature = 90
-bridge_fan_speed = 50
-fan_below_layer_time = 20
-filament_colour = #FF8000
-filament_cost = 27.82
-filament_density = 1.27
-filament_max_volumetric_speed = 8
-filament_type = PETG
-first_layer_bed_temperature = 90
-first_layer_temperature = 230
-max_fan_speed = 50
-min_fan_speed = 30
-temperature = 240
-
-[filament:Generic PETG @MEGA]
-inherits = *PETG_mega*
-
-[filament:ColorFabb XT-CF20 @MEGA]
-inherits = *PETG_mega*
-compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
-extrusion_multiplier = 1.05
-filament_colour = #804040
-filament_cost = 66.60
-filament_density = 1.35
-filament_deretract_speed = 25
-filament_max_volumetric_speed = 2
-filament_notes = "Based on colorFabb_XT, XT-CF20 is a carbon fiber composite material. Loaded with no less than 20% specially sourced carbon fibers we have developed a very stiff and tough 3D printing filament made for functional parts. It is truly a professional printers go-to material, especially for users looking for high melt strength, high melt viscosity and good dimensional accuracy and stability.\n\nhttps://colorfabb.com/xt-cf20"
-filament_retract_before_travel = 1
-filament_retract_length = 1.4
-filament_retract_speed = 40
-filament_spool_weight = 236
-filament_vendor = ColorFabb
-first_layer_temperature = 260
-full_fan_speed_layer = 5
-slowdown_below_layer_time = 15
-temperature = 260
-
-[filament:ERYONE PETG @MEGA]
-inherits = *PETG_mega*
-filament_vendor = ERYONE
-filament_cost = 20.99
-filament_notes = "https://eryone.com/petg/show/10.html"
-
-[filament:FormFutura HDglass @MEGA]
-inherits = *PETG_mega*
-filament_vendor = FormFutura
-filament_cost = 46.65
-filament_notes = "HDglass is a high performance PETG type of 3D printer with unsurpassed 3D printing properties and improved mechanical strength, flexibility, toughness and heat resistance.\n\nhttps://www.formfutura.com/shop/product/hdglass-2812"
-
-[filament:FormFutura ReForm rPET @MEGA]
-inherits = *PETG_mega*
-filament_vendor = FormFutura
-filament_cost = 26.65
-filament_notes = "ReForm rPET is a recycled PETG type of 3D printer filament that is made from post-industrial waste streams of a nearby located plastic bottle manufacturer.\n\nhttps://www.formfutura.com/shop/product/reform-rpet-2836"
-filament_spool_weight = 176
-
-[filament:Janbex transparent PETG @MEGA]
-inherits = *PETG_mega*
-filament_vendor = Janbex
-filament_cost = 31.99
-filament_spool_weight = 222
-first_layer_temperature = 215
-min_fan_speed = 100
-temperature = 210
-
-[filament:DAS FILAMENT PETG @MEGA]
-inherits = *PETG_mega*
-filament_vendor = DAS FILAMENT
-bed_temperature = 75
-first_layer_bed_temperature = 75
-first_layer_temperature = 220
-temperature = 225
-
-[filament:*PLA_mega*]
-inherits = *common_mega*
-bed_temperature = 60
-disable_fan_first_layers = 1
-filament_colour = #FF3232
-filament_cost = 25.40
-filament_density = 1.24
-filament_max_volumetric_speed = 10
-first_layer_bed_temperature = 65
-first_layer_temperature = 215
-min_fan_speed = 100
-temperature = 210
-
-[filament:Generic PLA @MEGA]
-inherits = *PLA_mega*
-
-[filament:3Dmensionals PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = 3Dmensionals
-filament_cost = 22.90
-filament_notes = "Das 3DFilaments - PLA von 3Dmensionals ist ein sehr leicht zu druckendes 3D-Drucker Filament. Dabei handelt es sich um ein etwas härteres PLA mit einer exzellenten thermischen Stabilität. Das Filament zeichnet sich vor allem durch verzugfreies 3D-Drucken aus und weist minimale bis keine Verformung nach dem Abkühlen auf. Daher ist es besonders gut für den Druck größerer Objekte geeignet. Zudem bietet 3DFilaments - PLA über die gesamte Fadenläge eine hervorragende Durchmesser- und Rundheitstoleranz.\n\nhttps://www.3dmensionals.de/3dfilaments?number=PSU3DM001V"
-
-[filament:3D Warhorse PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = 3D Warhorse
-filament_cost = 19.99
-
-[filament:AMOLEN wood PLA]
-inherits = *PLA_mega*
-filament_vendor = AMOLEN
-compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
-extrusion_multiplier = 1.1
-filament_colour = #DFC287
-filament_cost = 33.99
-filament_density = 1.23
-filament_max_volumetric_speed = 9
-filament_notes = "https://amolen.com/collections/wood/products/amolen-pla-filament-1-75mm-wood-color-3d-printer-filament-1kg2-2lb"
-
-[filament:FormFutura EasyFil PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = FormFutura
-filament_cost = 39.93
-filament_notes = "EasyFil PLA is an easy to print PLA type of 3D printer filament that is available in a wide variety of colors. Its improved flowing behavior make 3D printed layers flow more into each other.\n\nhttps://www.formfutura.com/shop/product/easyfil-pla-2801"
-
-[filament:FormFutura ReForm rPLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = FormFutura
-filament_cost = 26.65
-filament_notes = "ReForm is a sustainable initiative within Formfutura to efficiently manage residual extrusion waste streams and re-use them into high-end upcycled filaments. The ideology behind ReForm is to a make 3D printing more sustainable – without having to make compromises on material properties – and yet keep it affordable.\n\nhttps://www.formfutura.com/shop/product/reform-rpla-2838"
-
-[filament:GIANTARM PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = GIANTARM
-filament_cost = 24.99
-
-[filament:Prusament PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = Prusa Polymers
-filament_cost = 30.24
-filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa"
-filament_spool_weight = 201
-temperature = 215
-
-[filament:Verbatim PLA @MEGA]
-inherits = *PLA_mega*
-filament_vendor = Verbatim
-filament_cost = 23.88
-
-[printer:*common_mega*]
-printer_technology = FFF
-bed_shape = 0x0,210x0,210x210,0x210
-before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]
-default_filament_profile = Generic PLA @MEGA
-default_print_profile = 0.15mm QUALITY @MEGA
-deretract_speed = 50
-end_gcode = G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-34.0 F720 ; move print head up & retract filament\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors
-extruder_colour = #808080
-gcode_flavor = marlin
-layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
-max_layer_height = 0.36
-max_print_height = 205
-remaining_times = 1
-retract_before_travel = 1.5
-retract_before_wipe = 60%
-retract_layer_change = 1
-retract_length = 6
-retract_lift = 0.075
-retract_lift_below = 204
-retract_speed = 40
-silent_mode = 0
-start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y1.0 Z0.3 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\n; initial load\nG1 X205.0 E19 F1000\nG1 Y1.6\nG1 X5.0 E19 F1000\nG92 E0.0\n; intro line\nG1 Y2.0 Z0.2 F1000\nG1 X65.0 E9.0 F1000\nG1 X105.0 E12.5 F1000\nG92 E0.0
-thumbnails = 16x16,220x124
-use_relative_e_distances = 1
-wipe = 1
-machine_max_acceleration_e = 10000
-machine_max_acceleration_extruding = 1250
-machine_max_acceleration_retracting = 1250
-machine_max_acceleration_x = 3000
-machine_max_acceleration_y = 2000
-machine_max_acceleration_z = 60
-machine_max_feedrate_e = 60
-machine_max_feedrate_x = 500
-machine_max_feedrate_y = 500
-machine_max_feedrate_z = 6
-machine_max_jerk_e = 5
-machine_max_jerk_x = 10
-machine_max_jerk_y = 10
-machine_max_jerk_z = 0.4
-
-[printer:Anycubic i3 Mega]
-inherits = *common_mega*
-printer_model = I3MEGA
-printer_variant = 0.4
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA\nPRINTER_HAS_BOWDEN
-
-[printer:Anycubic i3 Mega S]
-inherits = *common_mega*
-printer_model = I3MEGAS
-printer_variant = 0.4
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA_S\nPRINTER_HAS_BOWDEN
-machine_max_feedrate_e = 30
-machine_max_feedrate_z = 8
-
-
-## Anycubic PREDATOR
-## Author: https://github.com/tillverka3d
-## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4960
-
-#########################################
-###### begin common print presets #######
-#########################################
-
-# Common print preset
-[print:*common predator*]
-spiral_vase = 0
-top_solid_min_thickness = 0.8
-bottom_solid_min_thickness = 0.6
-extra_perimeters = 0
-ensure_vertical_shell_thickness = 1
-avoid_crossing_perimeters = 0
-thin_walls = 0
-overhangs = 1
-seam_position = nearest
-external_perimeters_first = 0
-fill_density = 20%
-external_fill_pattern = rectilinear
-infill_every_layers = 1
-infill_only_where_needed = 0
-solid_infill_every_layers = 0
-fill_angle = 45
-solid_infill_below_area = 20
-bridge_angle = 0
-only_retract_when_crossing_perimeters = 0
-infill_first = 0
-skirts = 1
-skirt_distance = 4
-skirt_height = 1
-min_skirt_length = 8
-brim_width = 0
-support_material = 0
-support_material_auto = 1
-support_material_threshold = 50
-support_material_enforce_layers = 0
-raft_layers = 0
-support_material_contact_distance = 0.1
-support_material_pattern = rectilinear
-support_material_with_sheath = 0
-support_material_spacing = 2
-support_material_angle = 0
-support_material_interface_layers = 2
-support_material_interface_spacing = 0.2
-support_material_interface_contact_loops = 0
-support_material_buildplate_only = 0
-support_material_xy_spacing = 60%
-dont_support_bridges = 1
-support_material_synchronize_layers = 0
-travel_speed = 94
-first_layer_speed = 15
-perimeter_acceleration = 0
-infill_acceleration = 0
-bridge_acceleration = 0
-first_layer_acceleration = 0
-default_acceleration = 0
-max_volumetric_speed = 15
-perimeter_extruder = 1
-infill_extruder = 1
-solid_infill_extruder = 1
-support_material_extruder = 0
-support_material_interface_extruder = 0
-ooze_prevention = 0
-standby_temperature_delta = -5
-wipe_tower = 0
-wipe_tower_x = 170
-wipe_tower_y = 140
-wipe_tower_width = 60
-wipe_tower_rotation_angle = 0
-wipe_tower_bridging = 10
-interface_shells = 0
-bridge_flow_ratio = 0.8
-resolution = 0
-xy_size_compensation = 0
-elefant_foot_compensation = 0.2
-clip_multipart_objects = 1
-complete_objects = 0
-extruder_clearance_radius = 45
-extruder_clearance_height = 25
-gcode_comments = 0
-output_filename_format = {input_filename_base}.gcode
-post_process =
-notes =
-max_volumetric_extrusion_rate_slope_negative = 0
-max_volumetric_extrusion_rate_slope_positive = 0
-print_settings_id =
-
-# Common print preset
-[print:*common predator 0.4 nozzle*]
-inherits = *common predator*
-first_layer_height = 0.16
-infill_overlap = 25%
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.4
-
-# Common print preset
-[print:*common predator 0.6 nozzle*]
-inherits = *common predator*
-first_layer_height = 0.24
-infill_overlap = 27%
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.6
-
-# Common print preset
-[print:*common predator 0.8 nozzle*]
-inherits = *common predator*
-first_layer_height = 0.32
-infill_overlap = 30%
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.8
-
-# Common print preset
-[print:*common predator quality*]
-perimeter_speed = 50
-small_perimeter_speed = 15
-external_perimeter_speed = 70%
-infill_speed = 65
-solid_infill_speed = 85%
-top_solid_infill_speed = 85%
-support_material_speed = 30
-support_material_interface_speed = 85%
-bridge_speed = 30
-gap_fill_speed = 40
-ironing_speed = 15
-
-# Common print preset
-[print:*common predator speed*]
-perimeter_speed = 70
-small_perimeter_speed = 15
-external_perimeter_speed = 70%
-infill_speed = 85
-solid_infill_speed = 85%
-top_solid_infill_speed = 85%
-support_material_speed = 30
-support_material_interface_speed = 85%
-bridge_speed = 30
-gap_fill_speed = 40
-ironing_speed = 15
-
-# Common print preset
-[print:*common predator 0.4 nozzle detailed*]
-inherits = *common predator 0.4 nozzle*
-extrusion_width = 0.42
-first_layer_extrusion_width = 0.41
-perimeter_extrusion_width = 0.42
-external_perimeter_extrusion_width = 0.42
-infill_extrusion_width = 0.4
-solid_infill_extrusion_width = 0.4
-top_infill_extrusion_width = 0.4
-support_material_extrusion_width = 0.38
-
-# Common print preset
-[print:*common predator 0.4 nozzle coarse*]
-inherits = *common predator 0.4 nozzle*
-extrusion_width = 0.44
-first_layer_extrusion_width = 0.42
-perimeter_extrusion_width = 0.5
-external_perimeter_extrusion_width = 0.5
-infill_extrusion_width = 0.5
-solid_infill_extrusion_width = 0.5
-top_infill_extrusion_width = 0.4
-support_material_extrusion_width = 0.38
-
-# Common print preset
-[print:*common predator 0.6 nozzle detailed*]
-inherits = *common predator 0.6 nozzle*
-extrusion_width = 0.64
-first_layer_extrusion_width = 0.62
-perimeter_extrusion_width = 0.64
-external_perimeter_extrusion_width = 0.64
-infill_extrusion_width = 0.6
-solid_infill_extrusion_width = 0.6
-top_infill_extrusion_width = 0.6
-support_material_extrusion_width = 0.56
-
-# Common print preset
-[print:*common predator 0.6 nozzle coarse*]
-inherits = *common predator 0.6 nozzle*
-extrusion_width = 0.67
-first_layer_extrusion_width = 0.64
-perimeter_extrusion_width = 0.7
-external_perimeter_extrusion_width = 0.7
-infill_extrusion_width = 0.7
-solid_infill_extrusion_width = 0.7
-top_infill_extrusion_width = 0.6
-support_material_extrusion_width = 0.56
-
-# Common print preset
-[print:*common predator 0.8 nozzle detailed*]
-inherits = *common predator 0.8 nozzle*
-extrusion_width = 0.84
-first_layer_extrusion_width = 0.82
-perimeter_extrusion_width = 0.84
-external_perimeter_extrusion_width = 0.84
-infill_extrusion_width = 0.8
-solid_infill_extrusion_width = 0.8
-top_infill_extrusion_width = 0.8
-support_material_extrusion_width = 0.72
-
-# Common print preset
-[print:*common predator 0.8 nozzle coarse*]
-inherits = *common predator 0.8 nozzle*
-extrusion_width = 0.87
-first_layer_extrusion_width = 0.84
-perimeter_extrusion_width = 0.9
-external_perimeter_extrusion_width = 0.9
-infill_extrusion_width = 0.9
-solid_infill_extrusion_width = 0.9
-top_infill_extrusion_width = 0.8
-support_material_extrusion_width = 0.72
-
-#########################################
-####### end common print presets ########
-#########################################
-
-#########################################
-########## begin print presets ##########
-#########################################
-
-[print:0.08mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
-layer_height = 0.08
-max_print_speed = 50
-perimeters = 3
-fill_pattern = grid
-
-[print:0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
-layer_height = 0.16
-max_print_speed = 60
-perimeters = 3
-fill_pattern = grid
-
-[print:0.16mm 0.4 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
-layer_height = 0.16
-max_print_speed = 60
-perimeters = 3
-fill_pattern = grid
-
-[print:0.24mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 70
-perimeters = 3
-fill_pattern = grid
-
-[print:0.24mm 0.4 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 70
-perimeters = 3
-fill_pattern = grid
-
-[print:0.32mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 70
-perimeters = 3
-fill_pattern = grid
-
-[print:0.32mm 0.4 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 70
-perimeters = 3
-fill_pattern = grid
-
-[print:0.16mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
-layer_height = 0.16
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.16mm 0.6 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
-layer_height = 0.16
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.16mm 0.6 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
-layer_height = 0.16
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.16mm 0.6 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
-layer_height = 0.16
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.6 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
-layer_height = 0.24
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.6 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.6 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
-layer_height = 0.24
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.6 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
-layer_height = 0.32
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.6 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.6 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
-layer_height = 0.32
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
-layer_height = 0.4
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.6 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
-layer_height = 0.4
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.6 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
-layer_height = 0.4
-max_print_speed = 70
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.6 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
-layer_height = 0.4
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.8 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
-layer_height = 0.24
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.8 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
-layer_height = 0.24
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.24mm 0.8 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
-layer_height = 0.24
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.8 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
-layer_height = 0.32
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.8 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
-layer_height = 0.32
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.32mm 0.8 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
-layer_height = 0.32
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
-layer_height = 0.4
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.8 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
-layer_height = 0.4
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.8 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
-layer_height = 0.4
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.4mm 0.8 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
-layer_height = 0.4
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.48mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
-layer_height = 0.48
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.48mm 0.8 nozzle DETAILED SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
-layer_height = 0.48
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.48mm 0.8 nozzle COARSE QUALITY @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
-layer_height = 0.48
-max_print_speed = 80
-perimeters = 2
-fill_pattern = gyroid
-
-[print:0.48mm 0.8 nozzle COARSE SPEED @PREDATOR]
-inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
-layer_height = 0.48
-max_print_speed = 90
-perimeters = 2
-fill_pattern = gyroid
-
-#########################################
-########### end print presets ###########
-#########################################
-
-#########################################
-######## begin filament presets #########
-#########################################
-
-# Common filament preset
-[filament:*common predator*]
-cooling = 0
-compatible_printers =
-extrusion_multiplier = 1
-filament_cost = 0
-filament_density = 0
-filament_diameter = 1.75
-filament_notes = ""
-filament_settings_id = ""
-filament_soluble = 0
-min_print_speed = 15
-slowdown_below_layer_time = 20
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/
-
-[filament:*PLA predator*]
-inherits = *common predator*
-bed_temperature = 60
-fan_below_layer_time = 100
-filament_colour = #FF3232
-filament_max_volumetric_speed = 10
-filament_type = PLA
-filament_density = 1.24
-filament_cost = 20
-first_layer_bed_temperature = 60
-first_layer_temperature = 200
-fan_always_on = 1
-cooling = 1
-max_fan_speed = 100
-min_fan_speed = 100
-bridge_fan_speed = 100
-disable_fan_first_layers = 1
-temperature = 200
-
-[filament:*PET predator*]
-inherits = *common predator*
-bed_temperature = 70
-cooling = 1
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #FF8000
-filament_max_volumetric_speed = 8
-filament_type = PETG
-filament_density = 1.27
-filament_cost = 30
-first_layer_bed_temperature =70
-first_layer_temperature = 240
-fan_always_on = 1
-max_fan_speed = 50
-min_fan_speed = 20
-bridge_fan_speed = 100
-temperature = 240
-
-[filament:*ABS predator*]
-inherits = *common predator*
-bed_temperature = 100
-cooling = 0
-disable_fan_first_layers = 3
-fan_below_layer_time = 20
-filament_colour = #3A80CA
-filament_max_volumetric_speed = 10
-filament_type = ABS
-filament_density = 1.04
-filament_cost = 20
-first_layer_bed_temperature = 100
-first_layer_temperature = 245
-fan_always_on = 0
-max_fan_speed = 0
-min_fan_speed = 0
-bridge_fan_speed = 30
-top_fan_speed = 0
-temperature = 245
-
-[filament:Generic PLA @PREDATOR]
-inherits = *PLA predator*
-filament_vendor = Generic
-
-[filament:Generic PETG @PREDATOR]
-inherits = *PET predator*
-filament_vendor = Generic
-
-[filament:Generic ABS @PREDATOR]
-inherits = *ABS predator*
-filament_vendor = Generic
-
-#########################################
-######### end filament presets ##########
-#########################################
-
-#########################################
-######### begin printer presets #########
-#########################################
-
-# Anycubic predator common printer preset
-[printer:*common predator*]
-printer_vendor = Anycubic
-printer_model = Predator
-printer_technology = FFF
-printer_variant = 0.4
-thumbnails = 16x16,220x124
-bed_shape = 188.779x16.516,186.621x32.9063,183.043x49.0462,178.072x64.8128,171.745x80.0862,164.112x94.75,155.229x108.693,145.165x121.808,133.997x133.997,121.808x145.165,108.693x155.229,94.75x164.112,80.0862x171.745,64.8128x178.072,49.0462x183.043,32.9063x186.621,16.516x188.779,1.16035e-14x189.5,-16.516x188.779,-32.9063x186.621,-49.0462x183.043,-64.8128x178.072,-80.0862x171.745,-94.75x164.112,-108.693x155.229,-121.808x145.165,-133.997x133.997,-145.165x121.808,-155.229x108.693,-164.112x94.75,-171.745x80.0862,-178.072x64.8128,-183.043x49.0462,-186.621x32.9063,-188.779x16.516,-189.5x2.32071e-14,-188.779x-16.516,-186.621x-32.9063,-183.043x-49.0462,-178.072x-64.8128,-171.745x-80.0862,-164.112x-94.75,-155.229x-108.693,-145.165x-121.808,-133.997x-133.997,-121.808x-145.165,-108.693x-155.229,-94.75x-164.112,-80.0862x-171.745,-64.8128x-178.072,-49.0462x-183.043,-32.9063x-186.621,-16.516x-188.779,-3.48106e-14x-189.5,16.516x-188.779,32.9063x-186.621,49.0462x-183.043,64.8128x-178.072,80.0862x-171.745,94.75x-164.112,108.693x-155.229,121.808x-145.165,133.997x-133.997,145.165x-121.808,155.229x-108.693,164.112x-94.75,171.745x-80.0862,178.072x-64.8128,183.043x-49.0462,186.621x-32.9063,188.779x-16.516,189.5x-4.64141e-14
-max_print_height = 445
-z_offset = 0
-single_extruder_multi_material = 0
-gcode_flavor = reprap
-silent_mode = 0
-remaining_times = 0
-use_relative_e_distances = 0
-use_firmware_retraction = 0
-use_volumetric_e = 0
-variable_layer_height = 1
-start_gcode = ; start_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; set metric values\n\nG21\n\n; use absolute positioning\n\nG90\n\n; set extruder to absolute mode\n\nM82\n\n; start with fan off\n\nM107\n\n; set temps\n\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\n\n; home xy\n\nG28 X0 Y0\n\n; home z\n\nG28 Z0\n\n; move the head down to Z 94mm\n\nG1 Z94.0 F2394\n\n; set and wait for temps\n\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\n\n; zero the extruded length\n\nG92 E0\n\n; extrude 3mm of feed stock\n\nG1 F200 E3\n\n; zero the extruded length again\n\nG92 E0\n\n; set speed\n\nG1 F{travel_speed}\n\n; print preskirt\n\nG92 E0\nG1 E3.94000 F2520.00000\n\nG1 X125.464 Y-139.310\nG1 Z0.329 F3994.000\n\nG1 F994.000\n\nG1 X125.464 Y-139.310 E4.19679\nG1 X130.218 Y-134.876 E4.70359\nG1 X132.569 Y-132.567 E4.96053\nG1 X137.099 Y-127.877 E5.46890\nG1 X139.325 Y-125.447 E5.72585\nG1 X141.507 Y-122.981 E5.98254\nG1 X145.685 Y-118.002 E6.48934\nG1 X149.741 Y-112.810 E7.00296\nG1 X153.561 Y-107.552 E7.50975\nG1 X155.440 Y-104.819 E7.76827\nG1 X158.980 Y-99.367 E8.27506\nG1 X160.702 Y-96.558 E8.53201\nG1 X163.962 Y-90.911 E9.04038\nG1 X165.535 Y-88.015 E9.29732\nG1 X168.496 Y-82.205 E9.80570\nG1 X169.915 Y-79.231 E10.06264\nG1 X171.280 Y-76.235 E10.31934\nG1 X173.819 Y-70.251 E10.82613\nG1 X176.180 Y-64.101 E11.33975\nG1 X178.297 Y-57.955 E11.84654\nG1 X179.294 Y-54.793 E12.10507\nG1 X181.085 Y-48.544 E12.61186\nG1 X181.911 Y-45.354 E12.86880\nG1 X183.378 Y-39.001 E13.37718\nG1 X184.035 Y-35.771 E13.63412\nG1 X185.168 Y-29.350 E14.14250\nG1 X185.655 Y-26.091 E14.39944\nG1 X186.084 Y-22.826 E14.65614\nG1 X186.764 Y-16.362 E15.16293\nG1 X187.223 Y-9.790 E15.67655\nG1 X187.450 Y-3.294 E16.18334\nG1 X187.479 Y0.002 E16.44028\nG1 X187.450 Y3.294 E16.69698\nG1 X187.223 Y9.810 E17.20529\nG1 X187.021 Y13.100 E17.46229\nG1 X186.454 Y19.575 E17.96909\nG1 X186.079 Y22.870 E18.22761\nG1 X185.174 Y29.307 E18.73440\nG1 X184.031 Y35.794 E19.24802\nG1 X182.679 Y42.152 E19.75481\nG1 X181.910 Y45.357 E20.01176\nG1 X180.223 Y51.655 E20.52013\nG1 X179.287 Y54.815 E20.77708\nG1 X177.272 Y61.017 E21.28545\nG1 X176.172 Y64.123 E21.54239\nG1 X175.019 Y67.207 E21.79909\nG1 X172.584 Y73.234 E22.30588\nG1 X169.905 Y79.252 E22.81950\nG1 X167.055 Y85.094 E23.32629\nG1 X165.524 Y88.035 E23.58482\nG1 X162.373 Y93.721 E24.09161\nG1 X160.700 Y96.560 E24.34855\nG1 X157.245 Y102.090 E24.85693\nG1 X155.427 Y104.838 E25.11387\nG1 X151.687 Y110.180 E25.62225\nG1 X149.727 Y112.829 E25.87919\nG1 X147.722 Y115.441 E26.13588\nG1 X143.631 Y120.493 E26.64268\nG1 X139.310 Y125.464 E27.15629\nG1 X134.876 Y130.218 E27.66309\nG1 X132.567 Y132.569 E27.92003\nG1 X127.877 Y137.099 E28.42840\nG1 X125.447 Y139.325 E28.68535\nG1 X122.981 Y141.507 E28.94204\nG1 X118.002 Y145.685 E29.44883\nG1 X112.810 Y149.741 E29.96245\nG1 X107.552 Y153.561 E30.46924\nG1 X104.819 Y155.440 E30.72777\nG1 X99.367 Y158.980 E31.23456\nG1 X96.558 Y160.702 E31.49151\nG1 X90.911 Y163.962 E31.99988\nG1 X88.015 Y165.535 E32.25682\nG1 X82.205 Y168.496 E32.76520\nG1 X79.231 Y169.915 E33.02214\nG1 X76.235 Y171.280 E33.27884\nG1 X70.251 Y173.819 E33.78563\nG1 X64.101 Y176.180 E34.29925\nG1 X57.955 Y178.297 E34.80604\nG1 X54.793 Y179.294 E35.06457\nG1 X48.544 Y181.085 E35.57136\nG1 X45.354 Y181.911 E35.82830\nG1 X39.001 Y183.378 E36.33668\nG1 X35.771 Y184.035 E36.59362\nG1 X29.350 Y185.168 E37.10200\nG1 X26.091 Y185.655 E37.35894\nG1 X22.826 Y186.084 E37.61563\nG1 X16.362 Y186.764 E38.12242\nG1 X9.790 Y187.223 E38.63605\nG1 X3.294 Y187.450 E39.14283\nG1 X-0.002 Y187.479 E39.39978\nG1 X-3.294 Y187.450 E39.65648\nG1 X-9.810 Y187.223 E40.16479\nG1 X-13.100 Y187.021 E40.42179\nG1 X-19.575 Y186.454 E40.92858\nG1 X-22.870 Y186.079 E41.18711\nG1 X-29.307 Y185.174 E41.69390\nG1 X-35.794 Y184.031 E42.20752\nG1 X-42.152 Y182.679 E42.71431\nG1 X-45.357 Y181.910 E42.97126\nG1 X-51.655 Y180.223 E43.47963\nG1 X-54.815 Y179.287 E43.73657\nG1 X-61.017 Y177.272 E44.24495\nG1 X-64.123 Y176.172 E44.50189\nG1 X-67.207 Y175.019 E44.75859\nG1 X-73.234 Y172.584 E45.26538\nG1 X-79.252 Y169.905 E45.77900\nG1 X-85.094 Y167.055 E46.28579\nG1 X-88.035 Y165.524 E46.54432\nG1 X-93.721 Y162.373 E47.05111\nG1 X-96.560 Y160.700 E47.30805\nG1 X-102.090 Y157.245 E47.81643\nG1 X-104.838 Y155.427 E48.07337\nG1 X-110.180 Y151.687 E48.58174\nG1 X-112.829 Y149.727 E48.83869\nG1 X-115.441 Y147.722 E49.09538\nG1 X-120.493 Y143.631 E49.60218\nG1 X-125.464 Y139.310 E50.11579\nG1 X-130.218 Y134.876 E50.62259\nG1 X-132.569 Y132.567 E50.87953\nG1 X-137.099 Y127.877 E51.38790\nG1 X-139.325 Y125.447 E51.64485\nG1 X-141.507 Y122.981 E51.90154\nG1 X-145.685 Y118.002 E52.40833\nG1 X-149.741 Y112.810 E52.92195\nG1 X-153.561 Y107.552 E53.42874\nG1 X-155.440 Y104.819 E53.68727\nG1 X-158.980 Y99.367 E54.19406\nG1 X-160.702 Y96.558 E54.45101\nG1 X-163.962 Y90.911 E54.95938\nG1 X-165.535 Y88.015 E55.21632\nG1 X-168.496 Y82.205 E55.72470\nG1 X-169.915 Y79.231 E55.98164\nG1 X-171.280 Y76.235 E56.23834\nG1 X-173.819 Y70.251 E56.74513\nG1 X-176.180 Y64.101 E57.25875\nG1 X-178.297 Y57.955 E57.76554\nG1 X-179.294 Y54.793 E58.02407\nG1 X-181.085 Y48.544 E58.53086\nG1 X-181.911 Y45.354 E58.78780\nG1 X-183.378 Y39.001 E59.29618\nG1 X-184.035 Y35.771 E59.55312\nG1 X-185.168 Y29.350 E60.06149\nG1 X-185.655 Y26.091 E60.31844\nG1 X-186.084 Y22.826 E60.57513\nG1 X-186.764 Y16.362 E61.08192\nG1 X-187.223 Y9.790 E61.59554\nG1 X-187.450 Y3.294 E62.10233\nG1 X-187.479 Y-0.002 E62.35928\nG1 X-187.450 Y-3.294 E62.61598\nG1 X-187.223 Y-9.810 E63.12429\nG1 X-187.021 Y-13.100 E63.38129\nG1 X-186.454 Y-19.575 E63.88808\nG1 X-186.079 Y-22.870 E64.14661\nG1 X-185.174 Y-29.307 E64.65340\nG1 X-184.031 Y-35.794 E65.16702\nG1 X-182.679 Y-42.152 E65.67381\nG1 X-181.910 Y-45.357 E65.93076\nG1 X-180.223 Y-51.655 E66.43913\nG1 X-179.287 Y-54.815 E66.69607\nG1 X-177.272 Y-61.017 E67.20445\nG1 X-176.172 Y-64.123 E67.46139\nG1 X-175.019 Y-67.207 E67.71809\nG1 X-172.584 Y-73.234 E68.22488\nG1 X-169.905 Y-79.252 E68.73850\nG1 X-167.055 Y-85.094 E69.24529\nG1 X-165.524 Y-88.035 E69.50382\nG1 X-162.373 Y-93.721 E70.01061\nG1 X-160.700 Y-96.560 E70.26755\nG1 X-157.245 Y-102.090 E70.77593\nG1 X-155.427 Y-104.838 E71.03287\nG1 X-151.687 Y-110.180 E71.54124\nG1 X-149.727 Y-112.829 E71.79819\nG1 X-147.722 Y-115.441 E72.05488\nG1 X-143.631 Y-120.493 E72.56167\nG1 X-139.310 Y-125.464 E73.07529\nG1 X-134.876 Y-130.218 E73.58209\nG1 X-132.567 Y-132.569 E73.83903\nG1 X-127.877 Y-137.099 E74.34740\nG1 X-125.447 Y-139.325 E74.60435\nG1 X-122.981 Y-141.507 E74.86104\nG1 X-118.002 Y-145.685 E75.36783\nG1 X-112.810 Y-149.741 E75.88145\nG1 X-107.552 Y-153.561 E76.38824\nG1 X-104.819 Y-155.440 E76.64677\nG1 X-99.367 Y-158.980 E77.15356\nG1 X-96.558 Y-160.702 E77.41051\nG1 X-90.911 Y-163.962 E77.91888\nG1 X-88.015 Y-165.535 E78.17582\nG1 X-82.205 Y-168.496 E78.68420\nG1 X-79.231 Y-169.915 E78.94114\nG1 X-76.235 Y-171.280 E79.19784\nG1 X-70.251 Y-173.819 E79.70463\nG1 X-64.101 Y-176.180 E80.21825\nG1 X-57.955 Y-178.297 E80.72504\nG1 X-54.793 Y-179.294 E80.98356\nG1 X-48.544 Y-181.085 E81.49036\nG1 X-45.354 Y-181.911 E81.74730\nG1 X-39.001 Y-183.378 E82.25568\nG1 X-35.771 Y-184.035 E82.51262\nG1 X-29.350 Y-185.168 E83.02099\nG1 X-26.091 Y-185.655 E83.27794\nG1 X-22.826 Y-186.084 E83.53463\nG1 X-16.362 Y-186.764 E84.04142\nG1 X-9.790 Y-187.223 E84.55504\nG1 X-3.294 Y-187.450 E85.06183\nG1 X0.006 Y-187.479 E85.31908\nG1 X6.521 Y-187.366 E85.82715\nG1 X9.810 Y-187.223 E86.08379\nG1 X13.100 Y-187.021 E86.34079\nG1 X19.575 Y-186.454 E86.84758\nG1 X22.870 Y-186.079 E87.10611\nG1 X29.307 Y-185.174 E87.61290\nG1 X35.794 Y-184.031 E88.12652\nG1 X42.152 Y-182.679 E88.63331\nG1 X45.357 Y-181.910 E88.89025\nG1 X51.655 Y-180.223 E89.39863\nG1 X54.815 Y-179.287 E89.65557\nG1 X61.017 Y-177.272 E90.16395\nG1 X64.123 Y-176.172 E90.42089\nG1 X67.207 Y-175.019 E90.67759\nG1 X73.234 Y-172.584 E91.18438\nG1 X79.252 Y-169.905 E91.69800\nG1 X85.094 Y-167.055 E92.20479\nG1 X88.035 Y-165.524 E92.46332\nG1 X93.721 Y-162.373 E92.97011\nG1 X96.560 Y-160.700 E93.22705\nG1 X102.090 Y-157.245 E93.73543\nG1 X104.838 Y-155.427 E93.99237\nG1 X110.180 Y-151.687 E94.50074\nG1 X112.829 Y-149.727 E94.75768\nG1 X115.441 Y-147.722 E95.01438\nG1 X120.493 Y-143.631 E95.52117\nG1 X122.911 Y-141.529 E95.77098\n\n; end preskirt\n; start_gcode | end
-end_gcode = ; end_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; use relative positioning\n\nG91\n\n; retract the filament a bit before lifting the nozzle to release some of the pressure\n\nG1 E-1 F300\n\n; home\n\nG28\n\n; use absolute positioning\n\nG90\n\n; cooldown\n\nM104 S0\nM140 S0\n\n; end_gcode | end\n
-before_layer_gcode =
-layer_gcode =
-toolchange_gcode =
-between_objects_gcode =
-retract_length = 4
-retract_lift = 0.3
-retract_lift_above = 0
-retract_lift_below = 449
-retract_speed = 30
-deretract_speed = 0
-retract_restart_extra = 0
-retract_before_travel = 2
-retract_layer_change = 1
-wipe = 1
-retract_before_wipe = 70%
-retract_length_toolchange = 10
-retract_restart_extra_toolchange = 0
-extruder_colour = #1193FF
-machine_max_acceleration_e = 3000
-machine_max_acceleration_extruding = 1000
-machine_max_acceleration_retracting = 1000
-machine_max_acceleration_x = 1500
-machine_max_acceleration_y = 1500
-machine_max_acceleration_z = 1500
-machine_max_feedrate_e = 60
-machine_max_feedrate_x = 200
-machine_max_feedrate_y = 200
-machine_max_feedrate_z = 200
-machine_max_jerk_e = 5
-machine_max_jerk_x = 5
-machine_max_jerk_y = 5
-machine_max_jerk_z = 5
-machine_min_extruding_rate = 0
-machine_min_travel_rate = 0
-printer_settings_id =
-printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n
-default_filament_profile = Generic PLA @PREDATOR
-
-[printer:Anycubic Predator 0.4 nozzle]
-inherits = *common predator*
-printer_model = PREDATOR
-printer_variant = 0.4
-nozzle_diameter = 0.4
-min_layer_height = 0.08
-max_layer_height = 0.32
-default_print_profile = 0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR
-
-[printer:Anycubic Predator 0.6 nozzle]
-inherits = *common predator*
-printer_model = PREDATOR
-printer_variant = 0.6
-nozzle_diameter = 0.6
-min_layer_height = 0.12
-max_layer_height = 0.4
-default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
-
-[printer:Anycubic Predator 0.8 nozzle]
-inherits = *common predator*
-printer_model = PREDATOR
-printer_variant = 0.8
-nozzle_diameter = 0.8
-min_layer_height = 0.16
-max_layer_height = 0.48
-default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
-
-## Anycubic 4MAX Pro 2.0
-## based on https://hartrusion.com/en/prusaslicer-config-for-anycubic-4max-pro-2-0/
-
-[print:*common_4max*]
-avoid_crossing_perimeters = 0
-avoid_crossing_perimeters_max_detour = 0
-bottom_fill_pattern = monotonic
-bottom_solid_layers = 4
-bridge_acceleration = 300
-bridge_angle = 0
-bridge_flow_ratio = 0.65
-bridge_speed = 30
-brim_separation = 0
-brim_type = outer_only
-brim_width = 0
-clip_multipart_objects = 1
-compatible_printers_condition = printer_model=="4MAXPRO20" and nozzle_diameter[0]==0.4
-complete_objects = 0
-default_acceleration = 900
-dont_support_bridges = 1
-draft_shield = disabled
-elefant_foot_compensation = 0.2
-ensure_vertical_shell_thickness = 1
-external_perimeter_extrusion_width = 0
-external_perimeter_speed = 35
-external_perimeters_first = 0
-extra_perimeters = 0
-extruder_clearance_height = 20
-extruder_clearance_radius = 20
-extrusion_width = 0.45
-fill_angle = 45
-fill_density = 20%
-fill_pattern = gyroid
-first_layer_acceleration = 300
-first_layer_acceleration_over_raft = 0
-first_layer_extrusion_width = 0.65
-first_layer_height = 0.3
-first_layer_speed = 20
-first_layer_speed_over_raft = 30
-fuzzy_skin = none
-fuzzy_skin_point_dist = 0.8
-fuzzy_skin_thickness = 0.3
-gap_fill_enabled = 1
-gap_fill_speed = 40
-gcode_comments = 0
-gcode_label_objects = 0
-gcode_resolution = 0.0125
-infill_acceleration = 600
-infill_anchor = 400%
-infill_anchor_max = 50
-infill_every_layers = 1
-infill_extruder = 1
-infill_extrusion_width = 0
-infill_first = 0
-infill_only_where_needed = 0
-infill_overlap = 23%
-infill_speed = 45
-inherits =
-interface_shells = 0
-ironing = 0
-ironing_flowrate = 15%
-ironing_spacing = 0.1
-ironing_speed = 15
-ironing_type = top
-layer_height = 0.2
-max_print_speed = 50
-max_volumetric_speed = 0
-min_skirt_length = 0
-only_retract_when_crossing_perimeters = 0
-ooze_prevention = 0
-output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{print_time}.gcode
-overhangs = 1
-perimeter_acceleration = 500
-perimeter_extruder = 1
-perimeter_extrusion_width = 0
-perimeter_speed = 45
-perimeters = 3
-post_process =
-print_settings_id =
-raft_contact_distance = 0.1
-raft_expansion = 1.5
-raft_first_layer_density = 90%
-raft_first_layer_expansion = 3
-raft_layers = 0
-resolution = 0
-seam_position = aligned
-single_extruder_multi_material_priming = 1
-skirt_distance = 5
-skirt_height = 1
-skirts = 2
-slicing_mode = regular
-small_perimeter_speed = 20
-solid_infill_below_area = 0
-solid_infill_every_layers = 0
-solid_infill_extruder = 1
-solid_infill_extrusion_width = 0
-solid_infill_speed = 45
-spiral_vase = 0
-standby_temperature_delta = -5
-support_material = 0
-support_material_angle = 0
-support_material_auto = 1
-support_material_bottom_contact_distance = 0
-support_material_bottom_interface_layers = -1
-support_material_buildplate_only = 1
-support_material_closing_radius = 2
-support_material_contact_distance = 0.2
-support_material_enforce_layers = 0
-support_material_extruder = 1
-support_material_extrusion_width = 0.4
-support_material_interface_contact_loops = 0
-support_material_interface_extruder = 1
-support_material_interface_layers = 2
-support_material_interface_pattern = rectilinear
-support_material_interface_spacing = 0.2
-support_material_interface_speed = 30
-support_material_pattern = rectilinear-grid
-support_material_spacing = 2.5
-support_material_speed = 45
-support_material_style = grid
-support_material_synchronize_layers = 0
-support_material_threshold = 45
-support_material_with_sheath = 1
-support_material_xy_spacing = 60%
-thick_bridges = 1
-thin_walls = 0
-top_fill_pattern = monotonic
-top_infill_extrusion_width = 0.4
-top_solid_infill_speed = 30
-top_solid_layers = 5
-travel_speed = 60
-travel_speed_z = 0
-wipe_tower = 0
-wipe_tower_bridging = 10
-wipe_tower_brim_width = 2
-wipe_tower_no_sparse_layers = 0
-wipe_tower_rotation_angle = 0
-wipe_tower_width = 60
-wipe_tower_x = 180
-wipe_tower_y = 140
-xy_size_compensation = 0
-
-[print:0.15mm Detail @4Max Pro 2.0]
-inherits = *common_4max*
-layer_height = 0.15
-bottom_solid_layers = 5
-top_solid_layers = 7
-perimeter_speed = 40
-external_perimeter_speed = 25
-
-[print:0.20mm Quality @4Max Pro 2.0]
-inherits = *common_4max*
-external_perimeter_speed = 25
-
-[print:0.30mm Draft @4Max Pro 2.0]
-inherits = *common_4max*
-layer_height = 0.3
-bottom_solid_layers = 3
-top_solid_layers = 3
-
-[filament:*common_4max*]
-bed_temperature = 60
-bridge_fan_speed = 100
-compatible_printers_condition = printer_model=="4MAXPRO20"
-cooling = 1
-disable_fan_first_layers = 1
-extrusion_multiplier = 1
-fan_always_on = 1
-fan_below_layer_time = 30
-filament_density = 1.24
-filament_diameter = 1.75
-filament_max_volumetric_speed = 0
-filament_type = PLA
-first_layer_bed_temperature = 60
-first_layer_temperature = 210
-full_fan_speed_layer = 5
-max_fan_speed = 100
-min_fan_speed = 80
-min_print_speed = 10
-slowdown_below_layer_time = 15
-temperature = 205
-
-[filament:*PLA_4max*]
-inherits = *common_4max*
-
-[filament:Generic PLA @4Max Pro 2.0]
-inherits = *PLA_4max*
-filament_vendor = Generic
-
-[filament:Anycubic PLA @4Max Pro 2.0]
-inherits = *PLA_4max*
-first_layer_temperature = 215
-temperature = 207
-filament_vendor = Anycubic
-
-[filament:Generic ABS @4Max Pro 2.0]
-filament_vendor = Generic
-compatible_printers_condition = printer_model=="4MAXPRO20"
-bed_temperature = 100
-first_layer_bed_temperature = 100
-temperature = 245
-first_layer_temperature = 245
-bridge_fan_speed = 15
-cooling = 1
-disable_fan_first_layers = 3
-extrusion_multiplier = 1
-fan_always_on = 0
-fan_below_layer_time = 60
-filament_colour = #800000
-filament_density = 1.04
-filament_diameter = 1.75
-filament_type = ABS
-full_fan_speed_layer = 0
-max_fan_speed = 0
-min_fan_speed = 0
-min_print_speed = 10
-slowdown_below_layer_time = 25
-
-[filament:Generic TPU @4Max Pro 2.0]
-filament_vendor = Generic
-bed_temperature = 60
-bridge_fan_speed = 0
-compatible_printers_condition = printer_model=="4MAXPRO20"
-cooling = 1
-disable_fan_first_layers = 3
-extrusion_multiplier = 1
-fan_always_on = 0
-fan_below_layer_time = 60
-filament_colour = #211AB5
-filament_density = 1.19
-filament_deretract_speed = 20
-filament_diameter = 1.75
-filament_retract_speed = 30
-filament_type = FLEX
-filament_max_volumetric_speed = 1.65
-first_layer_bed_temperature = 60
-first_layer_temperature = 215
-full_fan_speed_layer = 0
-max_fan_speed = 0
-min_fan_speed = 0
-min_print_speed = 10
-slowdown_below_layer_time = 20
-temperature = 215
-
-[filament:Polymaker PolyFlex TPU95 @4Max Pro 2.0]
-filament_vendor = Polymaker
-bed_temperature = 45
-bridge_fan_speed = 80
-compatible_printers_condition = printer_model=="4MAXPRO20"
-cooling = 1
-disable_fan_first_layers = 5
-extrusion_multiplier = 1.04
-fan_always_on = 1
-fan_below_layer_time = 45
-filament_colour = #FD7D2F
-filament_density = 1.22
-filament_deretract_speed = 25
-filament_diameter = 1.75
-filament_max_volumetric_speed = 1.65
-filament_retract_length = 4
-filament_retract_restart_extra = 0.1
-filament_retract_speed = 60
-filament_type = FLEX
-first_layer_bed_temperature = 55
-first_layer_temperature = 215
-full_fan_speed_layer = 8
-max_fan_speed = 50
-min_fan_speed = 25
-min_print_speed = 10
-slowdown_below_layer_time = 10
-temperature = 217
-
-[printer:Anycubic 4Max Pro 2.0]
-printer_model = 4MAXPRO20
-printer_variant = 0.4
-printer_technology = FFF
-bed_shape = 0x0,270x0,270x210,0x210
-color_change_gcode = M600
-default_filament_profile = Generic PLA @4Max Pro 2.0
-default_print_profile = 0.20mm Quality @4Max Pro 2.0
-deretract_speed = 25
-end_gcode = M104 S0 ; turn off extruder heating\nM140 S0 ; turn off bed heating\nM107 ; turn off fans\nG91 ; relative positioning\nG0 Z+0.5 ; move Z up a tiny bit\nG90 ; absolute positioning\nG0 X135 Y105 F{machine_max_feedrate_x[0]*60} ; move extruder to center position\nG0 Z190.5 F{machine_max_feedrate_z[0]*60} ; lower the plattform to Z min\nM84 ; steppers off\nG90 ; absolute positioning\n
-extruder_offset = 0x0
-gcode_flavor = marlin
-machine_limits_usage = time_estimate_only
-machine_max_acceleration_e = 5000
-machine_max_acceleration_extruding = 1250
-machine_max_acceleration_retracting = 1250
-machine_max_acceleration_travel = 1500
-machine_max_acceleration_x = 900
-machine_max_acceleration_y = 900
-machine_max_acceleration_z = 100
-machine_max_feedrate_e = 120
-machine_max_feedrate_x = 200
-machine_max_feedrate_y = 200
-machine_max_feedrate_z = 16
-machine_max_jerk_e = 5
-machine_max_jerk_x = 6
-machine_max_jerk_y = 6
-machine_max_jerk_z = 0.2
-machine_min_extruding_rate = 0
-machine_min_travel_rate = 0
-max_layer_height = 0.3
-max_print_height = 190
-min_layer_height = 0.07
-nozzle_diameter = 0.4
-pause_print_gcode = M601
-remaining_times = 0
-retract_before_travel = 2
-retract_before_wipe = 0%
-retract_layer_change = 1
-retract_length = 2.5
-retract_length_toolchange = 10
-retract_lift = 0
-retract_lift_above = 0
-retract_lift_below = 0
-retract_restart_extra = 0
-retract_restart_extra_toolchange = 0
-retract_speed = 35
-silent_mode = 0
-single_extruder_multi_material = 0
-start_gcode = G21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 X0 Y0 ; home X and Y\nG28 Z0 ; home Z\nG1 Z30 F{machine_max_feedrate_z[0]*60} ; move Z a bit down to not blow on the bed edge while heating\nG1 X10 F3900 ; let some space on x to prevent the filament cooling exhaust from beeing blocked by the servo motor\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM104 S[first_layer_temperature] ; set extruder temp\nM106 S80 ; turn on fan to prevent air nozzle melt while heating up\nM109 S[first_layer_temperature] ; wait for extruder temp\nM107 ; start with the fan off\nG28 X0 ; goto X home again\nG92 E0 ; zero the extruded length\nG1 Z0.2 F360 ; move plattform upwards\n; extrude material next to the plattform (comment or remove following lines to disable)\nG1 F180 E20 ; extrude some material next to the plattform\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG92 E0 ; zero the extruded length again\nG1 X5 F3900 ; move sideways to get rid of that string\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\nG92 E0 ; zero the extruded length again\n; draw intro line (comment or remove following lines to disable)\nG1 X30 E5 F700 ; draw intro line\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG1 X40 Z2.0 ; move away from the introline\nG92 E0 ; zero the extruded length again\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\n; end of intro line code\nM117 Printing...\nG5
-use_firmware_retraction = 0
-use_relative_e_distances = 0
-use_volumetric_e = 0
-variable_layer_height = 1
-wipe = 0
-z_offset = 0
-
-########## SLA printer presets ##########
-
-[sla_print:*common print ANYCUBIC SLA*]
-compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
-layer_height = 0.05
-output_filename_format = [input_filename_base].pwmx
-pad_edge_radius = 0.5
-pad_enable = 0
-pad_max_merge_distance = 50
-pad_wall_height = 0
-pad_wall_thickness = 1
-pad_wall_slope = 45
-faded_layers = 8
-slice_closing_radius = 0.005
-support_base_diameter = 3
-support_base_height = 1
-support_critical_angle = 45
-support_density_at_45 = 250
-support_density_at_horizontal = 500
-support_head_front_diameter = 0.4
-support_head_penetration = 0.4
-support_head_width = 3
-support_max_bridge_length = 10
-support_minimal_z = 0
-support_object_elevation = 5
-support_pillar_diameter = 1
-support_pillar_connection_mode = zigzag
-support_pillar_widening_factor = 0
-supports_enable = 1
-support_small_pillar_diameter_percent = 60%
-
-[sla_print:0.05 Normal @ANYCUBIC]
-inherits = *common print ANYCUBIC SLA*
-layer_height = 0.05
-
-########### Materials
-
-[sla_material:*common ANYCUBIC SLA*]
-compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
-compatible_prints_condition = layer_height == 0.05
-exposure_time = 7
-initial_exposure_time = 40
-initial_layer_height = 0.05
-material_correction = 1,1,1
-material_notes = LIFT_DISTANCE=8.0\nLIFT_SPEED=2.5\nRETRACT_SPEED=3.0\nBOTTOM_LIFT_SPEED=2.0\nBOTTOM_LIFT_DISTANCE=9.0\nDELAY_BEFORE_EXPOSURE=0.5
-
-[sla_material:*common 0.05 ANYCUBIC SLA*]
-inherits = *common ANYCUBIC SLA*
-
-[sla_material:Generic Blue Resin @MONO 0.05]
-inherits = *common 0.05 ANYCUBIC SLA*
-exposure_time = 2.5
-initial_exposure_time = 40
-material_type = Tough
-material_vendor = Generic
-material_colour = #6080EC
-compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
-
-########## Printers
-
-[printer:Anycubic Photon Mono X]
-printer_technology = SLA
-printer_model = PHOTON MONO X
-printer_variant = default
-default_sla_material_profile = Generic Blue Resin @MONO 0.05
-default_sla_print_profile = 0.05 Normal @ANYCUBIC
-thumbnails = 224x168
-sla_archive_format = pwmx
-bed_shape = 1.48x1.02,193.48x1.02,193.48x121.02,1.48x121.02
-display_height = 120
-display_orientation = landscape
-display_mirror_x = 1
-display_mirror_y = 0
-display_pixels_x = 3840
-display_pixels_y = 2400
-display_width = 192
-max_print_height = 245
-elefant_foot_compensation = 0.2
-elefant_foot_min_width = 0.2
-min_exposure_time = 1
-max_exposure_time = 120
-min_initial_exposure_time = 1
-max_initial_exposure_time = 300
-printer_correction = 1,1,1
-gamma_correction = 1
-area_fill = 45
-printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.'\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PHOTONMONOX\n
+# Print profiles for the Anycubic printers.
+
+[vendor]
+# Vendor name will be shown by the Config Wizard.
+name = Anycubic
+# Configuration version of this file. Config file will only be installed, if the config_version differs.
+# This means, the server may force the PrusaSlicer configuration to be downgraded.
+config_version = 0.1.1
+# Where to get the updates from?
+config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/
+# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
+
+# The printer models will be shown by the Configuration Wizard in this order,
+# also the first model installed & the first nozzle installed will be activated after install.
+# Printer model name will be shown by the installation wizard.
+
+[printer_model:AKLP]
+name = Anycubic Kossel Linear Plus
+variants = 0.4
+technology = FFF
+family = KOSSEL
+bed_model = AKLP_Bed.stl
+bed_texture = AK.svg
+default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL
+
+[printer_model:AK]
+name = Anycubic Kossel Pulley (Linear)
+variants = 0.4
+technology = FFF
+family = KOSSEL
+bed_model = AK_Bed.stl
+bed_texture = AK.svg
+default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL
+
+[printer_model:MEGA0]
+name = Anycubic Mega Zero
+variants = 0.4
+technology = FFF
+family = MEGA
+bed_model = mega0_bed.stl
+bed_texture = mega0.svg
+default_materials = Generic PLA @MEGA0; Generic PETG @MEGA0; Anycubic PLA @MEGA0; Prusament PLA @MEGA0; Prusament PETG @MEGA0
+
+[printer_model:I3MEGA]
+name = Anycubic i3 Mega
+variants = 0.4
+technology = FFF
+family = MEGA
+bed_model = i3megas_bed.stl
+bed_texture = i3megas.svg
+
+[printer_model:I3MEGAS]
+name = Anycubic i3 Mega S
+variants = 0.4
+technology = FFF
+family = MEGA
+bed_model = i3megas_bed.stl
+bed_texture = i3megas.svg
+
+[printer_model:4MAXPRO20]
+name = Anycubic 4Max Pro 2.0
+variants = 0.4
+technology = FFF
+family = 4Max
+bed_model = 4MAXPRO20_bed.stl
+bed_texture = 4MAXPRO20_texture.svg
+default_materials = Generic PLA @4Max Pro 2.0; Generic TPU @4Max Pro 2.0; Generic ABS @4Max Pro 2.0
+
+[printer_model:PREDATOR]
+name = Anycubic Predator
+variants = 0.4; 0.6; 0.8
+technology = FFF
+family = PREDATOR
+default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR
+
+[printer_model:PHOTON MONO X]
+name = Photon Mono X
+variants = default
+technology = SLA
+family = PHOTON MONO
+default_materials = Generic Blue Resin @MONO 0.05
+
+# All presets starting with asterisk, for example *common*, are intermediate and they will
+# not make it into the user interface.
+
+## Anycubic KOSSEL
+## Author: https://github.com/tc0fh
+## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4220
+
+# Common print preset
+[print:*common_akossel*]
+avoid_crossing_perimeters = 0
+bottom_solid_min_thickness = 0.5
+bridge_angle = 0
+bridge_flow_ratio = 0.8
+bridge_speed = 30
+brim_width = 0
+clip_multipart_objects = 1
+compatible_printers =
+complete_objects = 0
+dont_support_bridges = 1
+elefant_foot_compensation = 0
+ensure_vertical_shell_thickness = 1
+external_fill_pattern = rectilinear
+external_perimeters_first = 0
+external_perimeter_extrusion_width = 0.45
+extra_perimeters = 0
+extruder_clearance_height = 25
+extruder_clearance_radius = 45
+extrusion_width = 0.45
+fill_angle = 45
+fill_density = 20%
+fill_pattern = grid
+first_layer_extrusion_width = 0.42
+first_layer_height = 0.2
+first_layer_speed = 20
+gap_fill_speed = 40
+gcode_comments = 0
+infill_every_layers = 1
+infill_extruder = 1
+infill_extrusion_width = 0.45
+infill_first = 0
+infill_only_where_needed = 0
+infill_overlap = 25%
+interface_shells = 0
+max_print_speed = 200
+max_volumetric_extrusion_rate_slope_negative = 0
+max_volumetric_extrusion_rate_slope_positive = 0
+max_volumetric_speed = 0
+min_skirt_length = 4
+notes =
+overhangs = 0
+only_retract_when_crossing_perimeters = 0
+ooze_prevention = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
+perimeters = 2
+perimeter_extruder = 1
+perimeter_extrusion_width = 0.45
+perimeter_speed = 45
+post_process =
+print_settings_id =
+raft_layers = 0
+resolution = 0
+seam_position = nearest
+single_extruder_multi_material_priming = 0
+skirts = 2
+skirt_distance = 5
+skirt_height = 1
+small_perimeter_speed = 25
+solid_infill_below_area = 0
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0.45
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 0
+support_material_extruder = 0
+support_material_extrusion_width = 0.38
+support_material_interface_extruder = 0
+support_material_angle = 0
+support_material_buildplate_only = 0
+support_material_enforce_layers = 0
+support_material_contact_distance = 0.15
+support_material_interface_contact_loops = 0
+support_material_interface_layers = 2
+support_material_interface_spacing = 0.2
+support_material_interface_speed = 100%
+support_material_pattern = rectilinear
+support_material_spacing = 2
+support_material_speed = 50
+support_material_synchronize_layers = 0
+support_material_threshold = 45
+support_material_with_sheath = 0
+support_material_xy_spacing = 60%
+thin_walls = 0
+top_infill_extrusion_width = 0.4
+top_solid_infill_speed = 40
+top_solid_min_thickness = 0.6
+travel_speed = 180
+wipe_tower = 1
+wipe_tower_bridging = 10
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 60
+wipe_tower_x = 170
+wipe_tower_y = 140
+xy_size_compensation = 0
+bridge_acceleration = 1000
+default_acceleration = 1500
+first_layer_acceleration = 1000
+infill_acceleration = 1500
+perimeter_acceleration = 800
+
+[print:*0.08mm_akossel*]
+inherits = *common_akossel*
+bottom_solid_layers = 10
+bridge_acceleration = 300
+bridge_flow_ratio = 0.7
+bridge_speed = 20
+external_perimeter_speed = 20
+first_layer_acceleration = 500
+gap_fill_speed = 20
+infill_acceleration = 800
+infill_speed = 40
+layer_height = 0.08
+max_print_speed = 80
+perimeter_acceleration = 300
+perimeter_speed = 30
+perimeters = 3
+small_perimeter_speed = 20
+solid_infill_speed = 40
+support_material_extrusion_width = 0.3
+support_material_spacing = 1.5
+support_material_speed = 40
+top_solid_infill_speed = 30
+top_solid_layers = 12
+
+[print:*0.16mm_akossel*]
+inherits = *common_akossel*
+bottom_solid_layers = 5
+layer_height = 0.16
+top_solid_layers = 6
+
+[print:*0.20mm_akossel*]
+inherits = *common_akossel*
+bottom_solid_layers = 4
+bridge_flow_ratio = 0.95
+layer_height = 0.20
+top_solid_layers = 5
+
+[print:*0.24mm_akossel*]
+inherits = *common_akossel*
+bottom_solid_layers = 4
+bridge_flow_ratio = 0.95
+layer_height = 0.24
+perimeter_speed = 50
+external_perimeter_speed = 35
+top_solid_layers = 4
+infill_speed = 100
+solid_infill_speed = 100
+top_solid_infill_speed = 40
+
+[print:*0.30mm_akossel*]
+inherits = *common_akossel*
+bottom_solid_layers = 3
+bridge_flow_ratio = 0.95
+external_perimeter_extrusion_width = 0.6
+external_perimeter_speed = 35
+extrusion_width = 0.5
+infill_extrusion_width = 0.5
+infill_speed = 70
+layer_height = 0.30
+perimeter_extrusion_width = 0.5
+perimeter_speed = 50
+small_perimeter_speed = 30
+solid_infill_extrusion_width = 0.5
+solid_infill_speed = 70
+support_material_speed = 45
+top_infill_extrusion_width = 0.45
+top_solid_infill_speed = 50
+top_solid_layers = 3
+
+[print:0.08mm ULTRADETAIL @AKOSSEL]
+inherits = *0.08mm_akossel*
+fill_density = 15%
+fill_pattern = gyroid
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.16mm QUALITY @AKOSSEL]
+inherits = *0.16mm_akossel*
+external_perimeter_speed = 25
+fill_density = 15%
+fill_pattern = gyroid
+infill_speed = 80
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.16mm SPEED @AKOSSEL]
+inherits = *0.16mm_akossel*
+external_perimeter_speed = 35
+infill_speed = 120
+perimeter_speed = 60
+solid_infill_speed = 120
+top_solid_infill_speed = 50
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.20mm QUALITY @AKOSSEL]
+inherits = *0.20mm_akossel*
+external_perimeter_speed = 25
+fill_density = 15%
+fill_pattern = gyroid
+infill_speed = 80
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.20mm SPEED @AKOSSEL]
+inherits = *0.20mm_akossel*
+external_perimeter_speed = 35
+infill_speed = 120
+perimeter_speed = 60
+solid_infill_speed = 120
+top_solid_infill_speed = 50
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.24mm DRAFT @AKOSSEL]
+inherits = *0.24mm_akossel*
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+[print:0.30mm FAST @AKOSSEL]
+inherits = *0.30mm_akossel*
+compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4
+
+# Common filament preset
+[filament:*common_akossel*]
+cooling = 0
+compatible_printers =
+extrusion_multiplier = 1
+filament_cost = 0
+filament_density = 0
+filament_diameter = 1.75
+filament_notes = ""
+filament_settings_id = ""
+filament_soluble = 0
+min_print_speed = 15
+slowdown_below_layer_time = 20
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Anycubic.*/ and printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/
+
+[filament:*PLA_akossel*]
+inherits = *common_akossel*
+bed_temperature = 60
+fan_below_layer_time = 100
+filament_colour = #FF3232
+filament_max_volumetric_speed = 10
+filament_type = PLA
+filament_density = 1.24
+filament_cost = 20
+first_layer_bed_temperature = 60
+first_layer_temperature = 200
+fan_always_on = 1
+cooling = 1
+max_fan_speed = 100
+min_fan_speed = 100
+bridge_fan_speed = 100
+disable_fan_first_layers = 1
+temperature = 200
+
+[filament:*PET_akossel*]
+inherits = *common_akossel*
+bed_temperature = 70
+cooling = 1
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #FF8000
+filament_max_volumetric_speed = 8
+filament_type = PETG
+filament_density = 1.27
+filament_cost = 30
+first_layer_bed_temperature =70
+first_layer_temperature = 240
+fan_always_on = 1
+max_fan_speed = 50
+min_fan_speed = 20
+bridge_fan_speed = 100
+temperature = 240
+
+[filament:*ABS_akossel*]
+inherits = *common_akossel*
+bed_temperature = 100
+cooling = 0
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #3A80CA
+filament_max_volumetric_speed = 10
+filament_type = ABS
+filament_density = 1.04
+filament_cost = 20
+first_layer_bed_temperature = 100
+first_layer_temperature = 245
+fan_always_on = 0
+max_fan_speed = 0
+min_fan_speed = 0
+bridge_fan_speed = 30
+top_fan_speed = 0
+temperature = 245
+
+[filament:Generic PLA @AKOSSEL]
+inherits = *PLA_akossel*
+filament_vendor = Generic
+
+[filament:Generic PETG @AKOSSEL]
+inherits = *PET_akossel*
+filament_vendor = Generic
+
+[filament:Generic ABS @AKOSSEL]
+inherits = *ABS_akossel*
+filament_vendor = Generic
+
+# Common printer preset
+[printer:*common_akossel*]
+printer_technology = FFF
+bed_shape =
+before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]
+between_objects_gcode =
+deretract_speed = 40
+extruder_colour = #FFFF00
+extruder_offset = 0x0
+gcode_flavor = marlin
+silent_mode = 0
+remaining_times = 0
+machine_max_acceleration_e = 3000
+machine_max_acceleration_extruding = 1000
+machine_max_acceleration_retracting = 1000
+machine_max_acceleration_x = 1500
+machine_max_acceleration_y = 1500
+machine_max_acceleration_z = 1500
+machine_max_feedrate_e = 60
+machine_max_feedrate_x = 200
+machine_max_feedrate_y = 200
+machine_max_feedrate_z = 200
+machine_max_jerk_e = 5
+machine_max_jerk_x = 5
+machine_max_jerk_y = 5
+machine_max_jerk_z = 5
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
+max_layer_height = 0.3
+min_layer_height = 0.08
+max_print_height = 300
+nozzle_diameter = 0.4
+printer_notes =
+printer_settings_id =
+retract_before_travel = 2
+retract_before_wipe = 70%
+retract_layer_change = 1
+retract_length = 5
+retract_length_toolchange = 1
+retract_lift = 0
+retract_lift_above = 0
+retract_lift_below = 0
+retract_restart_extra = 0
+retract_restart_extra_toolchange = 0
+retract_speed = 60
+single_extruder_multi_material = 0
+start_gcode =
+end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG28 ; home\nM84 ; disable motors
+toolchange_gcode =
+use_firmware_retraction = 0
+use_relative_e_distances = 1
+use_volumetric_e = 0
+variable_layer_height = 1
+wipe = 1
+z_offset = 0
+default_print_profile = 0.20mm QUALITY @AKOSSEL
+default_filament_profile = Generic PLA @AKOSSEL
+
+[printer:Anycubic Kossel Linear Plus]
+inherits = *common_akossel*
+printer_model = AKLP
+printer_variant = 0.4
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n
+bed_shape = 114.562x10.0229,113.253x19.9695,111.081x29.7642,108.065x39.3323,104.225x48.6011,99.5929x57.5,94.2025x65.9613,88.0951x73.9206,81.3173x81.3173,73.9206x88.0951,65.9613x94.2025,57.5x99.5929,48.6011x104.225,39.3323x108.065,29.7642x111.081,19.9695x113.253,10.0229x114.562,7.04172e-15x115,-10.0229x114.562,-19.9695x113.253,-29.7642x111.081,-39.3323x108.065,-48.6011x104.225,-57.5x99.5929,-65.9613x94.2025,-73.9206x88.0951,-81.3173x81.3173,-88.0951x73.9206,-94.2025x65.9613,-99.5929x57.5,-104.225x48.6011,-108.065x39.3323,-111.081x29.7642,-113.253x19.9695,-114.562x10.0229,-115x1.40834e-14,-114.562x-10.0229,-113.253x-19.9695,-111.081x-29.7642,-108.065x-39.3323,-104.225x-48.6011,-99.5929x-57.5,-94.2025x-65.9613,-88.0951x-73.9206,-81.3173x-81.3173,-73.9206x-88.0951,-65.9613x-94.2025,-57.5x-99.5929,-48.6011x-104.225,-39.3323x-108.065,-29.7642x-111.081,-19.9695x-113.253,-10.0229x-114.562,-2.11252e-14x-115,10.0229x-114.562,19.9695x-113.253,29.7642x-111.081,39.3323x-108.065,48.6011x-104.225,57.5x-99.5929,65.9613x-94.2025,73.9206x-88.0951,81.3173x-81.3173,88.0951x-73.9206,94.2025x-65.9613,99.5929x-57.5,104.225x-48.6011,108.065x-39.3323,111.081x-29.7642,113.253x-19.9695,114.562x-10.0229,115x-2.81669e-14
+start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-54.672 Y95.203 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-52.931 Y96.185 E0.300\nG1 X-50.985 Y97.231 E0.331\nG1 X-49.018 Y98.238 E0.331\nG1 X-47.032 Y99.205 E0.331\nG1 X-45.026 Y100.132 E0.331\nG1 X-43.003 Y101.019 E0.331\nG1 X-40.961 Y101.864 E0.331\nG1 X-38.904 Y102.668 E0.331\nG1 X-36.83 Y103.431 E0.331\nG1 X-34.742 Y104.152 E0.331\nG1 X-32.639 Y104.83 E0.331\nG1 X-30.523 Y105.466 E0.331\nG1 X-28.395 Y106.06 E0.331\nG1 X-26.255 Y106.61 E0.331\nG1 X-24.105 Y107.117 E0.331\nG1 X-21.945 Y107.581 E0.331\nG1 X-19.776 Y108.001 E0.331\nG1 X-17.599 Y108.377 E0.331\nG1 X-15.415 Y108.71 E0.331\nG1 X-13.224 Y108.998 E0.331\nG1 X-11.028 Y109.242 E0.331\nG1 X-8.828 Y109.442 E0.331\nG1 X-6.624 Y109.598 E0.331\nG1 X-4.418 Y109.709 E0.331\nG1 X-2.209 Y109.776 E0.332\nG1 X0 Y109.798 E0.331\nG1 X2.209 Y109.776 E0.690\nG1 X4.418 Y109.709 E0.691\nG1 X6.624 Y109.598 E0.690\nG1 X8.828 Y109.442 E0.690\nG1 X11.028 Y109.242 E0.690\nG1 X13.224 Y108.998 E0.690\nG1 X15.415 Y108.71 E0.691\nG1 X17.599 Y108.377 E0.690\nG1 X19.776 Y108.001 E0.690\nG1 X21.945 Y107.581 E0.690\nG1 X24.105 Y107.117 E0.690\nG1 X26.255 Y106.61 E0.690\nG1 X28.395 Y106.06 E0.690\nG1 X30.523 Y105.466 E0.690\nG1 X32.639 Y104.83 E0.690\nG1 X34.742 Y104.152 E0.690\nG1 X36.83 Y103.431 E0.690\nG1 X38.904 Y102.668 E0.691\nG1 X40.961 Y101.864 E0.690\nG1 X43.003 Y101.019 E0.691\nG1 X45.026 Y100.132 E0.690\nG1 X47.032 Y99.205 E0.691\nG1 X49.018 Y98.238 E0.690\nG1 X50.985 Y97.231 E0.691\nG1 X52.931 Y96.185 E0.690\nG1 X54.672 Y95.203 E0.625\nG92 E0.0\nG1 E-5 F3000 ; retract 5mm\nG1 X52.931 Y96.185 F1000 ; wipe\nG1 X50.985 Y97.231 F1000 ; wipe\nG1 X49.018 Y98.238 F1000 ; wipe\nG1 X0 Y109.798 F1000\nG1 E4.8 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\nM221 S{if layer_height<0.075}100{else}95{endif}
+
+[printer:Anycubic Kossel Pulley (Linear)]
+inherits = *common_akossel*
+printer_model = AK
+printer_variant = 0.4
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n
+bed_shape = 89.6575x7.84402,88.6327x15.6283,86.9333x23.2937,84.5723x30.7818,81.5677x38.0356,77.9423x45,73.7237x51.6219,68.944x57.8509,63.6396x63.6396,57.8509x68.944,51.6219x73.7237,45x77.9423,38.0356x81.5677,30.7818x84.5723,23.2937x86.9333,15.6283x88.6327,7.84402x89.6575,5.51091e-15x90,-7.84402x89.6575,-15.6283x88.6327,-23.2937x86.9333,-30.7818x84.5723,-38.0356x81.5677,-45x77.9423,-51.6219x73.7237,-57.8509x68.944,-63.6396x63.6396,-68.944x57.8509,-73.7237x51.6219,-77.9423x45,-81.5677x38.0356,-84.5723x30.7818,-86.9333x23.2937,-88.6327x15.6283,-89.6575x7.84402,-90x1.10218e-14,-89.6575x-7.84402,-88.6327x-15.6283,-86.9333x-23.2937,-84.5723x-30.7818,-81.5677x-38.0356,-77.9423x-45,-73.7237x-51.6219,-68.944x-57.8509,-63.6396x-63.6396,-57.8509x-68.944,-51.6219x-73.7237,-45x-77.9423,-38.0356x-81.5677,-30.7818x-84.5723,-23.2937x-86.9333,-15.6283x-88.6327,-7.84402x-89.6575,-1.65327e-14x-90,7.84402x-89.6575,15.6283x-88.6327,23.2937x-86.9333,30.7818x-84.5723,38.0356x-81.5677,45x-77.9423,51.6219x-73.7237,57.8509x-68.944,63.6396x-63.6396,68.944x-57.8509,73.7237x-51.6219,77.9423x-45,81.5677x-38.0356,84.5723x-30.7818,86.9333x-23.2937,88.6327x-15.6283,89.6575x-7.84402,90x-2.20436e-14
+start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-39.672 Y69.712 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-38.457 Y70.397 E0.209\nG1 X-37.043 Y71.157 E0.241\nG1 X-35.614 Y71.889 E0.241\nG1 X-34.171 Y72.591 E0.241\nG1 X-32.714 Y73.265 E0.241\nG1 X-31.244 Y73.909 E0.241\nG1 X-29.761 Y74.523 E0.241\nG1 X-28.266 Y75.108 E0.241\nG1 X-26.759 Y75.662 E0.241\nG1 X-25.242 Y76.185 E0.241\nG1 X-23.714 Y76.678 E0.241\nG1 X-22.177 Y77.14 E0.241\nG1 X-20.63 Y77.571 E0.241\nG1 X-19.076 Y77.971 E0.241\nG1 X-17.514 Y78.34 E0.241\nG1 X-15.944 Y78.677 E0.241\nG1 X-14.368 Y78.982 E0.241\nG1 X-12.786 Y79.255 E0.241\nG1 X-11.199 Y79.497 E0.241\nG1 X-9.608 Y79.706 E0.241\nG1 X-8.013 Y79.884 E0.241\nG1 X-6.414 Y80.029 E0.241\nG1 X-4.813 Y80.142 E0.241\nG1 X-3.21 Y80.223 E0.241\nG1 X-1.605 Y80.271 E0.241\nG1 X0 Y80.287 E0.241\nG1 X1.605 Y80.271 E0.502\nG1 X3.21 Y80.223 E0.502\nG1 X4.813 Y80.142 E0.502\nG1 X6.414 Y80.029 E0.502\nG1 X8.013 Y79.884 E0.502\nG1 X9.608 Y79.706 E0.502\nG1 X11.199 Y79.497 E0.501\nG1 X12.786 Y79.255 E0.502\nG1 X14.368 Y78.982 E0.502\nG1 X15.944 Y78.677 E0.502\nG1 X17.514 Y78.34 E0.502\nG1 X19.076 Y77.971 E0.502\nG1 X20.63 Y77.571 E0.501\nG1 X22.177 Y77.14 E0.502\nG1 X23.714 Y76.678 E0.502\nG1 X25.242 Y76.185 E0.502\nG1 X26.759 Y75.662 E0.501\nG1 X28.266 Y75.108 E0.502\nG1 X29.761 Y74.523 E0.502\nG1 X31.244 Y73.909 E0.502\nG1 X32.714 Y73.265 E0.502\nG1 X34.171 Y72.591 E0.502\nG1 X35.614 Y71.889 E0.501\nG1 X37.043 Y71.157 E0.502\nG1 X38.457 Y70.397 E0.502\nG1 X39.672 Y69.712 E0.436\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
+
+## Anycubic MEGA ZERO
+## Author: https://github.com/kad
+## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4057
+
+# Common print preset
+[print:*common_mega0*]
+avoid_crossing_perimeters = 1
+bridge_angle = 0
+bridge_flow_ratio = 0.7
+bridge_speed = 25
+brim_width = 0
+clip_multipart_objects = 1
+compatible_printers =
+complete_objects = 0
+dont_support_bridges = 1
+elefant_foot_compensation = 0
+ensure_vertical_shell_thickness = 1
+external_fill_pattern = rectilinear
+external_perimeters_first = 0
+external_perimeter_extrusion_width = 0.45
+extra_perimeters = 0
+extruder_clearance_height = 25
+extruder_clearance_radius = 45
+extrusion_width = 0.45
+fill_angle = 45
+fill_density = 20%
+fill_pattern = grid
+first_layer_extrusion_width = 0.42
+first_layer_height = 0.2
+first_layer_speed = 20
+gap_fill_speed = 30
+gcode_comments = 0
+infill_every_layers = 1
+infill_extruder = 1
+infill_extrusion_width = 0.45
+infill_first = 0
+infill_only_where_needed = 0
+infill_overlap = 25%
+interface_shells = 0
+max_print_speed = 100
+max_volumetric_extrusion_rate_slope_negative = 0
+max_volumetric_extrusion_rate_slope_positive = 0
+max_volumetric_speed = 0
+min_skirt_length = 4
+notes =
+overhangs = 1
+only_retract_when_crossing_perimeters = 0
+ooze_prevention = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
+perimeters = 2
+perimeter_extruder = 1
+perimeter_extrusion_width = 0.45
+post_process =
+print_settings_id =
+raft_layers = 0
+resolution = 0
+seam_position = nearest
+single_extruder_multi_material_priming = 1
+skirts = 2
+skirt_distance = 2
+skirt_height = 2
+small_perimeter_speed = 25
+solid_infill_below_area = 0
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0.45
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 0
+support_material_extruder = 0
+support_material_extrusion_width = 0.4
+support_material_interface_extruder = 0
+support_material_angle = 0
+support_material_buildplate_only = 0
+support_material_enforce_layers = 0
+support_material_contact_distance = 0.15
+support_material_interface_contact_loops = 0
+support_material_interface_layers = 2
+support_material_interface_spacing = 0.2
+support_material_interface_speed = 100%
+support_material_pattern = rectilinear
+support_material_spacing = 2
+support_material_speed = 40
+support_material_synchronize_layers = 0
+support_material_threshold = 45
+support_material_with_sheath = 0
+support_material_xy_spacing = 60%
+thin_walls = 0
+top_infill_extrusion_width = 0.45
+top_solid_infill_speed = 40
+travel_speed = 100
+wipe_tower = 0
+wipe_tower_bridging = 10
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 60
+wipe_tower_x = 170
+wipe_tower_y = 140
+xy_size_compensation = 0
+
+[print:*0.10mm_mega0*]
+inherits = *common_mega0*
+perimeter_speed = 40
+external_perimeter_speed = 25
+infill_speed = 50
+solid_infill_speed = 40
+layer_height = 0.10
+perimeters = 3
+top_infill_extrusion_width = 0.4
+bottom_solid_layers = 6
+top_solid_layers = 7
+
+[print:*0.20mm_mega0*]
+inherits = *common_mega0*
+perimeter_speed = 40
+external_perimeter_speed = 25
+infill_speed = 50
+solid_infill_speed = 40
+layer_height = 0.20
+top_infill_extrusion_width = 0.4
+bottom_solid_layers = 4
+top_solid_layers = 5
+
+[print:*0.30mm_mega0*]
+inherits = *common_mega0*
+perimeter_speed = 40
+external_perimeter_speed = 25
+infill_speed = 50
+solid_infill_speed = 40
+layer_height = 0.24
+top_infill_extrusion_width = 0.45
+bottom_solid_layers = 3
+top_solid_layers = 4
+
+[print:0.10mm DETAIL @MEGA0]
+inherits = *0.10mm_mega0*
+travel_speed = 120
+infill_speed = 50
+solid_infill_speed = 40
+top_solid_infill_speed = 30
+support_material_extrusion_width = 0.38
+compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
+
+[print:0.20mm NORMAL @MEGA0]
+inherits = *0.20mm_mega0*
+travel_speed = 120
+infill_speed = 50
+solid_infill_speed = 40
+top_solid_infill_speed = 30
+support_material_extrusion_width = 0.38
+compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
+
+[print:0.30mm DRAFT @MEGA0]
+inherits = *0.30mm_mega0*
+travel_speed = 120
+infill_speed = 50
+solid_infill_speed = 40
+top_solid_infill_speed = 30
+support_material_extrusion_width = 0.38
+compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4
+
+# Common filament preset
+[filament:*common_mega0*]
+cooling = 0
+compatible_printers =
+extrusion_multiplier = 1
+filament_cost = 0
+filament_density = 0
+filament_diameter = 1.75
+filament_notes = ""
+filament_settings_id = ""
+filament_soluble = 0
+min_print_speed = 15
+slowdown_below_layer_time = 20
+compatible_printers_condition = printer_model=="MEGA0"
+
+[filament:*PLA_mega0*]
+inherits = *common_mega0*
+bed_temperature = 40
+fan_below_layer_time = 100
+filament_colour = #FF3232
+filament_max_volumetric_speed = 15
+filament_type = PLA
+filament_density = 1.24
+filament_cost = 20
+first_layer_bed_temperature = 40
+first_layer_temperature = 215
+fan_always_on = 1
+cooling = 1
+max_fan_speed = 100
+min_fan_speed = 100
+bridge_fan_speed = 100
+disable_fan_first_layers = 1
+temperature = 210
+
+[filament:*PET_mega0*]
+inherits = *common_mega0*
+bed_temperature = 70
+cooling = 1
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #FF8000
+filament_max_volumetric_speed = 8
+filament_type = PETG
+filament_density = 1.27
+filament_cost = 30
+first_layer_bed_temperature =70
+first_layer_temperature = 240
+fan_always_on = 1
+max_fan_speed = 50
+min_fan_speed = 20
+bridge_fan_speed = 100
+temperature = 240
+
+[filament:*ABS_mega0*]
+inherits = *common_mega0*
+bed_temperature = 100
+cooling = 0
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #3A80CA
+filament_max_volumetric_speed = 11
+filament_type = ABS
+filament_density = 1.04
+filament_cost = 20
+first_layer_bed_temperature = 100
+first_layer_temperature = 245
+fan_always_on = 0
+max_fan_speed = 0
+min_fan_speed = 0
+bridge_fan_speed = 30
+top_fan_speed = 0
+temperature = 245
+
+[filament:Generic PLA @MEGA0]
+inherits = *PLA_mega0*
+filament_vendor = Generic
+
+[filament:Generic PETG @MEGA0]
+inherits = *PET_mega0*
+filament_vendor = Generic
+
+[filament:Generic ABS @MEGA0]
+inherits = *ABS_mega0*
+filament_vendor = Generic
+
+[filament:Anycubic PLA @MEGA0]
+inherits = *PLA_mega0*
+filament_vendor = Anycubic
+temperature = 190
+first_layer_temperature = 195
+filament_cost = 24.99
+filament_density = 1.25
+
+[filament:Prusament PLA @MEGA0]
+inherits = *PLA_mega0*
+filament_vendor = Prusa Polymers
+temperature = 215
+bed_temperature = 40
+first_layer_temperature = 215
+filament_cost = 24.99
+filament_density = 1.24
+
+[filament:Prusament PETG @MEGA0]
+inherits = *PET_mega0*
+filament_vendor = Prusa Polymers
+temperature = 245
+bed_temperature = 70
+first_layer_temperature = 245
+filament_cost = 24.99
+filament_density = 1.27
+
+# Common printer preset
+[printer:*common_mega0*]
+printer_technology = FFF
+bed_shape = 0x0,220x0,220x220,0x220
+before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm\nG92 E0
+between_objects_gcode =
+deretract_speed = 0
+extruder_colour = #FFFF00
+extruder_offset = 0x0
+gcode_flavor = marlin
+silent_mode = 0
+remaining_times = 0
+machine_max_acceleration_e = 10000
+machine_max_acceleration_extruding = 2000
+machine_max_acceleration_retracting = 1500
+machine_max_acceleration_x = 3000
+machine_max_acceleration_y = 3000
+machine_max_acceleration_z = 500
+machine_max_feedrate_e = 120
+machine_max_feedrate_x = 500
+machine_max_feedrate_y = 500
+machine_max_feedrate_z = 12
+machine_max_jerk_e = 2.5
+machine_max_jerk_x = 20
+machine_max_jerk_y = 20
+machine_max_jerk_z = 0.4
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+layer_gcode = ; AFTER_LAYER_CHANGE [layer_num] @ [layer_z]mm
+max_layer_height = 0.3
+min_layer_height = 0.1
+max_print_height = 200
+nozzle_diameter = 0.4
+printer_notes =
+printer_settings_id =
+retract_before_travel = 1
+retract_before_wipe = 0%
+retract_layer_change = 1
+retract_length = 6
+retract_length_toolchange = 1
+retract_lift = 0
+retract_lift_above = 0
+retract_lift_below = 0
+retract_restart_extra = 0
+retract_restart_extra_toolchange = 0
+retract_speed = 30
+single_extruder_multi_material = 0
+start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n
+end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM140 S0 ; turn off heatbed\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n
+toolchange_gcode =
+use_firmware_retraction = 0
+use_relative_e_distances = 1
+use_volumetric_e = 0
+variable_layer_height = 1
+wipe = 1
+z_offset = 0
+printer_model =
+default_print_profile =
+default_filament_profile =
+
+[printer:Anycubic Mega Zero]
+inherits = *common_mega0*
+printer_model = MEGA0
+printer_variant = 0.4
+max_layer_height = 0.3
+min_layer_height = 0.1
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0
+bed_shape = 0x0,220x0,220x220,0x220
+max_print_height = 250
+machine_max_acceleration_e = 5000
+machine_max_acceleration_extruding = 500
+machine_max_acceleration_retracting = 500
+machine_max_acceleration_x = 500
+machine_max_acceleration_y = 500
+machine_max_acceleration_z = 100
+machine_max_feedrate_e = 25
+machine_max_feedrate_x = 500
+machine_max_feedrate_y = 500
+machine_max_feedrate_z = 5
+machine_max_jerk_e = 5
+machine_max_jerk_x = 10
+machine_max_jerk_y = 10
+machine_max_jerk_z = 0.4
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+nozzle_diameter = 0.4
+retract_before_travel = 2
+retract_layer_change = 0
+retract_length = 7
+retract_speed = 30
+retract_lift = 0.2
+deretract_speed = 30
+retract_before_wipe = 70%
+default_print_profile = 0.20mm NORMAL @MEGA0
+default_filament_profile = Anycubic PLA @MEGA0
+start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n
+end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n
+
+## Anycubic i3 Mega and i3 Mega S
+## Author: https://github.com/Igami
+## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4619
+
+[print:*common_mega*]
+bottom_solid_min_thickness = 0.5
+bridge_acceleration = 1000
+bridge_flow_ratio = 0.95
+bridge_speed = 25
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ and nozzle_diameter[0]==0.4
+default_acceleration = 1000
+ensure_vertical_shell_thickness = 1
+external_perimeter_extrusion_width = 0.45
+external_perimeter_speed = 40
+extruder_clearance_height = 35
+extruder_clearance_radius = 60
+extrusion_width = 0.45
+fill_density = 15%
+fill_pattern = gyroid
+first_layer_acceleration = 800
+first_layer_extrusion_width = 0.42
+first_layer_height = 0.2
+first_layer_speed = 20
+gap_fill_speed = 40
+gcode_comments = 0
+gcode_label_objects = 1
+infill_acceleration = 1000
+infill_anchor = 2.5
+infill_anchor_max = 12
+infill_extrusion_width = 0.45
+max_print_speed = 100
+min_skirt_length = 4
+only_retract_when_crossing_perimeters = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
+perimeter_acceleration = 800
+perimeter_extrusion_width = 0.45
+perimeter_speed = 50
+perimeters = 2
+seam_position = nearest
+skirt_distance = 2
+skirt_height = 3
+skirts = 1
+small_perimeter_speed = 25
+solid_infill_below_area = 0
+solid_infill_extrusion_width = 0.45
+solid_infill_speed = 50
+support_material = 0
+support_material_buildplate_only = 0
+support_material_contact_distance = 0.1
+support_material_extrusion_width = 0.35
+support_material_interface_layers = 2
+support_material_interface_spacing = 0.2
+support_material_interface_speed = 80%
+support_material_spacing = 2
+support_material_speed = 50
+support_material_threshold = 50
+support_material_xy_spacing = 60%
+thin_walls = 0
+top_infill_extrusion_width = 0.4
+top_solid_infill_speed = 40
+top_solid_min_thickness = 0.7
+travel_speed = 180
+
+# XXXXXXXXXXXXXXXXXXXX
+# XXX--- 0.15mm ---XXX
+# XXXXXXXXXXXXXXXXXXXX
+
+[print:*0.15mm_mega*]
+inherits = *common_mega*
+bottom_solid_layers = 5
+bridge_flow_ratio = 1
+infill_speed = 60
+layer_height = 0.15
+top_solid_layers = 7
+
+[print:0.15mm QUALITY @MEGA]
+inherits = *0.15mm_mega*
+
+# XXXXXXXXXXXXXXXXXXXX
+# XXX--- 0.20mm ---XXX
+# XXXXXXXXXXXXXXXXXXXX
+
+[print:*0.20mm_mega*]
+inherits = *common_mega*
+bottom_solid_layers = 4
+infill_speed = 60
+layer_height = 0.2
+top_solid_layers = 5
+
+[print:0.20mm QUALITY @MEGA]
+inherits = *0.20mm_mega*
+
+# XXXXXXXXXXXXXXXXXXXX
+# XXX--- 0.30mm ---XXX
+# XXXXXXXXXXXXXXXXXXXX
+
+[print:*0.30mm_mega*]
+inherits = *common_mega*
+bottom_solid_layers = 4
+external_perimeter_extrusion_width = 0.6
+external_perimeter_speed = 35
+extrusion_width = 0.5
+fill_pattern = cubic
+infill_extrusion_width = 0.5
+infill_speed = 85
+layer_height = 0.3
+perimeter_extrusion_width = 0.5
+small_perimeter_speed = 30
+solid_infill_extrusion_width = 0.5
+support_material_extrusion_width = 0.38
+support_material_speed = 45
+top_solid_layers = 4
+
+[print:0.30mm DRAFT @MEGA]
+inherits = *0.30mm_mega*
+
+# XXXXXXXXXXXXXXXXXXXXXX
+# XXX--- filament ---XXX
+# XXXXXXXXXXXXXXXXXXXXXX
+
+[filament:*common_mega*]
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
+end_filament_gcode = "; Filament-specific end gcode"
+fan_always_on = 1
+fan_below_layer_time = 100
+filament_vendor = Generic
+min_print_speed = 15
+slowdown_below_layer_time = 20
+
+[filament:*ABS_mega*]
+ inherits = *common_mega*
+ bed_temperature = 110
+ bridge_fan_speed = 25
+ cooling = 0
+ fan_always_on = 0
+ fan_below_layer_time = 20
+ filament_colour = #3A80CA
+ filament_cost = 27.82
+ filament_density = 1.04
+ filament_max_volumetric_speed = 11
+ filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
+ filament_type = ABS
+ first_layer_bed_temperature = 105
+ first_layer_temperature = 255
+ max_fan_speed = 30
+ min_fan_speed = 20
+ temperature = 255
+
+[filament:Generic ABS @MEGA]
+inherits = *ABS_mega*
+
+[filament:*FLEX_mega*]
+inherits = *common_mega*
+bed_temperature = 50
+bridge_fan_speed = 80
+cooling = 0
+extrusion_multiplier = 1.15
+fan_always_on = 0
+filament_colour = #008000
+filament_cost = 82.00
+filament_density = 1.22
+filament_deretract_speed = 25
+filament_max_volumetric_speed = 1.2
+filament_retract_length = 0.8
+filament_type = FLEX
+first_layer_bed_temperature = 55
+first_layer_temperature = 240
+max_fan_speed = 90
+min_fan_speed = 70
+temperature = 240
+
+[filament:Generic FLEX @MEGA]
+inherits = *FLEX_mega*
+
+[filament:SainSmart TPU @MEGA]
+inherits = *FLEX_mega*
+filament_vendor = SainSmart
+bed_temperature = 50
+bridge_fan_speed = 100
+cooling = 1
+disable_fan_first_layers = 4
+filament_cost = 39.99
+filament_density = 1.21
+filament_deretract_speed = 15
+filament_max_volumetric_speed = 1.8
+filament_notes = "SainSmart TPU gains popularity among 3D Printing community for its balance of rigidity and flexibility. In addition, with a 95A Shore Hardness and improved bed adhesion, it is easier to print even with a stock elementary 3D Printer like the Creality Ender 3. SainSmart TPU will not disappoint if you are looking for flexible filament. From drone parts, phone cases, to small toys, all can be printed with ease.\n\nhttps://www.sainsmart.com/collections/tpu-filament/products/all-colors-tpu-flexible-filament-1-75mm-0-8kg-1-76lb"
+filament_retract_before_travel = 5
+filament_retract_length = 4
+filament_retract_speed = 40
+filament_unloading_speed = 90
+first_layer_bed_temperature = 55
+first_layer_temperature = 235
+full_fan_speed_layer = 6
+max_fan_speed = 80
+min_fan_speed = 80
+slowdown_below_layer_time = 10
+temperature = 235
+
+[filament:*PETG_mega*]
+inherits = *common_mega*
+bed_temperature = 90
+bridge_fan_speed = 50
+fan_below_layer_time = 20
+filament_colour = #FF8000
+filament_cost = 27.82
+filament_density = 1.27
+filament_max_volumetric_speed = 8
+filament_type = PETG
+first_layer_bed_temperature = 90
+first_layer_temperature = 230
+max_fan_speed = 50
+min_fan_speed = 30
+temperature = 240
+
+[filament:Generic PETG @MEGA]
+inherits = *PETG_mega*
+
+[filament:ColorFabb XT-CF20 @MEGA]
+inherits = *PETG_mega*
+compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
+extrusion_multiplier = 1.05
+filament_colour = #804040
+filament_cost = 66.60
+filament_density = 1.35
+filament_deretract_speed = 25
+filament_max_volumetric_speed = 2
+filament_notes = "Based on colorFabb_XT, XT-CF20 is a carbon fiber composite material. Loaded with no less than 20% specially sourced carbon fibers we have developed a very stiff and tough 3D printing filament made for functional parts. It is truly a professional printers go-to material, especially for users looking for high melt strength, high melt viscosity and good dimensional accuracy and stability.\n\nhttps://colorfabb.com/xt-cf20"
+filament_retract_before_travel = 1
+filament_retract_length = 1.4
+filament_retract_speed = 40
+filament_spool_weight = 236
+filament_vendor = ColorFabb
+first_layer_temperature = 260
+full_fan_speed_layer = 5
+slowdown_below_layer_time = 15
+temperature = 260
+
+[filament:ERYONE PETG @MEGA]
+inherits = *PETG_mega*
+filament_vendor = ERYONE
+filament_cost = 20.99
+filament_notes = "https://eryone.com/petg/show/10.html"
+
+[filament:FormFutura HDglass @MEGA]
+inherits = *PETG_mega*
+filament_vendor = FormFutura
+filament_cost = 46.65
+filament_notes = "HDglass is a high performance PETG type of 3D printer with unsurpassed 3D printing properties and improved mechanical strength, flexibility, toughness and heat resistance.\n\nhttps://www.formfutura.com/shop/product/hdglass-2812"
+
+[filament:FormFutura ReForm rPET @MEGA]
+inherits = *PETG_mega*
+filament_vendor = FormFutura
+filament_cost = 26.65
+filament_notes = "ReForm rPET is a recycled PETG type of 3D printer filament that is made from post-industrial waste streams of a nearby located plastic bottle manufacturer.\n\nhttps://www.formfutura.com/shop/product/reform-rpet-2836"
+filament_spool_weight = 176
+
+[filament:Janbex transparent PETG @MEGA]
+inherits = *PETG_mega*
+filament_vendor = Janbex
+filament_cost = 31.99
+filament_spool_weight = 222
+first_layer_temperature = 215
+min_fan_speed = 100
+temperature = 210
+
+[filament:DAS FILAMENT PETG @MEGA]
+inherits = *PETG_mega*
+filament_vendor = DAS FILAMENT
+bed_temperature = 75
+first_layer_bed_temperature = 75
+first_layer_temperature = 220
+temperature = 225
+
+[filament:*PLA_mega*]
+inherits = *common_mega*
+bed_temperature = 60
+disable_fan_first_layers = 1
+filament_colour = #FF3232
+filament_cost = 25.40
+filament_density = 1.24
+filament_max_volumetric_speed = 10
+first_layer_bed_temperature = 65
+first_layer_temperature = 215
+min_fan_speed = 100
+temperature = 210
+
+[filament:Generic PLA @MEGA]
+inherits = *PLA_mega*
+
+[filament:3Dmensionals PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = 3Dmensionals
+filament_cost = 22.90
+filament_notes = "Das 3DFilaments - PLA von 3Dmensionals ist ein sehr leicht zu druckendes 3D-Drucker Filament. Dabei handelt es sich um ein etwas härteres PLA mit einer exzellenten thermischen Stabilität. Das Filament zeichnet sich vor allem durch verzugfreies 3D-Drucken aus und weist minimale bis keine Verformung nach dem Abkühlen auf. Daher ist es besonders gut für den Druck größerer Objekte geeignet. Zudem bietet 3DFilaments - PLA über die gesamte Fadenläge eine hervorragende Durchmesser- und Rundheitstoleranz.\n\nhttps://www.3dmensionals.de/3dfilaments?number=PSU3DM001V"
+
+[filament:3D Warhorse PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = 3D Warhorse
+filament_cost = 19.99
+
+[filament:AMOLEN wood PLA]
+inherits = *PLA_mega*
+filament_vendor = AMOLEN
+compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/
+extrusion_multiplier = 1.1
+filament_colour = #DFC287
+filament_cost = 33.99
+filament_density = 1.23
+filament_max_volumetric_speed = 9
+filament_notes = "https://amolen.com/collections/wood/products/amolen-pla-filament-1-75mm-wood-color-3d-printer-filament-1kg2-2lb"
+
+[filament:FormFutura EasyFil PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = FormFutura
+filament_cost = 39.93
+filament_notes = "EasyFil PLA is an easy to print PLA type of 3D printer filament that is available in a wide variety of colors. Its improved flowing behavior make 3D printed layers flow more into each other.\n\nhttps://www.formfutura.com/shop/product/easyfil-pla-2801"
+
+[filament:FormFutura ReForm rPLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = FormFutura
+filament_cost = 26.65
+filament_notes = "ReForm is a sustainable initiative within Formfutura to efficiently manage residual extrusion waste streams and re-use them into high-end upcycled filaments. The ideology behind ReForm is to a make 3D printing more sustainable – without having to make compromises on material properties – and yet keep it affordable.\n\nhttps://www.formfutura.com/shop/product/reform-rpla-2838"
+
+[filament:GIANTARM PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = GIANTARM
+filament_cost = 24.99
+
+[filament:Prusament PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = Prusa Polymers
+filament_cost = 30.24
+filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa"
+filament_spool_weight = 201
+temperature = 215
+
+[filament:Verbatim PLA @MEGA]
+inherits = *PLA_mega*
+filament_vendor = Verbatim
+filament_cost = 23.88
+
+[printer:*common_mega*]
+printer_technology = FFF
+bed_shape = 0x0,210x0,210x210,0x210
+before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]
+default_filament_profile = Generic PLA @MEGA
+default_print_profile = 0.15mm QUALITY @MEGA
+deretract_speed = 50
+end_gcode = G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-34.0 F720 ; move print head up & retract filament\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors
+extruder_colour = #808080
+gcode_flavor = marlin
+layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
+max_layer_height = 0.36
+max_print_height = 205
+remaining_times = 1
+retract_before_travel = 1.5
+retract_before_wipe = 60%
+retract_layer_change = 1
+retract_length = 6
+retract_lift = 0.075
+retract_lift_below = 204
+retract_speed = 40
+silent_mode = 0
+start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y1.0 Z0.3 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\n; initial load\nG1 X205.0 E19 F1000\nG1 Y1.6\nG1 X5.0 E19 F1000\nG92 E0.0\n; intro line\nG1 Y2.0 Z0.2 F1000\nG1 X65.0 E9.0 F1000\nG1 X105.0 E12.5 F1000\nG92 E0.0
+thumbnails = 16x16,220x124
+use_relative_e_distances = 1
+wipe = 1
+machine_max_acceleration_e = 10000
+machine_max_acceleration_extruding = 1250
+machine_max_acceleration_retracting = 1250
+machine_max_acceleration_x = 3000
+machine_max_acceleration_y = 2000
+machine_max_acceleration_z = 60
+machine_max_feedrate_e = 60
+machine_max_feedrate_x = 500
+machine_max_feedrate_y = 500
+machine_max_feedrate_z = 6
+machine_max_jerk_e = 5
+machine_max_jerk_x = 10
+machine_max_jerk_y = 10
+machine_max_jerk_z = 0.4
+
+[printer:Anycubic i3 Mega]
+inherits = *common_mega*
+printer_model = I3MEGA
+printer_variant = 0.4
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA\nPRINTER_HAS_BOWDEN
+
+[printer:Anycubic i3 Mega S]
+inherits = *common_mega*
+printer_model = I3MEGAS
+printer_variant = 0.4
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA_S\nPRINTER_HAS_BOWDEN
+machine_max_feedrate_e = 30
+machine_max_feedrate_z = 8
+
+
+## Anycubic PREDATOR
+## Author: https://github.com/tillverka3d
+## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4960
+
+#########################################
+###### begin common print presets #######
+#########################################
+
+# Common print preset
+[print:*common predator*]
+spiral_vase = 0
+top_solid_min_thickness = 0.8
+bottom_solid_min_thickness = 0.6
+extra_perimeters = 0
+ensure_vertical_shell_thickness = 1
+avoid_crossing_perimeters = 0
+thin_walls = 0
+overhangs = 1
+seam_position = nearest
+external_perimeters_first = 0
+fill_density = 20%
+external_fill_pattern = rectilinear
+infill_every_layers = 1
+infill_only_where_needed = 0
+solid_infill_every_layers = 0
+fill_angle = 45
+solid_infill_below_area = 20
+bridge_angle = 0
+only_retract_when_crossing_perimeters = 0
+infill_first = 0
+skirts = 1
+skirt_distance = 4
+skirt_height = 1
+min_skirt_length = 8
+brim_width = 0
+support_material = 0
+support_material_auto = 1
+support_material_threshold = 50
+support_material_enforce_layers = 0
+raft_layers = 0
+support_material_contact_distance = 0.1
+support_material_pattern = rectilinear
+support_material_with_sheath = 0
+support_material_spacing = 2
+support_material_angle = 0
+support_material_interface_layers = 2
+support_material_interface_spacing = 0.2
+support_material_interface_contact_loops = 0
+support_material_buildplate_only = 0
+support_material_xy_spacing = 60%
+dont_support_bridges = 1
+support_material_synchronize_layers = 0
+travel_speed = 94
+first_layer_speed = 15
+perimeter_acceleration = 0
+infill_acceleration = 0
+bridge_acceleration = 0
+first_layer_acceleration = 0
+default_acceleration = 0
+max_volumetric_speed = 15
+perimeter_extruder = 1
+infill_extruder = 1
+solid_infill_extruder = 1
+support_material_extruder = 0
+support_material_interface_extruder = 0
+ooze_prevention = 0
+standby_temperature_delta = -5
+wipe_tower = 0
+wipe_tower_x = 170
+wipe_tower_y = 140
+wipe_tower_width = 60
+wipe_tower_rotation_angle = 0
+wipe_tower_bridging = 10
+interface_shells = 0
+bridge_flow_ratio = 0.8
+resolution = 0
+xy_size_compensation = 0
+elefant_foot_compensation = 0.2
+clip_multipart_objects = 1
+complete_objects = 0
+extruder_clearance_radius = 45
+extruder_clearance_height = 25
+gcode_comments = 0
+output_filename_format = {input_filename_base}.gcode
+post_process =
+notes =
+max_volumetric_extrusion_rate_slope_negative = 0
+max_volumetric_extrusion_rate_slope_positive = 0
+print_settings_id =
+
+# Common print preset
+[print:*common predator 0.4 nozzle*]
+inherits = *common predator*
+first_layer_height = 0.16
+infill_overlap = 25%
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.4
+
+# Common print preset
+[print:*common predator 0.6 nozzle*]
+inherits = *common predator*
+first_layer_height = 0.24
+infill_overlap = 27%
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.6
+
+# Common print preset
+[print:*common predator 0.8 nozzle*]
+inherits = *common predator*
+first_layer_height = 0.32
+infill_overlap = 30%
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.8
+
+# Common print preset
+[print:*common predator quality*]
+perimeter_speed = 50
+small_perimeter_speed = 15
+external_perimeter_speed = 70%
+infill_speed = 65
+solid_infill_speed = 85%
+top_solid_infill_speed = 85%
+support_material_speed = 30
+support_material_interface_speed = 85%
+bridge_speed = 30
+gap_fill_speed = 40
+ironing_speed = 15
+
+# Common print preset
+[print:*common predator speed*]
+perimeter_speed = 70
+small_perimeter_speed = 15
+external_perimeter_speed = 70%
+infill_speed = 85
+solid_infill_speed = 85%
+top_solid_infill_speed = 85%
+support_material_speed = 30
+support_material_interface_speed = 85%
+bridge_speed = 30
+gap_fill_speed = 40
+ironing_speed = 15
+
+# Common print preset
+[print:*common predator 0.4 nozzle detailed*]
+inherits = *common predator 0.4 nozzle*
+extrusion_width = 0.42
+first_layer_extrusion_width = 0.41
+perimeter_extrusion_width = 0.42
+external_perimeter_extrusion_width = 0.42
+infill_extrusion_width = 0.4
+solid_infill_extrusion_width = 0.4
+top_infill_extrusion_width = 0.4
+support_material_extrusion_width = 0.38
+
+# Common print preset
+[print:*common predator 0.4 nozzle coarse*]
+inherits = *common predator 0.4 nozzle*
+extrusion_width = 0.44
+first_layer_extrusion_width = 0.42
+perimeter_extrusion_width = 0.5
+external_perimeter_extrusion_width = 0.5
+infill_extrusion_width = 0.5
+solid_infill_extrusion_width = 0.5
+top_infill_extrusion_width = 0.4
+support_material_extrusion_width = 0.38
+
+# Common print preset
+[print:*common predator 0.6 nozzle detailed*]
+inherits = *common predator 0.6 nozzle*
+extrusion_width = 0.64
+first_layer_extrusion_width = 0.62
+perimeter_extrusion_width = 0.64
+external_perimeter_extrusion_width = 0.64
+infill_extrusion_width = 0.6
+solid_infill_extrusion_width = 0.6
+top_infill_extrusion_width = 0.6
+support_material_extrusion_width = 0.56
+
+# Common print preset
+[print:*common predator 0.6 nozzle coarse*]
+inherits = *common predator 0.6 nozzle*
+extrusion_width = 0.67
+first_layer_extrusion_width = 0.64
+perimeter_extrusion_width = 0.7
+external_perimeter_extrusion_width = 0.7
+infill_extrusion_width = 0.7
+solid_infill_extrusion_width = 0.7
+top_infill_extrusion_width = 0.6
+support_material_extrusion_width = 0.56
+
+# Common print preset
+[print:*common predator 0.8 nozzle detailed*]
+inherits = *common predator 0.8 nozzle*
+extrusion_width = 0.84
+first_layer_extrusion_width = 0.82
+perimeter_extrusion_width = 0.84
+external_perimeter_extrusion_width = 0.84
+infill_extrusion_width = 0.8
+solid_infill_extrusion_width = 0.8
+top_infill_extrusion_width = 0.8
+support_material_extrusion_width = 0.72
+
+# Common print preset
+[print:*common predator 0.8 nozzle coarse*]
+inherits = *common predator 0.8 nozzle*
+extrusion_width = 0.87
+first_layer_extrusion_width = 0.84
+perimeter_extrusion_width = 0.9
+external_perimeter_extrusion_width = 0.9
+infill_extrusion_width = 0.9
+solid_infill_extrusion_width = 0.9
+top_infill_extrusion_width = 0.8
+support_material_extrusion_width = 0.72
+
+#########################################
+####### end common print presets ########
+#########################################
+
+#########################################
+########## begin print presets ##########
+#########################################
+
+[print:0.08mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
+layer_height = 0.08
+max_print_speed = 50
+perimeters = 3
+fill_pattern = grid
+
+[print:0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
+layer_height = 0.16
+max_print_speed = 60
+perimeters = 3
+fill_pattern = grid
+
+[print:0.16mm 0.4 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
+layer_height = 0.16
+max_print_speed = 60
+perimeters = 3
+fill_pattern = grid
+
+[print:0.24mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 70
+perimeters = 3
+fill_pattern = grid
+
+[print:0.24mm 0.4 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 70
+perimeters = 3
+fill_pattern = grid
+
+[print:0.32mm 0.4 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle detailed*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 70
+perimeters = 3
+fill_pattern = grid
+
+[print:0.32mm 0.4 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.4 nozzle coarse*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 70
+perimeters = 3
+fill_pattern = grid
+
+[print:0.16mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
+layer_height = 0.16
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.16mm 0.6 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
+layer_height = 0.16
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.16mm 0.6 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
+layer_height = 0.16
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.16mm 0.6 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
+layer_height = 0.16
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.6 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
+layer_height = 0.24
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.6 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.6 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
+layer_height = 0.24
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.6 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
+layer_height = 0.32
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.6 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.6 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
+layer_height = 0.32
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.6 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator quality*
+layer_height = 0.4
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.6 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle detailed*; *common predator speed*
+layer_height = 0.4
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.6 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator quality*
+layer_height = 0.4
+max_print_speed = 70
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.6 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.6 nozzle coarse*; *common predator speed*
+layer_height = 0.4
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.8 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
+layer_height = 0.24
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.8 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
+layer_height = 0.24
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.24mm 0.8 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
+layer_height = 0.24
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.8 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
+layer_height = 0.32
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.8 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
+layer_height = 0.32
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.32mm 0.8 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
+layer_height = 0.32
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
+layer_height = 0.4
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.8 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
+layer_height = 0.4
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.8 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
+layer_height = 0.4
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.4mm 0.8 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
+layer_height = 0.4
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.48mm 0.8 nozzle DETAILED QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator quality*
+layer_height = 0.48
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.48mm 0.8 nozzle DETAILED SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle detailed*; *common predator speed*
+layer_height = 0.48
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.48mm 0.8 nozzle COARSE QUALITY @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator quality*
+layer_height = 0.48
+max_print_speed = 80
+perimeters = 2
+fill_pattern = gyroid
+
+[print:0.48mm 0.8 nozzle COARSE SPEED @PREDATOR]
+inherits = *common predator 0.8 nozzle coarse*; *common predator speed*
+layer_height = 0.48
+max_print_speed = 90
+perimeters = 2
+fill_pattern = gyroid
+
+#########################################
+########### end print presets ###########
+#########################################
+
+#########################################
+######## begin filament presets #########
+#########################################
+
+# Common filament preset
+[filament:*common predator*]
+cooling = 0
+compatible_printers =
+extrusion_multiplier = 1
+filament_cost = 0
+filament_density = 0
+filament_diameter = 1.75
+filament_notes = ""
+filament_settings_id = ""
+filament_soluble = 0
+min_print_speed = 15
+slowdown_below_layer_time = 20
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/
+
+[filament:*PLA predator*]
+inherits = *common predator*
+bed_temperature = 60
+fan_below_layer_time = 100
+filament_colour = #FF3232
+filament_max_volumetric_speed = 10
+filament_type = PLA
+filament_density = 1.24
+filament_cost = 20
+first_layer_bed_temperature = 60
+first_layer_temperature = 200
+fan_always_on = 1
+cooling = 1
+max_fan_speed = 100
+min_fan_speed = 100
+bridge_fan_speed = 100
+disable_fan_first_layers = 1
+temperature = 200
+
+[filament:*PET predator*]
+inherits = *common predator*
+bed_temperature = 70
+cooling = 1
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #FF8000
+filament_max_volumetric_speed = 8
+filament_type = PETG
+filament_density = 1.27
+filament_cost = 30
+first_layer_bed_temperature =70
+first_layer_temperature = 240
+fan_always_on = 1
+max_fan_speed = 50
+min_fan_speed = 20
+bridge_fan_speed = 100
+temperature = 240
+
+[filament:*ABS predator*]
+inherits = *common predator*
+bed_temperature = 100
+cooling = 0
+disable_fan_first_layers = 3
+fan_below_layer_time = 20
+filament_colour = #3A80CA
+filament_max_volumetric_speed = 10
+filament_type = ABS
+filament_density = 1.04
+filament_cost = 20
+first_layer_bed_temperature = 100
+first_layer_temperature = 245
+fan_always_on = 0
+max_fan_speed = 0
+min_fan_speed = 0
+bridge_fan_speed = 30
+top_fan_speed = 0
+temperature = 245
+
+[filament:Generic PLA @PREDATOR]
+inherits = *PLA predator*
+filament_vendor = Generic
+
+[filament:Generic PETG @PREDATOR]
+inherits = *PET predator*
+filament_vendor = Generic
+
+[filament:Generic ABS @PREDATOR]
+inherits = *ABS predator*
+filament_vendor = Generic
+
+#########################################
+######### end filament presets ##########
+#########################################
+
+#########################################
+######### begin printer presets #########
+#########################################
+
+# Anycubic predator common printer preset
+[printer:*common predator*]
+printer_vendor = Anycubic
+printer_model = Predator
+printer_technology = FFF
+printer_variant = 0.4
+thumbnails = 16x16,220x124
+bed_shape = 188.779x16.516,186.621x32.9063,183.043x49.0462,178.072x64.8128,171.745x80.0862,164.112x94.75,155.229x108.693,145.165x121.808,133.997x133.997,121.808x145.165,108.693x155.229,94.75x164.112,80.0862x171.745,64.8128x178.072,49.0462x183.043,32.9063x186.621,16.516x188.779,1.16035e-14x189.5,-16.516x188.779,-32.9063x186.621,-49.0462x183.043,-64.8128x178.072,-80.0862x171.745,-94.75x164.112,-108.693x155.229,-121.808x145.165,-133.997x133.997,-145.165x121.808,-155.229x108.693,-164.112x94.75,-171.745x80.0862,-178.072x64.8128,-183.043x49.0462,-186.621x32.9063,-188.779x16.516,-189.5x2.32071e-14,-188.779x-16.516,-186.621x-32.9063,-183.043x-49.0462,-178.072x-64.8128,-171.745x-80.0862,-164.112x-94.75,-155.229x-108.693,-145.165x-121.808,-133.997x-133.997,-121.808x-145.165,-108.693x-155.229,-94.75x-164.112,-80.0862x-171.745,-64.8128x-178.072,-49.0462x-183.043,-32.9063x-186.621,-16.516x-188.779,-3.48106e-14x-189.5,16.516x-188.779,32.9063x-186.621,49.0462x-183.043,64.8128x-178.072,80.0862x-171.745,94.75x-164.112,108.693x-155.229,121.808x-145.165,133.997x-133.997,145.165x-121.808,155.229x-108.693,164.112x-94.75,171.745x-80.0862,178.072x-64.8128,183.043x-49.0462,186.621x-32.9063,188.779x-16.516,189.5x-4.64141e-14
+max_print_height = 445
+z_offset = 0
+single_extruder_multi_material = 0
+gcode_flavor = reprap
+silent_mode = 0
+remaining_times = 0
+use_relative_e_distances = 0
+use_firmware_retraction = 0
+use_volumetric_e = 0
+variable_layer_height = 1
+start_gcode = ; start_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; set metric values\n\nG21\n\n; use absolute positioning\n\nG90\n\n; set extruder to absolute mode\n\nM82\n\n; start with fan off\n\nM107\n\n; set temps\n\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\n\n; home xy\n\nG28 X0 Y0\n\n; home z\n\nG28 Z0\n\n; move the head down to Z 94mm\n\nG1 Z94.0 F2394\n\n; set and wait for temps\n\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\n\n; zero the extruded length\n\nG92 E0\n\n; extrude 3mm of feed stock\n\nG1 F200 E3\n\n; zero the extruded length again\n\nG92 E0\n\n; set speed\n\nG1 F{travel_speed}\n\n; print preskirt\n\nG92 E0\nG1 E3.94000 F2520.00000\n\nG1 X125.464 Y-139.310\nG1 Z0.329 F3994.000\n\nG1 F994.000\n\nG1 X125.464 Y-139.310 E4.19679\nG1 X130.218 Y-134.876 E4.70359\nG1 X132.569 Y-132.567 E4.96053\nG1 X137.099 Y-127.877 E5.46890\nG1 X139.325 Y-125.447 E5.72585\nG1 X141.507 Y-122.981 E5.98254\nG1 X145.685 Y-118.002 E6.48934\nG1 X149.741 Y-112.810 E7.00296\nG1 X153.561 Y-107.552 E7.50975\nG1 X155.440 Y-104.819 E7.76827\nG1 X158.980 Y-99.367 E8.27506\nG1 X160.702 Y-96.558 E8.53201\nG1 X163.962 Y-90.911 E9.04038\nG1 X165.535 Y-88.015 E9.29732\nG1 X168.496 Y-82.205 E9.80570\nG1 X169.915 Y-79.231 E10.06264\nG1 X171.280 Y-76.235 E10.31934\nG1 X173.819 Y-70.251 E10.82613\nG1 X176.180 Y-64.101 E11.33975\nG1 X178.297 Y-57.955 E11.84654\nG1 X179.294 Y-54.793 E12.10507\nG1 X181.085 Y-48.544 E12.61186\nG1 X181.911 Y-45.354 E12.86880\nG1 X183.378 Y-39.001 E13.37718\nG1 X184.035 Y-35.771 E13.63412\nG1 X185.168 Y-29.350 E14.14250\nG1 X185.655 Y-26.091 E14.39944\nG1 X186.084 Y-22.826 E14.65614\nG1 X186.764 Y-16.362 E15.16293\nG1 X187.223 Y-9.790 E15.67655\nG1 X187.450 Y-3.294 E16.18334\nG1 X187.479 Y0.002 E16.44028\nG1 X187.450 Y3.294 E16.69698\nG1 X187.223 Y9.810 E17.20529\nG1 X187.021 Y13.100 E17.46229\nG1 X186.454 Y19.575 E17.96909\nG1 X186.079 Y22.870 E18.22761\nG1 X185.174 Y29.307 E18.73440\nG1 X184.031 Y35.794 E19.24802\nG1 X182.679 Y42.152 E19.75481\nG1 X181.910 Y45.357 E20.01176\nG1 X180.223 Y51.655 E20.52013\nG1 X179.287 Y54.815 E20.77708\nG1 X177.272 Y61.017 E21.28545\nG1 X176.172 Y64.123 E21.54239\nG1 X175.019 Y67.207 E21.79909\nG1 X172.584 Y73.234 E22.30588\nG1 X169.905 Y79.252 E22.81950\nG1 X167.055 Y85.094 E23.32629\nG1 X165.524 Y88.035 E23.58482\nG1 X162.373 Y93.721 E24.09161\nG1 X160.700 Y96.560 E24.34855\nG1 X157.245 Y102.090 E24.85693\nG1 X155.427 Y104.838 E25.11387\nG1 X151.687 Y110.180 E25.62225\nG1 X149.727 Y112.829 E25.87919\nG1 X147.722 Y115.441 E26.13588\nG1 X143.631 Y120.493 E26.64268\nG1 X139.310 Y125.464 E27.15629\nG1 X134.876 Y130.218 E27.66309\nG1 X132.567 Y132.569 E27.92003\nG1 X127.877 Y137.099 E28.42840\nG1 X125.447 Y139.325 E28.68535\nG1 X122.981 Y141.507 E28.94204\nG1 X118.002 Y145.685 E29.44883\nG1 X112.810 Y149.741 E29.96245\nG1 X107.552 Y153.561 E30.46924\nG1 X104.819 Y155.440 E30.72777\nG1 X99.367 Y158.980 E31.23456\nG1 X96.558 Y160.702 E31.49151\nG1 X90.911 Y163.962 E31.99988\nG1 X88.015 Y165.535 E32.25682\nG1 X82.205 Y168.496 E32.76520\nG1 X79.231 Y169.915 E33.02214\nG1 X76.235 Y171.280 E33.27884\nG1 X70.251 Y173.819 E33.78563\nG1 X64.101 Y176.180 E34.29925\nG1 X57.955 Y178.297 E34.80604\nG1 X54.793 Y179.294 E35.06457\nG1 X48.544 Y181.085 E35.57136\nG1 X45.354 Y181.911 E35.82830\nG1 X39.001 Y183.378 E36.33668\nG1 X35.771 Y184.035 E36.59362\nG1 X29.350 Y185.168 E37.10200\nG1 X26.091 Y185.655 E37.35894\nG1 X22.826 Y186.084 E37.61563\nG1 X16.362 Y186.764 E38.12242\nG1 X9.790 Y187.223 E38.63605\nG1 X3.294 Y187.450 E39.14283\nG1 X-0.002 Y187.479 E39.39978\nG1 X-3.294 Y187.450 E39.65648\nG1 X-9.810 Y187.223 E40.16479\nG1 X-13.100 Y187.021 E40.42179\nG1 X-19.575 Y186.454 E40.92858\nG1 X-22.870 Y186.079 E41.18711\nG1 X-29.307 Y185.174 E41.69390\nG1 X-35.794 Y184.031 E42.20752\nG1 X-42.152 Y182.679 E42.71431\nG1 X-45.357 Y181.910 E42.97126\nG1 X-51.655 Y180.223 E43.47963\nG1 X-54.815 Y179.287 E43.73657\nG1 X-61.017 Y177.272 E44.24495\nG1 X-64.123 Y176.172 E44.50189\nG1 X-67.207 Y175.019 E44.75859\nG1 X-73.234 Y172.584 E45.26538\nG1 X-79.252 Y169.905 E45.77900\nG1 X-85.094 Y167.055 E46.28579\nG1 X-88.035 Y165.524 E46.54432\nG1 X-93.721 Y162.373 E47.05111\nG1 X-96.560 Y160.700 E47.30805\nG1 X-102.090 Y157.245 E47.81643\nG1 X-104.838 Y155.427 E48.07337\nG1 X-110.180 Y151.687 E48.58174\nG1 X-112.829 Y149.727 E48.83869\nG1 X-115.441 Y147.722 E49.09538\nG1 X-120.493 Y143.631 E49.60218\nG1 X-125.464 Y139.310 E50.11579\nG1 X-130.218 Y134.876 E50.62259\nG1 X-132.569 Y132.567 E50.87953\nG1 X-137.099 Y127.877 E51.38790\nG1 X-139.325 Y125.447 E51.64485\nG1 X-141.507 Y122.981 E51.90154\nG1 X-145.685 Y118.002 E52.40833\nG1 X-149.741 Y112.810 E52.92195\nG1 X-153.561 Y107.552 E53.42874\nG1 X-155.440 Y104.819 E53.68727\nG1 X-158.980 Y99.367 E54.19406\nG1 X-160.702 Y96.558 E54.45101\nG1 X-163.962 Y90.911 E54.95938\nG1 X-165.535 Y88.015 E55.21632\nG1 X-168.496 Y82.205 E55.72470\nG1 X-169.915 Y79.231 E55.98164\nG1 X-171.280 Y76.235 E56.23834\nG1 X-173.819 Y70.251 E56.74513\nG1 X-176.180 Y64.101 E57.25875\nG1 X-178.297 Y57.955 E57.76554\nG1 X-179.294 Y54.793 E58.02407\nG1 X-181.085 Y48.544 E58.53086\nG1 X-181.911 Y45.354 E58.78780\nG1 X-183.378 Y39.001 E59.29618\nG1 X-184.035 Y35.771 E59.55312\nG1 X-185.168 Y29.350 E60.06149\nG1 X-185.655 Y26.091 E60.31844\nG1 X-186.084 Y22.826 E60.57513\nG1 X-186.764 Y16.362 E61.08192\nG1 X-187.223 Y9.790 E61.59554\nG1 X-187.450 Y3.294 E62.10233\nG1 X-187.479 Y-0.002 E62.35928\nG1 X-187.450 Y-3.294 E62.61598\nG1 X-187.223 Y-9.810 E63.12429\nG1 X-187.021 Y-13.100 E63.38129\nG1 X-186.454 Y-19.575 E63.88808\nG1 X-186.079 Y-22.870 E64.14661\nG1 X-185.174 Y-29.307 E64.65340\nG1 X-184.031 Y-35.794 E65.16702\nG1 X-182.679 Y-42.152 E65.67381\nG1 X-181.910 Y-45.357 E65.93076\nG1 X-180.223 Y-51.655 E66.43913\nG1 X-179.287 Y-54.815 E66.69607\nG1 X-177.272 Y-61.017 E67.20445\nG1 X-176.172 Y-64.123 E67.46139\nG1 X-175.019 Y-67.207 E67.71809\nG1 X-172.584 Y-73.234 E68.22488\nG1 X-169.905 Y-79.252 E68.73850\nG1 X-167.055 Y-85.094 E69.24529\nG1 X-165.524 Y-88.035 E69.50382\nG1 X-162.373 Y-93.721 E70.01061\nG1 X-160.700 Y-96.560 E70.26755\nG1 X-157.245 Y-102.090 E70.77593\nG1 X-155.427 Y-104.838 E71.03287\nG1 X-151.687 Y-110.180 E71.54124\nG1 X-149.727 Y-112.829 E71.79819\nG1 X-147.722 Y-115.441 E72.05488\nG1 X-143.631 Y-120.493 E72.56167\nG1 X-139.310 Y-125.464 E73.07529\nG1 X-134.876 Y-130.218 E73.58209\nG1 X-132.567 Y-132.569 E73.83903\nG1 X-127.877 Y-137.099 E74.34740\nG1 X-125.447 Y-139.325 E74.60435\nG1 X-122.981 Y-141.507 E74.86104\nG1 X-118.002 Y-145.685 E75.36783\nG1 X-112.810 Y-149.741 E75.88145\nG1 X-107.552 Y-153.561 E76.38824\nG1 X-104.819 Y-155.440 E76.64677\nG1 X-99.367 Y-158.980 E77.15356\nG1 X-96.558 Y-160.702 E77.41051\nG1 X-90.911 Y-163.962 E77.91888\nG1 X-88.015 Y-165.535 E78.17582\nG1 X-82.205 Y-168.496 E78.68420\nG1 X-79.231 Y-169.915 E78.94114\nG1 X-76.235 Y-171.280 E79.19784\nG1 X-70.251 Y-173.819 E79.70463\nG1 X-64.101 Y-176.180 E80.21825\nG1 X-57.955 Y-178.297 E80.72504\nG1 X-54.793 Y-179.294 E80.98356\nG1 X-48.544 Y-181.085 E81.49036\nG1 X-45.354 Y-181.911 E81.74730\nG1 X-39.001 Y-183.378 E82.25568\nG1 X-35.771 Y-184.035 E82.51262\nG1 X-29.350 Y-185.168 E83.02099\nG1 X-26.091 Y-185.655 E83.27794\nG1 X-22.826 Y-186.084 E83.53463\nG1 X-16.362 Y-186.764 E84.04142\nG1 X-9.790 Y-187.223 E84.55504\nG1 X-3.294 Y-187.450 E85.06183\nG1 X0.006 Y-187.479 E85.31908\nG1 X6.521 Y-187.366 E85.82715\nG1 X9.810 Y-187.223 E86.08379\nG1 X13.100 Y-187.021 E86.34079\nG1 X19.575 Y-186.454 E86.84758\nG1 X22.870 Y-186.079 E87.10611\nG1 X29.307 Y-185.174 E87.61290\nG1 X35.794 Y-184.031 E88.12652\nG1 X42.152 Y-182.679 E88.63331\nG1 X45.357 Y-181.910 E88.89025\nG1 X51.655 Y-180.223 E89.39863\nG1 X54.815 Y-179.287 E89.65557\nG1 X61.017 Y-177.272 E90.16395\nG1 X64.123 Y-176.172 E90.42089\nG1 X67.207 Y-175.019 E90.67759\nG1 X73.234 Y-172.584 E91.18438\nG1 X79.252 Y-169.905 E91.69800\nG1 X85.094 Y-167.055 E92.20479\nG1 X88.035 Y-165.524 E92.46332\nG1 X93.721 Y-162.373 E92.97011\nG1 X96.560 Y-160.700 E93.22705\nG1 X102.090 Y-157.245 E93.73543\nG1 X104.838 Y-155.427 E93.99237\nG1 X110.180 Y-151.687 E94.50074\nG1 X112.829 Y-149.727 E94.75768\nG1 X115.441 Y-147.722 E95.01438\nG1 X120.493 Y-143.631 E95.52117\nG1 X122.911 Y-141.529 E95.77098\n\n; end preskirt\n; start_gcode | end
+end_gcode = ; end_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; use relative positioning\n\nG91\n\n; retract the filament a bit before lifting the nozzle to release some of the pressure\n\nG1 E-1 F300\n\n; home\n\nG28\n\n; use absolute positioning\n\nG90\n\n; cooldown\n\nM104 S0\nM140 S0\n\n; end_gcode | end\n
+before_layer_gcode =
+layer_gcode =
+toolchange_gcode =
+between_objects_gcode =
+retract_length = 4
+retract_lift = 0.3
+retract_lift_above = 0
+retract_lift_below = 449
+retract_speed = 30
+deretract_speed = 0
+retract_restart_extra = 0
+retract_before_travel = 2
+retract_layer_change = 1
+wipe = 1
+retract_before_wipe = 70%
+retract_length_toolchange = 10
+retract_restart_extra_toolchange = 0
+extruder_colour = #1193FF
+machine_max_acceleration_e = 3000
+machine_max_acceleration_extruding = 1000
+machine_max_acceleration_retracting = 1000
+machine_max_acceleration_x = 1500
+machine_max_acceleration_y = 1500
+machine_max_acceleration_z = 1500
+machine_max_feedrate_e = 60
+machine_max_feedrate_x = 200
+machine_max_feedrate_y = 200
+machine_max_feedrate_z = 200
+machine_max_jerk_e = 5
+machine_max_jerk_x = 5
+machine_max_jerk_y = 5
+machine_max_jerk_z = 5
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+printer_settings_id =
+printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n
+default_filament_profile = Generic PLA @PREDATOR
+
+[printer:Anycubic Predator 0.4 nozzle]
+inherits = *common predator*
+printer_model = PREDATOR
+printer_variant = 0.4
+nozzle_diameter = 0.4
+min_layer_height = 0.08
+max_layer_height = 0.32
+default_print_profile = 0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR
+
+[printer:Anycubic Predator 0.6 nozzle]
+inherits = *common predator*
+printer_model = PREDATOR
+printer_variant = 0.6
+nozzle_diameter = 0.6
+min_layer_height = 0.12
+max_layer_height = 0.4
+default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
+
+[printer:Anycubic Predator 0.8 nozzle]
+inherits = *common predator*
+printer_model = PREDATOR
+printer_variant = 0.8
+nozzle_diameter = 0.8
+min_layer_height = 0.16
+max_layer_height = 0.48
+default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR
+
+## Anycubic 4MAX Pro 2.0
+## based on https://hartrusion.com/en/prusaslicer-config-for-anycubic-4max-pro-2-0/
+
+[print:*common_4max*]
+avoid_crossing_perimeters = 0
+avoid_crossing_perimeters_max_detour = 0
+bottom_fill_pattern = monotonic
+bottom_solid_layers = 4
+bridge_acceleration = 300
+bridge_angle = 0
+bridge_flow_ratio = 0.65
+bridge_speed = 30
+brim_separation = 0
+brim_type = outer_only
+brim_width = 0
+clip_multipart_objects = 1
+compatible_printers_condition = printer_model=="4MAXPRO20" and nozzle_diameter[0]==0.4
+complete_objects = 0
+default_acceleration = 900
+dont_support_bridges = 1
+draft_shield = disabled
+elefant_foot_compensation = 0.2
+ensure_vertical_shell_thickness = 1
+external_perimeter_extrusion_width = 0
+external_perimeter_speed = 35
+external_perimeters_first = 0
+extra_perimeters = 0
+extruder_clearance_height = 20
+extruder_clearance_radius = 20
+extrusion_width = 0.45
+fill_angle = 45
+fill_density = 20%
+fill_pattern = gyroid
+first_layer_acceleration = 300
+first_layer_acceleration_over_raft = 0
+first_layer_extrusion_width = 0.65
+first_layer_height = 0.3
+first_layer_speed = 20
+first_layer_speed_over_raft = 30
+fuzzy_skin = none
+fuzzy_skin_point_dist = 0.8
+fuzzy_skin_thickness = 0.3
+gap_fill_enabled = 1
+gap_fill_speed = 40
+gcode_comments = 0
+gcode_label_objects = 0
+gcode_resolution = 0.0125
+infill_acceleration = 600
+infill_anchor = 400%
+infill_anchor_max = 50
+infill_every_layers = 1
+infill_extruder = 1
+infill_extrusion_width = 0
+infill_first = 0
+infill_only_where_needed = 0
+infill_overlap = 23%
+infill_speed = 45
+inherits =
+interface_shells = 0
+ironing = 0
+ironing_flowrate = 15%
+ironing_spacing = 0.1
+ironing_speed = 15
+ironing_type = top
+layer_height = 0.2
+max_print_speed = 50
+max_volumetric_speed = 0
+min_skirt_length = 0
+only_retract_when_crossing_perimeters = 0
+ooze_prevention = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{print_time}.gcode
+overhangs = 1
+perimeter_acceleration = 500
+perimeter_extruder = 1
+perimeter_extrusion_width = 0
+perimeter_speed = 45
+perimeters = 3
+post_process =
+print_settings_id =
+raft_contact_distance = 0.1
+raft_expansion = 1.5
+raft_first_layer_density = 90%
+raft_first_layer_expansion = 3
+raft_layers = 0
+resolution = 0
+seam_position = aligned
+single_extruder_multi_material_priming = 1
+skirt_distance = 5
+skirt_height = 1
+skirts = 2
+slicing_mode = regular
+small_perimeter_speed = 20
+solid_infill_below_area = 0
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0
+solid_infill_speed = 45
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 0
+support_material_angle = 0
+support_material_auto = 1
+support_material_bottom_contact_distance = 0
+support_material_bottom_interface_layers = -1
+support_material_buildplate_only = 1
+support_material_closing_radius = 2
+support_material_contact_distance = 0.2
+support_material_enforce_layers = 0
+support_material_extruder = 1
+support_material_extrusion_width = 0.4
+support_material_interface_contact_loops = 0
+support_material_interface_extruder = 1
+support_material_interface_layers = 2
+support_material_interface_pattern = rectilinear
+support_material_interface_spacing = 0.2
+support_material_interface_speed = 30
+support_material_pattern = rectilinear-grid
+support_material_spacing = 2.5
+support_material_speed = 45
+support_material_style = grid
+support_material_synchronize_layers = 0
+support_material_threshold = 45
+support_material_with_sheath = 1
+support_material_xy_spacing = 60%
+thick_bridges = 1
+thin_walls = 0
+top_fill_pattern = monotonic
+top_infill_extrusion_width = 0.4
+top_solid_infill_speed = 30
+top_solid_layers = 5
+travel_speed = 60
+travel_speed_z = 0
+wipe_tower = 0
+wipe_tower_bridging = 10
+wipe_tower_brim_width = 2
+wipe_tower_no_sparse_layers = 0
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 60
+wipe_tower_x = 180
+wipe_tower_y = 140
+xy_size_compensation = 0
+
+[print:0.15mm Detail @4Max Pro 2.0]
+inherits = *common_4max*
+layer_height = 0.15
+bottom_solid_layers = 5
+top_solid_layers = 7
+perimeter_speed = 40
+external_perimeter_speed = 25
+
+[print:0.20mm Quality @4Max Pro 2.0]
+inherits = *common_4max*
+external_perimeter_speed = 25
+
+[print:0.30mm Draft @4Max Pro 2.0]
+inherits = *common_4max*
+layer_height = 0.3
+bottom_solid_layers = 3
+top_solid_layers = 3
+
+[filament:*common_4max*]
+bed_temperature = 60
+bridge_fan_speed = 100
+compatible_printers_condition = printer_model=="4MAXPRO20"
+cooling = 1
+disable_fan_first_layers = 1
+extrusion_multiplier = 1
+fan_always_on = 1
+fan_below_layer_time = 30
+filament_density = 1.24
+filament_diameter = 1.75
+filament_max_volumetric_speed = 0
+filament_type = PLA
+first_layer_bed_temperature = 60
+first_layer_temperature = 210
+full_fan_speed_layer = 5
+max_fan_speed = 100
+min_fan_speed = 80
+min_print_speed = 10
+slowdown_below_layer_time = 15
+temperature = 205
+
+[filament:*PLA_4max*]
+inherits = *common_4max*
+
+[filament:Generic PLA @4Max Pro 2.0]
+inherits = *PLA_4max*
+filament_vendor = Generic
+
+[filament:Anycubic PLA @4Max Pro 2.0]
+inherits = *PLA_4max*
+first_layer_temperature = 215
+temperature = 207
+filament_vendor = Anycubic
+
+[filament:Generic ABS @4Max Pro 2.0]
+filament_vendor = Generic
+compatible_printers_condition = printer_model=="4MAXPRO20"
+bed_temperature = 100
+first_layer_bed_temperature = 100
+temperature = 245
+first_layer_temperature = 245
+bridge_fan_speed = 15
+cooling = 1
+disable_fan_first_layers = 3
+extrusion_multiplier = 1
+fan_always_on = 0
+fan_below_layer_time = 60
+filament_colour = #800000
+filament_density = 1.04
+filament_diameter = 1.75
+filament_type = ABS
+full_fan_speed_layer = 0
+max_fan_speed = 0
+min_fan_speed = 0
+min_print_speed = 10
+slowdown_below_layer_time = 25
+
+[filament:Generic TPU @4Max Pro 2.0]
+filament_vendor = Generic
+bed_temperature = 60
+bridge_fan_speed = 0
+compatible_printers_condition = printer_model=="4MAXPRO20"
+cooling = 1
+disable_fan_first_layers = 3
+extrusion_multiplier = 1
+fan_always_on = 0
+fan_below_layer_time = 60
+filament_colour = #211AB5
+filament_density = 1.19
+filament_deretract_speed = 20
+filament_diameter = 1.75
+filament_retract_speed = 30
+filament_type = FLEX
+filament_max_volumetric_speed = 1.65
+first_layer_bed_temperature = 60
+first_layer_temperature = 215
+full_fan_speed_layer = 0
+max_fan_speed = 0
+min_fan_speed = 0
+min_print_speed = 10
+slowdown_below_layer_time = 20
+temperature = 215
+
+[filament:Polymaker PolyFlex TPU95 @4Max Pro 2.0]
+filament_vendor = Polymaker
+bed_temperature = 45
+bridge_fan_speed = 80
+compatible_printers_condition = printer_model=="4MAXPRO20"
+cooling = 1
+disable_fan_first_layers = 5
+extrusion_multiplier = 1.04
+fan_always_on = 1
+fan_below_layer_time = 45
+filament_colour = #FD7D2F
+filament_density = 1.22
+filament_deretract_speed = 25
+filament_diameter = 1.75
+filament_max_volumetric_speed = 1.65
+filament_retract_length = 4
+filament_retract_restart_extra = 0.1
+filament_retract_speed = 60
+filament_type = FLEX
+first_layer_bed_temperature = 55
+first_layer_temperature = 215
+full_fan_speed_layer = 8
+max_fan_speed = 50
+min_fan_speed = 25
+min_print_speed = 10
+slowdown_below_layer_time = 10
+temperature = 217
+
+[printer:Anycubic 4Max Pro 2.0]
+printer_model = 4MAXPRO20
+printer_variant = 0.4
+printer_technology = FFF
+bed_shape = 0x0,270x0,270x210,0x210
+color_change_gcode = M600
+default_filament_profile = Generic PLA @4Max Pro 2.0
+default_print_profile = 0.20mm Quality @4Max Pro 2.0
+deretract_speed = 25
+end_gcode = M104 S0 ; turn off extruder heating\nM140 S0 ; turn off bed heating\nM107 ; turn off fans\nG91 ; relative positioning\nG0 Z+0.5 ; move Z up a tiny bit\nG90 ; absolute positioning\nG0 X135 Y105 F{machine_max_feedrate_x[0]*60} ; move extruder to center position\nG0 Z190.5 F{machine_max_feedrate_z[0]*60} ; lower the plattform to Z min\nM84 ; steppers off\nG90 ; absolute positioning\n
+extruder_offset = 0x0
+gcode_flavor = marlin
+machine_limits_usage = time_estimate_only
+machine_max_acceleration_e = 5000
+machine_max_acceleration_extruding = 1250
+machine_max_acceleration_retracting = 1250
+machine_max_acceleration_travel = 1500
+machine_max_acceleration_x = 900
+machine_max_acceleration_y = 900
+machine_max_acceleration_z = 100
+machine_max_feedrate_e = 120
+machine_max_feedrate_x = 200
+machine_max_feedrate_y = 200
+machine_max_feedrate_z = 16
+machine_max_jerk_e = 5
+machine_max_jerk_x = 6
+machine_max_jerk_y = 6
+machine_max_jerk_z = 0.2
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+max_layer_height = 0.3
+max_print_height = 190
+min_layer_height = 0.07
+nozzle_diameter = 0.4
+pause_print_gcode = M601
+remaining_times = 0
+retract_before_travel = 2
+retract_before_wipe = 0%
+retract_layer_change = 1
+retract_length = 2.5
+retract_length_toolchange = 10
+retract_lift = 0
+retract_lift_above = 0
+retract_lift_below = 0
+retract_restart_extra = 0
+retract_restart_extra_toolchange = 0
+retract_speed = 35
+silent_mode = 0
+single_extruder_multi_material = 0
+start_gcode = G21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 X0 Y0 ; home X and Y\nG28 Z0 ; home Z\nG1 Z30 F{machine_max_feedrate_z[0]*60} ; move Z a bit down to not blow on the bed edge while heating\nG1 X10 F3900 ; let some space on x to prevent the filament cooling exhaust from beeing blocked by the servo motor\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM104 S[first_layer_temperature] ; set extruder temp\nM106 S80 ; turn on fan to prevent air nozzle melt while heating up\nM109 S[first_layer_temperature] ; wait for extruder temp\nM107 ; start with the fan off\nG28 X0 ; goto X home again\nG92 E0 ; zero the extruded length\nG1 Z0.2 F360 ; move plattform upwards\n; extrude material next to the plattform (comment or remove following lines to disable)\nG1 F180 E20 ; extrude some material next to the plattform\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG92 E0 ; zero the extruded length again\nG1 X5 F3900 ; move sideways to get rid of that string\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\nG92 E0 ; zero the extruded length again\n; draw intro line (comment or remove following lines to disable)\nG1 X30 E5 F700 ; draw intro line\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG1 X40 Z2.0 ; move away from the introline\nG92 E0 ; zero the extruded length again\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\n; end of intro line code\nM117 Printing...\nG5
+use_firmware_retraction = 0
+use_relative_e_distances = 0
+use_volumetric_e = 0
+variable_layer_height = 1
+wipe = 0
+z_offset = 0
+
+########## SLA printer presets ##########
+
+[sla_print:*common print ANYCUBIC SLA*]
+compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
+layer_height = 0.05
+output_filename_format = [input_filename_base].pwmx
+pad_edge_radius = 0.5
+pad_enable = 0
+pad_max_merge_distance = 50
+pad_wall_height = 0
+pad_wall_thickness = 1
+pad_wall_slope = 45
+faded_layers = 8
+slice_closing_radius = 0.005
+support_base_diameter = 3
+support_base_height = 1
+support_critical_angle = 45
+support_density_at_45 = 250
+support_density_at_horizontal = 500
+support_head_front_diameter = 0.4
+support_head_penetration = 0.4
+support_head_width = 3
+support_max_bridge_length = 10
+support_minimal_z = 0
+support_object_elevation = 5
+support_pillar_diameter = 1
+support_pillar_connection_mode = zigzag
+support_pillar_widening_factor = 0
+supports_enable = 1
+support_small_pillar_diameter_percent = 60%
+
+[sla_print:0.05 Normal @ANYCUBIC]
+inherits = *common print ANYCUBIC SLA*
+layer_height = 0.05
+
+########### Materials
+
+[sla_material:*common ANYCUBIC SLA*]
+compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
+compatible_prints_condition = layer_height == 0.05
+exposure_time = 7
+initial_exposure_time = 40
+initial_layer_height = 0.05
+material_correction = 1,1,1
+material_notes = LIFT_DISTANCE=8.0\nLIFT_SPEED=2.5\nRETRACT_SPEED=3.0\nBOTTOM_LIFT_SPEED=2.0\nBOTTOM_LIFT_DISTANCE=9.0\nDELAY_BEFORE_EXPOSURE=0.5
+
+[sla_material:*common 0.05 ANYCUBIC SLA*]
+inherits = *common ANYCUBIC SLA*
+
+[sla_material:Generic Blue Resin @MONO 0.05]
+inherits = *common 0.05 ANYCUBIC SLA*
+exposure_time = 2.5
+initial_exposure_time = 40
+material_type = Tough
+material_vendor = Generic
+material_colour = #6080EC
+compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/
+
+########## Printers
+
+[printer:Anycubic Photon Mono X]
+printer_technology = SLA
+printer_model = PHOTON MONO X
+printer_variant = default
+default_sla_material_profile = Generic Blue Resin @MONO 0.05
+default_sla_print_profile = 0.05 Normal @ANYCUBIC
+thumbnails = 224x168
+sla_archive_format = pwmx
+bed_shape = 1.48x1.02,193.48x1.02,193.48x121.02,1.48x121.02
+display_height = 120
+display_orientation = landscape
+display_mirror_x = 1
+display_mirror_y = 0
+display_pixels_x = 3840
+display_pixels_y = 2400
+display_width = 192
+max_print_height = 245
+elefant_foot_compensation = 0.2
+elefant_foot_min_width = 0.2
+min_exposure_time = 1
+max_exposure_time = 120
+min_initial_exposure_time = 1
+max_initial_exposure_time = 300
+printer_correction = 1,1,1
+gamma_correction = 1
+area_fill = 45
+printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.'\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PHOTONMONOX\n
diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx
index 9ee9035631..d63336c2ef 100644
--- a/resources/profiles/PrusaResearch.idx
+++ b/resources/profiles/PrusaResearch.idx
@@ -1,4 +1,5 @@
min_slic3r_version = 2.4.0-rc
+1.4.4 Added multiple Fiberlogy filament profiles. Updated Extrudr filament profiles.
1.4.3 Added new filament profiles and SLA materials.
1.4.2 Added SLA material profiles.
1.4.1 Updated firmware version.
diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini
index 3182eba6bb..4af1e35ed1 100644
--- a/resources/profiles/PrusaResearch.ini
+++ b/resources/profiles/PrusaResearch.ini
@@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
-config_version = 1.4.3
+config_version = 1.4.4
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@@ -2050,7 +2050,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MK2S
inherits = Fillamentum ASA
filament_vendor = Extrudr
bed_temperature = 90
-filament_cost = 25.98
+filament_cost = 34.64
filament_density = 1.05
filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=120"
first_layer_bed_temperature = 90
@@ -2083,8 +2083,8 @@ filament_vendor = Extrudr
[filament:Extrudr XPETG CF]
inherits = Extrudr PETG
-filament_cost = 49.99
-filament_density = 1.41
+filament_cost = 62.49
+filament_density = 1.29
filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=198"
first_layer_temperature = 235
temperature = 235
@@ -2125,7 +2125,7 @@ filament_spool_weight = 230
[filament:Extrudr Flax]
inherits = *PLA*
filament_vendor = Extrudr
-filament_cost = 56.23
+filament_cost = 50.91
filament_density = 1.45
filament_notes = "High Performance Filament for decorative parts.\nPrints as easily as PLA with much higher strength and temperature resistance.\nFully biodegradable with a nice matt finish.\n\nhttps://www.extrudr.com/en/products/catalogue/?material=131"
first_layer_temperature = 190
@@ -2140,13 +2140,13 @@ filament_spool_weight = 262
[filament:Extrudr GreenTEC]
inherits = *PLA*
filament_vendor = Extrudr
-filament_cost = 56
+filament_cost = 50.91
filament_density = 1.3
-filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=106"
+filament_notes = "https://www.extrudr.com/en/products/catalogue/?ignorechildren=1&material=106"
first_layer_temperature = 208
temperature = 208
slowdown_below_layer_time = 20
-filament_spool_weight = 230
+filament_spool_weight = 262
[filament:Extrudr GreenTEC Pro]
inherits = *PLA*
@@ -2164,7 +2164,7 @@ filament_spool_weight = 230
[filament:Extrudr GreenTEC Pro Carbon]
inherits = *PLA*
filament_vendor = Extrudr
-filament_cost = 56.23
+filament_cost = 62.49
filament_density = 1.2
filament_notes = "High Performance Filament for technical parts.\nPrints as easily as PLA with much higher stregnth and temperature resistance.\nFully biodegradable with a nice matt finish.\n\nhttps://www.extrudr.com/en/products/catalogue/?material=138"
first_layer_temperature = 225
@@ -2221,8 +2221,8 @@ extrusion_multiplier = 1.2
filament_cost = 39.98
filament_density = 1.19
filament_deretract_speed = nil
-filament_max_volumetric_speed = 2
-filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=115"
+filament_max_volumetric_speed = 3
+filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=117"
filament_retract_length = 0.4
filament_wipe = nil
filament_spool_weight = 230
@@ -2236,8 +2236,8 @@ extrusion_multiplier = 1.2
filament_cost = 39.98
filament_density = 1.18
filament_deretract_speed = nil
-filament_max_volumetric_speed = 1.2
-filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=115"
+filament_max_volumetric_speed = 1.8
+filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=116"
filament_retract_length = 0.4
filament_wipe = nil
filament_spool_weight = 230
@@ -3511,13 +3511,6 @@ filament_density = 1.27
filament_spool_weight = 235
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
-[filament:Fiberlogy PETG]
-inherits = *PET*
-filament_vendor = Fiberlogy
-filament_cost = 21.50
-filament_density = 1.27
-compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
-
[filament:Prusament PETG]
inherits = *PET*
filament_vendor = Prusa Polymers
@@ -3580,8 +3573,9 @@ filament_density = 1.27
filament_spool_weight = 235
filament_type = PETG
-[filament:Fiberlogy PETG @0.6 nozzle]
+[filament:Fiberlogy Easy PET-G @0.6 nozzle]
inherits = *PET06*
+renamed_from = Fiberlogy PETG @0.6 nozzle
filament_vendor = Fiberlogy
first_layer_temperature = 230
temperature = 240
@@ -3673,11 +3667,297 @@ filament_density = 1.24
filament_spool_weight = 230
compatible_printers_condition = nozzle_diameter[0]!=0.8 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
-[filament:Fiberlogy PLA]
+[filament:Fiberlogy Easy PLA]
inherits = *PLA*
+renamed_from = Fiberlogy PLA
filament_vendor = Fiberlogy
-filament_cost = 25.4
+filament_cost = 20
filament_density = 1.24
+first_layer_temperature = 220
+temperature = 220
+filament_spool_weight = 330
+
+[filament:Fiberlogy Easy PET-G]
+inherits = *PET*
+renamed_from = Fiberlogy PETG
+filament_vendor = Fiberlogy
+filament_spool_weight = 330
+filament_cost = 20
+filament_density = 1.27
+compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
+first_layer_bed_temperature = 80
+bed_temperature = 80
+first_layer_temperature = 235
+temperature = 235
+min_fan_speed = 15
+max_fan_speed = 30
+bridge_fan_speed = 60
+disable_fan_first_layers = 5
+full_fan_speed_layer = 5
+slowdown_below_layer_time = 15
+
+[filament:Fiberlogy ASA]
+inherits = *ABS*
+filament_vendor = Fiberlogy
+filament_cost = 33
+filament_density = 1.07
+filament_spool_weight = 330
+fan_always_on = 0
+cooling = 1
+min_fan_speed = 10
+max_fan_speed = 15
+bridge_fan_speed = 30
+min_print_speed = 15
+slowdown_below_layer_time = 15
+first_layer_temperature = 260
+temperature = 260
+first_layer_bed_temperature = 105
+bed_temperature = 110
+filament_type = ASA
+fan_below_layer_time = 30
+disable_fan_first_layers = 5
+
+[filament:Fiberlogy ASA @MINI]
+inherits = Fiberlogy ASA; *ABSMINI*
+
+[filament:Fiberlogy Easy ABS]
+inherits = Fiberlogy ASA
+filament_cost = 22.67
+filament_density = 1.09
+fan_always_on = 0
+cooling = 1
+min_fan_speed = 10
+max_fan_speed = 15
+min_print_speed = 15
+slowdown_below_layer_time = 15
+first_layer_temperature = 250
+temperature = 250
+first_layer_bed_temperature = 100
+bed_temperature = 100
+filament_type = ABS
+fan_below_layer_time = 25
+disable_fan_first_layers = 5
+
+[filament:Fiberlogy Easy ABS @MINI]
+inherits = Fiberlogy Easy ABS; *ABSMINI*
+
+[filament:Fiberlogy CPE HT]
+inherits = *PET*
+filament_vendor = Fiberlogy
+filament_cost = 42.67
+filament_density = 1.18
+extrusion_multiplier = 0.98
+filament_spool_weight = 330
+fan_always_on = 1
+cooling = 1
+min_fan_speed = 0
+max_fan_speed = 0
+bridge_fan_speed = 50
+min_print_speed = 15
+first_layer_temperature = 275
+temperature = 275
+first_layer_bed_temperature = 105
+bed_temperature = 110
+filament_type = CPE
+fan_below_layer_time = 20
+slowdown_below_layer_time = 15
+disable_fan_first_layers = 5
+
+[filament:Fiberlogy PCTG]
+inherits = Fiberlogy CPE HT
+filament_vendor = Fiberlogy
+filament_cost = 29.41
+filament_density = 1.23
+extrusion_multiplier = 0.98
+min_fan_speed = 10
+max_fan_speed = 15
+bridge_fan_speed = 50
+min_print_speed = 15
+first_layer_temperature = 265
+temperature = 265
+first_layer_bed_temperature = 90
+bed_temperature = 90
+filament_type = CPE
+fan_below_layer_time = 20
+slowdown_below_layer_time = 15
+disable_fan_first_layers = 5
+
+[filament:Fiberlogy FiberFlex 40D]
+inherits = *FLEX*
+filament_vendor = Fiberlogy
+fan_always_on = 1
+filament_max_volumetric_speed = 1.5
+extrusion_multiplier = 1.12
+first_layer_temperature = 230
+first_layer_bed_temperature = 60
+temperature = 230
+bed_temperature = 60
+bridge_fan_speed = 75
+min_fan_speed = 25
+max_fan_speed = 75
+filament_retract_before_travel = 2
+filament_cost = 39.41
+filament_density = 1.16
+filament_retract_length = 1.2
+filament_retract_speed = nil
+filament_deretract_speed = 20
+filament_retract_lift = 0
+filament_wipe = 0
+disable_fan_first_layers = 5
+full_fan_speed_layer = 5
+min_print_speed = 15
+cooling = 1
+filament_spool_weight = 330
+
+[filament:Fiberlogy FiberFlex 40D @MINI]
+inherits = *FLEXMINI*
+filament_vendor = Fiberlogy
+filament_max_volumetric_speed = 1.5
+fan_always_on = 1
+first_layer_temperature = 240
+first_layer_bed_temperature = 60
+temperature = 240
+bed_temperature = 60
+filament_retract_length = 4
+filament_retract_before_travel = 5
+bridge_fan_speed = 80
+min_fan_speed = 25
+max_fan_speed = 60
+min_print_speed = 15
+slowdown_below_layer_time = 10
+cooling = 1
+filament_cost = 84.68
+
+[filament:Fiberlogy MattFlex 40D]
+inherits = Fiberlogy FiberFlex 40D
+filament_vendor = Fiberlogy
+fan_always_on = 1
+filament_max_volumetric_speed = 1.35
+extrusion_multiplier = 1.1
+filament_retract_before_travel = 2
+filament_cost = 49.11
+filament_retract_length = 1.2
+
+[filament:Fiberlogy FiberFlex 30D]
+inherits = Fiberlogy FiberFlex 40D
+filament_max_volumetric_speed = 1.2
+extrusion_multiplier = 1.15
+first_layer_temperature = 240
+temperature = 240
+min_fan_speed = 25
+max_fan_speed = 60
+filament_density = 1.07
+filament_retract_length = 1.2
+
+[filament:Fiberlogy FiberSatin]
+inherits = Fiberlogy Easy PLA
+first_layer_temperature = 215
+temperature = 215
+extrusion_multiplier = 1.03
+filament_density = 1.2
+filament_cost = 32.35
+
+[filament:Fiberlogy FiberSilk]
+inherits = Fiberlogy FiberSatin
+first_layer_temperature = 230
+temperature = 230
+extrusion_multiplier = 0.97
+filament_density = 1.22
+filament_cost = 32.35
+
+[filament:Fiberlogy FiberWood]
+inherits = Fiberlogy Easy PLA
+first_layer_temperature = 185
+temperature = 185
+extrusion_multiplier = 1
+filament_density = 1.23
+filament_cost = 38.66
+filament_max_volumetric_speed = 8
+
+[filament:Fiberlogy HD PLA]
+inherits = Fiberlogy Easy PLA
+first_layer_temperature = 230
+temperature = 230
+extrusion_multiplier = 1
+filament_density = 1.24
+filament_cost = 30.59
+
+[filament:Fiberlogy PLA Mineral]
+inherits = Fiberlogy Easy PLA
+first_layer_temperature = 195
+temperature = 190
+extrusion_multiplier = 0.98
+filament_density = 1.38
+filament_cost = 37.64
+filament_max_volumetric_speed = 10
+
+[filament:Fiberlogy Impact PLA]
+inherits = Fiberlogy HD PLA
+filament_density = 1.22
+filament_cost = 27.65
+
+[filament:Fiberlogy Nylon PA12]
+inherits = Fiberlogy ASA
+filament_type = NYLON
+filament_density = 1.01
+filament_cost = 48
+first_layer_bed_temperature = 105
+bed_temperature = 110
+first_layer_temperature = 265
+temperature = 265
+min_fan_speed = 10
+max_fan_speed = 15
+fan_below_layer_time = 20
+bridge_fan_speed = 30
+fan_always_on = 0
+filament_retract_lift = 0.2
+filament_max_volumetric_speed = 6
+start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.02{elsif nozzle_diameter[0]==0.6}0.04{else}0.08{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K26{elsif nozzle_diameter[0]==0.8};{else}M900 K45{endif} ; Filament gcode LA 1.0"
+
+[filament:Fiberlogy Nylon PA12+CF15]
+inherits = Fiberlogy Nylon PA12
+extrusion_multiplier = 0.97
+filament_density = 1.07
+filament_cost = 87.5
+first_layer_bed_temperature = 105
+bed_temperature = 110
+first_layer_temperature = 265
+temperature = 265
+min_fan_speed = 10
+max_fan_speed = 15
+fan_below_layer_time = 20
+bridge_fan_speed = 30
+fan_always_on = 0
+filament_max_volumetric_speed = 8
+compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
+
+[filament:Fiberlogy Nylon PA12+GF15]
+inherits = Fiberlogy Nylon PA12+CF15
+filament_density = 1.13
+filament_max_volumetric_speed = 8
+
+[filament:Fiberlogy PP]
+inherits = *ABS*
+filament_vendor = Fiberlogy
+filament_cost = 36.67
+filament_density = 1.05
+extrusion_multiplier = 1.05
+filament_spool_weight = 330
+fan_always_on = 1
+cooling = 1
+min_fan_speed = 0
+max_fan_speed = 25
+bridge_fan_speed = 70
+min_print_speed = 15
+slowdown_below_layer_time = 15
+first_layer_temperature = 245
+temperature = 245
+first_layer_bed_temperature = 0
+bed_temperature = 0
+filament_type = PP
+fan_below_layer_time = 100
+disable_fan_first_layers = 5
+filament_max_volumetric_speed = 5
[filament:Filament PM PLA]
inherits = *PLA*
@@ -3736,7 +4016,7 @@ filament_density = 1.24
inherits = *PLA*
filament_vendor = Prusa Polymers
temperature = 215
-filament_cost = 30.24
+filament_cost = 36.29
filament_density = 1.24
filament_spool_weight = 201
filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa"
@@ -3790,7 +4070,7 @@ filament_spool_weight = 230
[filament:Prusament PLA @MMU2]
inherits = *PLA MMU2*
filament_vendor = Prusa Polymers
-filament_cost = 30.24
+filament_cost = 36.29
filament_density = 1.24
filament_spool_weight = 201
@@ -4124,8 +4404,9 @@ renamed_from = "Plasty Mladec PETG @MMU1"
[filament:Verbatim PETG @MMU1]
inherits = Verbatim PETG; *PETMMU1*
-[filament:Fiberlogy PETG @MMU1]
-inherits = Fiberlogy PETG; *PETMMU1*
+[filament:Fiberlogy Easy PET-G @MMU1]
+inherits = Fiberlogy Easy PET-G; *PETMMU1*
+renamed_from = Fiberlogy PETG @MMU1
[filament:Prusa PETG @MMU1]
inherits = Prusa PETG; *PETMMU1*
@@ -4215,8 +4496,9 @@ compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.
inherits = Verbatim PETG; *PETMINI*
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
-[filament:Fiberlogy PETG @MINI]
-inherits = Fiberlogy PETG; *PETMINI*
+[filament:Fiberlogy Easy PET-G @MINI]
+inherits = Fiberlogy Easy PET-G; *PETMINI*
+renamed_from = Fiberlogy PETG @MINI
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
[filament:Generic ABS @MINI]
@@ -4303,8 +4585,9 @@ renamed_from = "Plasty Mladec PETG @0.6 nozzle MINI"
[filament:Verbatim PETG @0.6 nozzle MINI]
inherits = Verbatim PETG; *PETMINI06*
-[filament:Fiberlogy PETG @0.6 nozzle MINI]
-inherits = Fiberlogy PETG; *PETMINI06*
+[filament:Fiberlogy Easy PET-G @0.6 nozzle MINI]
+inherits = Fiberlogy Easy PET-G; *PETMINI06*
+renamed_from = Fiberlogy PETG @0.6 nozzle MINI
[filament:Prusament ASA @MINI]
inherits = Prusament ASA; *ABSMINI*
diff --git a/resources/profiles/Snapmaker.idx b/resources/profiles/Snapmaker.idx
new file mode 100644
index 0000000000..03488b17c5
--- /dev/null
+++ b/resources/profiles/Snapmaker.idx
@@ -0,0 +1,2 @@
+min_slic3r_version = 2.4.1
+1.0.0 Initial Snapmaker bundle
diff --git a/resources/profiles/Snapmaker.ini b/resources/profiles/Snapmaker.ini
new file mode 100644
index 0000000000..68e32910b1
--- /dev/null
+++ b/resources/profiles/Snapmaker.ini
@@ -0,0 +1,473 @@
+# Snapmaker profiles
+
+# Based on the profiles from: https://github.com/nivekmai/snapmaker-prusa by nivekmai, WilliamBosacker, mrworf
+
+[vendor]
+# Vendor name will be shown by the Config Wizard.
+name = Snapmaker
+# Configuration version of this file. Config file will only be installed, if the config_version differs.
+# This means, the server may force the Slic3r configuration to be downgraded.
+config_version = 1.0.0
+# Where to get the updates from?
+config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Snapmaker/
+# The printer models will be shown by the Configuration Wizard in this order,
+
+[printer_model:A250]
+name = Snapmaker A250
+variants = 0.4
+technology = FFF
+bed_model = A250_bed.stl
+bed_texture = A250_texture.svg
+default_materials = Generic PLA @Snapmaker; Generic PETG @Snapmaker
+
+[printer_model:A350]
+name = Snapmaker A350
+variants = 0.4
+technology = FFF
+bed_model = A350_bed.stl
+bed_texture = A350_texture.svg
+default_materials = Generic PLA @Snapmaker; Generic PETG @Snapmaker
+
+[print:*common*]
+avoid_crossing_perimeters = 1
+avoid_crossing_perimeters_max_detour = 0
+bottom_fill_pattern = monotonic
+bottom_solid_layers = 4
+bottom_solid_min_thickness = 0
+bridge_acceleration = 0
+bridge_angle = 0
+bridge_flow_ratio = 1
+bridge_speed = 60
+brim_separation = 0
+brim_type = outer_only
+brim_width = 0
+clip_multipart_objects = 1
+complete_objects = 0
+default_acceleration = 0
+dont_support_bridges = 1
+draft_shield = disabled
+elefant_foot_compensation = 0.1
+ensure_vertical_shell_thickness = 1
+external_perimeter_extrusion_width = 0.45
+external_perimeter_speed = 50%
+external_perimeters_first = 0
+extra_perimeters = 0
+extruder_clearance_height = 25
+extruder_clearance_radius = 75
+extrusion_width = 0.45
+fill_angle = 45
+fill_density = 20%
+fill_pattern = gyroid
+first_layer_acceleration = 0
+first_layer_acceleration_over_raft = 0
+first_layer_extrusion_width = 0.45
+first_layer_height = 0.2
+first_layer_speed = 15
+first_layer_speed_over_raft = 30
+fuzzy_skin = none
+fuzzy_skin_point_dist = 0.8
+fuzzy_skin_thickness = 0.3
+gap_fill_enabled = 1
+gap_fill_speed = 20
+gcode_comments = 0
+gcode_label_objects = 0
+gcode_resolution = 0.0125
+gcode_substitutions =
+infill_acceleration = 0
+infill_anchor = 600%
+infill_anchor_max = 50
+infill_every_layers = 1
+infill_extruder = 1
+infill_extrusion_width = 0.45
+infill_first = 0
+infill_only_where_needed = 0
+infill_overlap = 25%
+infill_speed = 100
+inherits =
+interface_shells = 0
+ironing = 0
+ironing_flowrate = 15%
+ironing_spacing = 0.25
+ironing_speed = 15
+ironing_type = top
+layer_height = 0.2
+max_print_speed = 100
+max_volumetric_speed = 0
+min_skirt_length = 4
+mmu_segmented_region_max_width = 0
+notes =
+only_retract_when_crossing_perimeters = 0
+ooze_prevention = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
+overhangs = 0
+perimeter_acceleration = 0
+perimeter_extruder = 1
+perimeter_extrusion_width = 0.45
+perimeter_speed = 60
+perimeters = 2
+post_process =
+print_settings_id =
+raft_contact_distance = 0.1
+raft_expansion = 1.5
+raft_first_layer_density = 90%
+raft_first_layer_expansion = 3
+raft_layers = 0
+resolution = 0
+seam_position = nearest
+single_extruder_multi_material_priming = 1
+skirt_distance = 5
+skirt_height = 1
+skirts = 3
+slice_closing_radius = 0.049
+slicing_mode = regular
+small_perimeter_speed = 25%
+solid_infill_below_area = 0
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0.45
+solid_infill_speed = 80%
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 0
+support_material_angle = 0
+support_material_auto = 1
+support_material_bottom_contact_distance = 0
+support_material_bottom_interface_layers = -1
+support_material_buildplate_only = 0
+support_material_closing_radius = 2
+support_material_contact_distance = 0.15
+support_material_enforce_layers = 0
+support_material_extruder = 0
+support_material_extrusion_width = 0.38
+support_material_interface_contact_loops = 0
+support_material_interface_extruder = 0
+support_material_interface_layers = 2
+support_material_interface_pattern = rectilinear
+support_material_interface_spacing = 0.2
+support_material_interface_speed = 100%
+support_material_pattern = rectilinear
+support_material_spacing = 2
+support_material_speed = 60
+support_material_style = grid
+support_material_synchronize_layers = 0
+support_material_threshold = 45
+support_material_with_sheath = 0
+support_material_xy_spacing = 60%
+thick_bridges = 1
+thin_walls = 0
+threads = 8
+top_fill_pattern = monotonic
+top_infill_extrusion_width = 0.4
+top_solid_infill_speed = 60%
+top_solid_layers = 4
+top_solid_min_thickness = 0
+travel_speed = 150
+travel_speed_z = 0
+wipe_tower = 0
+wipe_tower_bridging = 10
+wipe_tower_brim_width = 2
+wipe_tower_no_sparse_layers = 0
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 60
+wipe_tower_x = 170
+wipe_tower_y = 140
+xy_size_compensation = 0
+compatible_printers_condition = nozzle_diameter[0]==0.4
+
+[print:0.10mm HIGHDETAIL @SnapmakerA350]
+inherits = *common*
+layer_height = 0.1
+bottom_solid_layers = 7
+top_solid_layers = 8
+top_solid_min_thickness = 0.8
+bottom_solid_min_thickness = 0.8
+bridge_speed = 40
+infill_speed = 50
+perimeter_speed = 40
+support_material_speed = 40
+max_print_speed = 50
+skirt_distance = 10
+first_layer_speed = 25%
+compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350"
+
+[print:0.16mm OPTIMAL @SnapmakerA350]
+inherits = *common*
+layer_height = 0.16
+top_solid_layers = 6
+bottom_solid_layers = 6
+first_layer_speed = 25%
+max_print_speed = 60
+compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350"
+
+[print:0.20mm NORMAL @SnapmakerA350]
+inherits = *common*
+compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350"
+
+[print:0.20mm FAST @SnapmakerA350]
+inherits = 0.20mm NORMAL @SnapmakerA350
+bridge_speed = 80
+gap_fill_speed = 30
+infill_speed = 120
+ironing_speed = 20
+perimeter_speed = 80
+support_material_speed = 80
+compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350"
+
+[print:0.08mm DETAIL @SnapmakerA250]
+inherits = 0.20mm NORMAL @SnapmakerA250
+layer_height = 0.08
+infill_speed = 40
+external_perimeter_speed = 10
+perimeter_speed = 15
+top_solid_infill_speed = 20
+travel_speed = 70
+first_layer_extrusion_width = 0.45
+perimeter_extrusion_width = 0.4
+external_perimeter_extrusion_width = 0.4
+infill_extrusion_width = 0.4
+solid_infill_extrusion_width = 0.4
+top_infill_extrusion_width = 0.4
+
+[print:0.20mm NORMAL @SnapmakerA250]
+inherits = *common*
+compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A250"
+first_layer_speed = 15
+gap_fill_speed = 15
+infill_speed = 50
+perimeter_speed = 25
+small_perimeter_speed = 20
+external_perimeter_speed = 15
+support_material_speed = 25
+top_solid_infill_speed = 25
+travel_speed = 80
+max_print_speed = 80
+skirt_distance = 3
+min_skirt_length = 25
+
+[print:0.24mm FAST @SnapmakerA250]
+inherits = 0.20mm NORMAL @SnapmakerA250
+layer_height = 0.24
+infill_speed = 60
+external_perimeter_speed = 20
+top_solid_infill_speed = 30
+
+[filament:*common*]
+bed_temperature = 60
+bridge_fan_speed = 100
+compatible_printers =
+compatible_printers_condition =
+compatible_prints =
+compatible_prints_condition =
+cooling = 1
+disable_fan_first_layers = 3
+end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
+extrusion_multiplier = 1
+fan_always_on = 1
+fan_below_layer_time = 60
+filament_colour = #29B2B2
+filament_cooling_final_speed = 3.4
+filament_cooling_initial_speed = 2.2
+filament_cooling_moves = 4
+filament_cost = 0
+filament_density = 0
+filament_deretract_speed = nil
+filament_diameter = 1.75
+filament_load_time = 0
+filament_loading_speed = 28
+filament_loading_speed_start = 3
+filament_max_volumetric_speed = 0
+filament_minimal_purge_on_wipe_tower = 15
+filament_notes = ""
+filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
+filament_retract_before_travel = nil
+filament_retract_before_wipe = nil
+filament_retract_layer_change = nil
+filament_retract_length = nil
+filament_retract_lift = nil
+filament_retract_lift_above = nil
+filament_retract_lift_below = nil
+filament_retract_restart_extra = nil
+filament_retract_speed = nil
+filament_settings_id = ""
+filament_soluble = 0
+filament_spool_weight = 0
+filament_toolchange_delay = 0
+filament_type = PLA
+filament_unload_time = 0
+filament_unloading_speed = 90
+filament_unloading_speed_start = 100
+filament_wipe = nil
+first_layer_bed_temperature = 60
+first_layer_temperature = 210
+full_fan_speed_layer = 0
+inherits =
+max_fan_speed = 100
+min_fan_speed = 35
+min_print_speed = 10
+slowdown_below_layer_time = 5
+start_filament_gcode = "; Filament gcode\n"
+temperature = 210
+
+[filament:*PLA*]
+inherits = *common*
+
+[filament:*PETG*]
+inherits = *common*
+first_layer_bed_temperature = 80
+bed_temperature = 75
+first_layer_temperature = 245
+temperature = 245
+filament_density = 1.27
+disable_fan_first_layers = 3
+min_fan_speed = 20
+max_fan_speed = 50
+fan_below_layer_time = 20
+min_print_speed = 20
+filament_max_volumetric_speed = 8
+filament_type = PETG
+
+[filament:Generic PLA @Snapmaker]
+inherits = *PLA*
+filament_vendor = Generic
+
+[filament:Generic PETG @Snapmaker]
+inherits = *PETG*
+filament_vendor = Generic
+
+[filament:Snapmaker PLA @Snapmaker]
+inherits = *PLA*
+filament_vendor = Snapmaker
+
+[filament:Overture PLA @Snapmaker]
+inherits = *PLA*
+filament_vendor = Overture
+bed_temperature = 50
+first_layer_temperature = 205
+temperature = 205
+filament_density = 1.24
+disable_fan_first_layers = 1
+min_fan_speed = 100
+max_fan_speed = 100
+full_fan_speed_layer = 3
+fan_below_layer_time = 100
+min_print_speed = 15
+filament_max_volumetric_speed = 0
+
+[filament:MatterHackers Build Translucent @Snapmaker]
+inherits = *PETG*
+filament_vendor = MatterHackers
+
+[filament:MatterHackers Build White @Snapmaker]
+inherits = MatterHackers Build Translucent @Snapmaker
+bed_temperature = 65
+first_layer_bed_temperature = 70
+first_layer_temperature = 260
+temperature = 255
+filament_density = 1.28
+disable_fan_first_layers = 3
+full_fan_speed_layer = 5
+min_fan_speed = 40
+max_fan_speed = 100
+fan_below_layer_time = 60
+min_print_speed = 10
+
+[filament:Overture TPU @Snapmaker]
+inherits = *common*
+filament_vendor = Overture
+filament_type = FLEX
+first_layer_temperature = 220
+temperature = 220
+filament_density = 1.22
+disable_fan_first_layers = 1
+min_fan_speed = 100
+max_fan_speed = 100
+fan_below_layer_time = 100
+min_print_speed = 15
+filament_retract_speed = 40
+filament_deretract_speed = 25
+filament_retract_length = 1.8
+filament_max_volumetric_speed = 3
+
+# Common printer preset
+[printer:*common*]
+bed_shape = 0x0,320x0,320x350,0x350
+color_change_gcode = M600
+cooling_tube_length = 5
+cooling_tube_retraction = 91.5
+default_filament_profile = ""
+default_print_profile =
+end_gcode = ;End GCode begin\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off\nG90 ;absolute positioning\nG92 E0\nG1 E-2 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG28 X0 Y0 ; home\nM84 ;steppers off\nM107 ;fan off\nM82 ;absolute extrusion mode\n;End GCode end
+extra_loading_move = -2
+extruder_colour = ""
+extruder_offset = 0x0
+gcode_flavor = marlin
+high_current_on_filament_swap = 0
+machine_limits_usage = time_estimate_only
+machine_max_acceleration_e = 10000
+machine_max_acceleration_extruding = 1000
+machine_max_acceleration_retracting = 1000
+machine_max_acceleration_travel = 1500
+machine_max_acceleration_x = 3000
+machine_max_acceleration_y = 3000
+machine_max_acceleration_z = 100
+machine_max_feedrate_e = 25
+machine_max_feedrate_x = 150
+machine_max_feedrate_y = 150
+machine_max_feedrate_z = 50
+machine_max_jerk_e = 2.5
+machine_max_jerk_x = 10
+machine_max_jerk_y = 10
+machine_max_jerk_z = 0.2
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+max_layer_height = 0.3
+max_print_height = 330
+min_layer_height = 0.08
+nozzle_diameter = 0.4
+parking_pos_retraction = 92
+pause_print_gcode =
+printer_technology = FFF
+remaining_times = 0
+retract_before_travel = 2
+retract_before_wipe = 0%
+retract_layer_change = 1
+retract_length = 3
+retract_length_toolchange = 10
+retract_lift = 0
+retract_lift_above = 0
+retract_lift_below = 328
+retract_restart_extra = 0
+retract_restart_extra_toolchange = 0
+retract_speed = 60
+deretract_speed = 40
+silent_mode = 0
+single_extruder_multi_material = 0
+start_gcode = M82 ;absolute extrusion mode\n;Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start warming Bed\nM104 S[first_layer_temperature] ;Start warming Nozzle\nG28 ; home all axes\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000\nG1 Z0 F1800\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0\nG1 E20 F200 ; Prime extrude for wipe\nG92 E0
+thumbnails = 16x16,220x124
+use_firmware_retraction = 0
+use_relative_e_distances = 0
+use_volumetric_e = 0
+variable_layer_height = 1
+wipe = 0
+z_offset = 0
+
+[printer:Snapmaker A350]
+inherits = *common*
+printer_model = A350
+printer_variant = 0.4
+default_filament_profile = Generic PLA @Snapmaker
+default_print_profile = 0.20mm NORMAL @SnapmakerA350
+
+[printer:Snapmaker A250]
+inherits = *common*
+printer_model = A250
+printer_variant = 0.4
+bed_shape = 0x0,230x0,230x250,0x250
+thumbnails =
+variable_layer_height = 0
+retract_lift_below = 0
+max_print_height = 235
+start_gcode = M82 ;absolute extrusion mode\n;Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start Warming Bed\nM104 S160 ;Preheat Nozzle\nG28 ; home all axes\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000\nG1 Z0 F1800\nG1 Z5 F5000 ; lift nozzle\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0\nG1 E10 F200\nG1 E-2 F300\nG92 E0\n;Start GCode end\nG1 F3600 E-2
+end_gcode = M140 S0\n;End GCode begin\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG90 ;absolute positioning\nG92 E0\nG1 E-2 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z330 E-1 F80 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y250 F3000 ;so the head is out of the way and Plate is moved forward\nM84 ;steppers off\n;End GCode end\nM82 ;absolute extrusion mode\nM104 S0\nM107\n;End of Gcode
+default_filament_profile = Generic PLA @Snapmaker
+default_print_profile = 0.20mm NORMAL @SnapmakerA250
diff --git a/resources/profiles/Snapmaker/A250_bed.stl b/resources/profiles/Snapmaker/A250_bed.stl
new file mode 100644
index 0000000000..c783af9ac1
Binary files /dev/null and b/resources/profiles/Snapmaker/A250_bed.stl differ
diff --git a/resources/profiles/Snapmaker/A250_texture.svg b/resources/profiles/Snapmaker/A250_texture.svg
new file mode 100644
index 0000000000..7f20598c35
--- /dev/null
+++ b/resources/profiles/Snapmaker/A250_texture.svg
@@ -0,0 +1,279 @@
+
+
diff --git a/resources/profiles/Snapmaker/A250_thumbnail.png b/resources/profiles/Snapmaker/A250_thumbnail.png
new file mode 100644
index 0000000000..ffc7619e68
Binary files /dev/null and b/resources/profiles/Snapmaker/A250_thumbnail.png differ
diff --git a/resources/profiles/Snapmaker/A350_bed.stl b/resources/profiles/Snapmaker/A350_bed.stl
new file mode 100644
index 0000000000..ee418a68d4
Binary files /dev/null and b/resources/profiles/Snapmaker/A350_bed.stl differ
diff --git a/resources/profiles/Snapmaker/A350_texture.svg b/resources/profiles/Snapmaker/A350_texture.svg
new file mode 100644
index 0000000000..8e8c47b655
--- /dev/null
+++ b/resources/profiles/Snapmaker/A350_texture.svg
@@ -0,0 +1,383 @@
+
+
diff --git a/resources/profiles/Snapmaker/A350_thumbnail.png b/resources/profiles/Snapmaker/A350_thumbnail.png
new file mode 100644
index 0000000000..598039a83e
Binary files /dev/null and b/resources/profiles/Snapmaker/A350_thumbnail.png differ
diff --git a/resources/profiles/Ultimaker.idx b/resources/profiles/Ultimaker.idx
index a593d2fb4b..605b87e071 100644
--- a/resources/profiles/Ultimaker.idx
+++ b/resources/profiles/Ultimaker.idx
@@ -1,2 +1,4 @@
min_slic3r_version = 2.4.0-beta0
+1.0.2 Fixed start g-code.
+1.0.1 Updated start g-code.
1.0.0 Initial version
diff --git a/resources/profiles/Ultimaker.ini b/resources/profiles/Ultimaker.ini
index 363e0dec8a..f3e30db400 100644
--- a/resources/profiles/Ultimaker.ini
+++ b/resources/profiles/Ultimaker.ini
@@ -9,7 +9,7 @@ name = Ultimaker
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
-config_version = 1.0.0
+config_version = 1.0.2
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Ultimaker/
@@ -396,5 +396,5 @@ printer_notes = Dont remove the following keywords! These keywords are used in t
nozzle_diameter = 0.4
default_print_profile = 0.20mm NORMAL @ULTIMAKER2
default_filament_profile = Generic PLA @ULTIMAKER2
-start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Heat up bed and nozzle\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\nG92 E0 ; zero the extruded length\nG1 F150 E22 ; purge nozzle with filament\nG92 E0 ; zero the extruded length again\nG1 F75 E7 ; additional priming\nG92 E0 ; zero the extruded length again\n\n; # # # # # # END Header
+start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nM140 S[first_layer_bed_temperature] ; start bed heating\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Wait for bed and nozzle temperatures\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\n; Purge and prime\nM83 ; set extruder to relative mode\nG92 E0 ; reset extrusion distance\nG0 X0 Y1 F10000\nG1 F150 E20 ; compress the bowden tube\nG1 E-8 F1200\nG0 X30 Y1 F5000 \nG0 F1200 Z{first_layer_height/2} ; Cut the connection to priming blob\nG0 X100 F10000 ; disconnect with the prime blob\nG0 X50 ; Avoid the metal clip holding the Ultimaker glass plate\nG0 Z0.2 F720\nG1 E8 F1200\nG1 X80 E3 F1000 ; intro line 1\nG1 X110 E4 F1000 ; intro line 2\nG1 X140 F600 ; drag filament to decompress bowden tube\nG1 X100 F3200 ; wipe backwards a bit\nG1 X150 F3200 ; back to where there is no plastic: avoid dragging\nG92 E0 ; reset extruder reference\nM82 ; set extruder to absolute mode\n\n; # # # # # # END Header
end_gcode = ; # # # # # # START Footer\nG91 ; relative coordinates\n;G1 E-1 F1200 ; retract the filament\nG1 Z+15 X-10 Y-10 E-7 F6000 ; move Z a bit\n; G1 X-10 Y-10 F6000 ; move XY a bit\nG1 E-5.5 F300 ; retract the filament\nG28 X0 Y0 ; move X/Y to min endstops, so the head is out of the way\nM104 S0 ; extruder heater off\nM140 S0 ; heated bed heater off (if you have it)\nM84 ; disable motors\n; # # # # # # END Footer\n
diff --git a/resources/shaders/110/background.fs b/resources/shaders/110/background.fs
new file mode 100644
index 0000000000..b148440898
--- /dev/null
+++ b/resources/shaders/110/background.fs
@@ -0,0 +1,11 @@
+#version 110
+
+uniform vec4 top_color;
+uniform vec4 bottom_color;
+
+varying vec2 tex_coord;
+
+void main()
+{
+ gl_FragColor = mix(bottom_color, top_color, tex_coord.y);
+}
diff --git a/resources/shaders/background_attr.vs b/resources/shaders/110/background.vs
similarity index 100%
rename from resources/shaders/background_attr.vs
rename to resources/shaders/110/background.vs
diff --git a/resources/shaders/110/flat.fs b/resources/shaders/110/flat.fs
new file mode 100644
index 0000000000..ab656998df
--- /dev/null
+++ b/resources/shaders/110/flat.fs
@@ -0,0 +1,8 @@
+#version 110
+
+uniform vec4 uniform_color;
+
+void main()
+{
+ gl_FragColor = uniform_color;
+}
diff --git a/resources/shaders/flat_attr.vs b/resources/shaders/110/flat.vs
similarity index 100%
rename from resources/shaders/flat_attr.vs
rename to resources/shaders/110/flat.vs
index 370eedb72d..d9063f0c70 100644
--- a/resources/shaders/flat_attr.vs
+++ b/resources/shaders/110/flat.vs
@@ -1,10 +1,10 @@
#version 110
-attribute vec3 v_position;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
+attribute vec3 v_position;
+
void main()
{
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
diff --git a/resources/shaders/110/flat_texture.fs b/resources/shaders/110/flat_texture.fs
new file mode 100644
index 0000000000..ffe193b1c0
--- /dev/null
+++ b/resources/shaders/110/flat_texture.fs
@@ -0,0 +1,10 @@
+#version 110
+
+uniform sampler2D uniform_texture;
+
+varying vec2 tex_coord;
+
+void main()
+{
+ gl_FragColor = texture2D(uniform_texture, tex_coord);
+}
diff --git a/resources/shaders/flat_texture_attr.vs b/resources/shaders/110/flat_texture.vs
similarity index 100%
rename from resources/shaders/flat_texture_attr.vs
rename to resources/shaders/110/flat_texture.vs
index e59a99da35..dc4868b04d 100644
--- a/resources/shaders/flat_texture_attr.vs
+++ b/resources/shaders/110/flat_texture.vs
@@ -1,11 +1,11 @@
#version 110
-attribute vec3 v_position;
-attribute vec2 v_tex_coord;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
+attribute vec3 v_position;
+attribute vec2 v_tex_coord;
+
varying vec2 tex_coord;
void main()
diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs
new file mode 100644
index 0000000000..0742f6cc88
--- /dev/null
+++ b/resources/shaders/110/gouraud.fs
@@ -0,0 +1,86 @@
+#version 110
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+struct PrintVolumeDetection
+{
+ // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid
+ int type;
+ // type = 0 (rectangle):
+ // x = min.x, y = min.y, z = max.x, w = max.y
+ // type = 1 (circle):
+ // x = center.x, y = center.y, z = radius
+ vec4 xy_data;
+ // x = min z, y = max z
+ vec2 z_data;
+};
+
+struct SlopeDetection
+{
+ bool actived;
+ float normal_z;
+ mat3 volume_world_normal_matrix;
+};
+
+uniform vec4 uniform_color;
+uniform SlopeDetection slope;
+
+uniform bool offset_depth_buffer;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+ uniform sampler2D environment_tex;
+ uniform bool use_environment_tex;
+#endif // ENABLE_ENVIRONMENT_MAP
+
+uniform PrintVolumeDetection print_volume;
+
+varying vec3 clipping_planes_dots;
+
+// x = diffuse, y = specular;
+varying vec2 intensity;
+
+varying vec4 world_pos;
+varying float world_normal_z;
+varying vec3 eye_normal;
+
+void main()
+{
+ if (any(lessThan(clipping_planes_dots, ZERO)))
+ discard;
+ vec3 color = uniform_color.rgb;
+ float alpha = uniform_color.a;
+
+ if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
+ color = vec3(0.7, 0.7, 1.0);
+ alpha = 1.0;
+ }
+
+ // if the fragment is outside the print volume -> use darker color
+ vec3 pv_check_min = ZERO;
+ vec3 pv_check_max = ZERO;
+ if (print_volume.type == 0) {
+ // rectangle
+ pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x);
+ pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y);
+ }
+ else if (print_volume.type == 1) {
+ // circle
+ float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy);
+ pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
+ pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
+ }
+ color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+ if (use_environment_tex)
+ gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
+ else
+#endif
+ gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
+
+ // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already
+ // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values
+ // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos.
+ gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0);
+}
diff --git a/resources/shaders/gouraud_attr.vs b/resources/shaders/110/gouraud.vs
similarity index 100%
rename from resources/shaders/gouraud_attr.vs
rename to resources/shaders/110/gouraud.vs
index 87e524c14a..70f71f886b 100644
--- a/resources/shaders/gouraud_attr.vs
+++ b/resources/shaders/110/gouraud.vs
@@ -25,9 +25,6 @@ struct SlopeDetection
mat3 volume_world_normal_matrix;
};
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
@@ -39,6 +36,9 @@ uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
// x = diffuse, y = specular;
varying vec2 intensity;
diff --git a/resources/shaders/110/gouraud_light.fs b/resources/shaders/110/gouraud_light.fs
new file mode 100644
index 0000000000..970185a00e
--- /dev/null
+++ b/resources/shaders/110/gouraud_light.fs
@@ -0,0 +1,12 @@
+#version 110
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+void main()
+{
+ gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/gouraud_light_attr.vs b/resources/shaders/110/gouraud_light.vs
similarity index 100%
rename from resources/shaders/gouraud_light_attr.vs
rename to resources/shaders/110/gouraud_light.vs
index 2e1b5fb429..a03653b8a3 100644
--- a/resources/shaders/gouraud_light_attr.vs
+++ b/resources/shaders/110/gouraud_light.vs
@@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define INTENSITY_AMBIENT 0.3
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
// x = tainted, y = specular;
varying vec2 intensity;
diff --git a/resources/shaders/110/gouraud_light_instanced.fs b/resources/shaders/110/gouraud_light_instanced.fs
new file mode 100644
index 0000000000..970185a00e
--- /dev/null
+++ b/resources/shaders/110/gouraud_light_instanced.fs
@@ -0,0 +1,12 @@
+#version 110
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+void main()
+{
+ gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/gouraud_light_instanced_attr.vs b/resources/shaders/110/gouraud_light_instanced.vs
similarity index 100%
rename from resources/shaders/gouraud_light_instanced_attr.vs
rename to resources/shaders/110/gouraud_light_instanced.vs
index 7069feb65e..87748ce6f0 100644
--- a/resources/shaders/gouraud_light_instanced_attr.vs
+++ b/resources/shaders/110/gouraud_light_instanced.vs
@@ -14,6 +14,10 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define INTENSITY_AMBIENT 0.3
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
// vertex attributes
attribute vec3 v_position;
attribute vec3 v_normal;
@@ -21,10 +25,6 @@ attribute vec3 v_normal;
attribute vec3 i_offset;
attribute vec2 i_scales;
-uniform mat4 view_model_matrix;
-uniform mat4 projection_matrix;
-uniform mat3 normal_matrix;
-
// x = tainted, y = specular;
varying vec2 intensity;
diff --git a/resources/shaders/imgui.fs b/resources/shaders/110/imgui.fs
similarity index 100%
rename from resources/shaders/imgui.fs
rename to resources/shaders/110/imgui.fs
diff --git a/resources/shaders/imgui.vs b/resources/shaders/110/imgui.vs
similarity index 100%
rename from resources/shaders/imgui.vs
rename to resources/shaders/110/imgui.vs
diff --git a/resources/shaders/mm_contour_attr.fs b/resources/shaders/110/mm_contour.fs
similarity index 100%
rename from resources/shaders/mm_contour_attr.fs
rename to resources/shaders/110/mm_contour.fs
diff --git a/resources/shaders/mm_contour_attr.vs b/resources/shaders/110/mm_contour.vs
similarity index 100%
rename from resources/shaders/mm_contour_attr.vs
rename to resources/shaders/110/mm_contour.vs
index 370eedb72d..d9063f0c70 100644
--- a/resources/shaders/mm_contour_attr.vs
+++ b/resources/shaders/110/mm_contour.vs
@@ -1,10 +1,10 @@
#version 110
-attribute vec3 v_position;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
+attribute vec3 v_position;
+
void main()
{
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
diff --git a/resources/shaders/mm_gouraud_attr.fs b/resources/shaders/110/mm_gouraud.fs
similarity index 100%
rename from resources/shaders/mm_gouraud_attr.fs
rename to resources/shaders/110/mm_gouraud.fs
diff --git a/resources/shaders/mm_gouraud_attr.vs b/resources/shaders/110/mm_gouraud.vs
similarity index 100%
rename from resources/shaders/mm_gouraud_attr.vs
rename to resources/shaders/110/mm_gouraud.vs
index 76101b7670..10c25239f9 100644
--- a/resources/shaders/mm_gouraud_attr.vs
+++ b/resources/shaders/110/mm_gouraud.vs
@@ -2,8 +2,6 @@
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
-attribute vec3 v_position;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
@@ -13,6 +11,8 @@ uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;
+attribute vec3 v_position;
+
varying vec3 clipping_planes_dots;
varying vec4 model_pos;
diff --git a/resources/shaders/110/printbed.fs b/resources/shaders/110/printbed.fs
new file mode 100644
index 0000000000..833dff08f4
--- /dev/null
+++ b/resources/shaders/110/printbed.fs
@@ -0,0 +1,34 @@
+#version 110
+
+const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
+const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
+
+uniform sampler2D texture;
+uniform bool transparent_background;
+uniform bool svg_source;
+
+varying vec2 tex_coord;
+
+vec4 svg_color()
+{
+ // takes foreground from texture
+ vec4 fore_color = texture2D(texture, tex_coord);
+
+ // calculates radial gradient
+ vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
+
+ // blends foreground with background
+ return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0);
+}
+
+vec4 non_svg_color()
+{
+ // takes foreground from texture
+ vec4 color = texture2D(texture, tex_coord);
+ return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
+}
+
+void main()
+{
+ gl_FragColor = svg_source ? svg_color() : non_svg_color();
+}
\ No newline at end of file
diff --git a/resources/shaders/printbed_attr.vs b/resources/shaders/110/printbed.vs
similarity index 100%
rename from resources/shaders/printbed_attr.vs
rename to resources/shaders/110/printbed.vs
index e59a99da35..dc4868b04d 100644
--- a/resources/shaders/printbed_attr.vs
+++ b/resources/shaders/110/printbed.vs
@@ -1,11 +1,11 @@
#version 110
-attribute vec3 v_position;
-attribute vec2 v_tex_coord;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
+attribute vec3 v_position;
+attribute vec2 v_tex_coord;
+
varying vec2 tex_coord;
void main()
diff --git a/resources/shaders/110/toolpaths_cog.fs b/resources/shaders/110/toolpaths_cog.fs
new file mode 100644
index 0000000000..668fe03ecf
--- /dev/null
+++ b/resources/shaders/110/toolpaths_cog.fs
@@ -0,0 +1,19 @@
+#version 110
+
+const vec4 BLACK = vec4(vec3(0.1), 1.0);
+const vec4 WHITE = vec4(vec3(1.0), 1.0);
+
+const float emission_factor = 0.25;
+
+uniform vec3 world_center;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+varying vec3 world_position;
+
+void main()
+{
+ vec3 delta = world_position - world_center;
+ vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;
+ gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0);
+}
diff --git a/resources/shaders/toolpaths_cog_attr.vs b/resources/shaders/110/toolpaths_cog.vs
similarity index 100%
rename from resources/shaders/toolpaths_cog_attr.vs
rename to resources/shaders/110/toolpaths_cog.vs
index 5951238b71..38d2f79444 100644
--- a/resources/shaders/toolpaths_cog_attr.vs
+++ b/resources/shaders/110/toolpaths_cog.vs
@@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define INTENSITY_AMBIENT 0.3
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
// x = tainted, y = specular;
varying vec2 intensity;
varying vec3 world_position;
diff --git a/resources/shaders/110/variable_layer_height.fs b/resources/shaders/110/variable_layer_height.fs
new file mode 100644
index 0000000000..693c1c6a0b
--- /dev/null
+++ b/resources/shaders/110/variable_layer_height.fs
@@ -0,0 +1,41 @@
+#version 110
+
+#define M_PI 3.1415926535897932384626433832795
+
+// 2D texture (1D texture split by the rows) of color along the object Z axis.
+uniform sampler2D z_texture;
+// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
+uniform float z_to_texture_row;
+uniform float z_texture_row_to_normalized;
+uniform float z_cursor;
+uniform float z_cursor_band_width;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+varying float object_z;
+
+void main()
+{
+ float object_z_row = z_to_texture_row * object_z;
+ // Index of the row in the texture.
+ float z_texture_row = floor(object_z_row);
+ // Normalized coordinate from 0. to 1.
+ float z_texture_col = object_z_row - z_texture_row;
+ float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25;
+ // Calculate level of detail from the object Z coordinate.
+ // This makes the slowly sloping surfaces to be shown with high detail (with stripes),
+ // and the vertical surfaces to be shown with low detail (no stripes)
+ float z_in_cells = object_z_row * 190.;
+ // Gradient of Z projected on the screen.
+ float dx_vtc = dFdx(z_in_cells);
+ float dy_vtc = dFdy(z_in_cells);
+ float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.);
+ // Sample the Z texture. Texture coordinates are normalized to <0, 1>.
+ vec4 color = vec4(0.25, 0.25, 0.25, 1.0);
+ if (z_texture_row >= 0.0)
+ color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.),
+ texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod);
+ // Mix the final color.
+ gl_FragColor = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
+}
diff --git a/resources/shaders/variable_layer_height_attr.vs b/resources/shaders/110/variable_layer_height.vs
similarity index 100%
rename from resources/shaders/variable_layer_height_attr.vs
rename to resources/shaders/110/variable_layer_height.vs
index 40609bd0d9..e6c88fa809 100644
--- a/resources/shaders/variable_layer_height_attr.vs
+++ b/resources/shaders/110/variable_layer_height.vs
@@ -14,16 +14,16 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
#define INTENSITY_AMBIENT 0.3
-attribute vec3 v_position;
-attribute vec3 v_normal;
-attribute vec2 v_tex_coord;
-
uniform mat4 view_model_matrix;
uniform mat4 projection_matrix;
uniform mat3 normal_matrix;
uniform mat4 volume_world_matrix;
uniform float object_max_z;
+attribute vec3 v_position;
+attribute vec3 v_normal;
+attribute vec2 v_tex_coord;
+
// x = tainted, y = specular;
varying vec2 intensity;
diff --git a/resources/shaders/140/background.fs b/resources/shaders/140/background.fs
new file mode 100644
index 0000000000..c21f3a70cd
--- /dev/null
+++ b/resources/shaders/140/background.fs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform vec4 top_color;
+uniform vec4 bottom_color;
+
+in vec2 tex_coord;
+
+void main()
+{
+ gl_FragColor = mix(bottom_color, top_color, tex_coord.y);
+}
diff --git a/resources/shaders/140/background.vs b/resources/shaders/140/background.vs
new file mode 100644
index 0000000000..13609b3a21
--- /dev/null
+++ b/resources/shaders/140/background.vs
@@ -0,0 +1,12 @@
+#version 140
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+ tex_coord = v_tex_coord;
+ gl_Position = vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/flat.fs b/resources/shaders/140/flat.fs
new file mode 100644
index 0000000000..e74124dcae
--- /dev/null
+++ b/resources/shaders/140/flat.fs
@@ -0,0 +1,8 @@
+#version 140
+
+uniform vec4 uniform_color;
+
+void main()
+{
+ gl_FragColor = uniform_color;
+}
diff --git a/resources/shaders/140/flat.vs b/resources/shaders/140/flat.vs
new file mode 100644
index 0000000000..7042671de2
--- /dev/null
+++ b/resources/shaders/140/flat.vs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+
+void main()
+{
+ gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs
new file mode 100644
index 0000000000..dec946721e
--- /dev/null
+++ b/resources/shaders/140/flat_texture.fs
@@ -0,0 +1,10 @@
+#version 140
+
+uniform sampler2D uniform_texture;
+
+in vec2 tex_coord;
+
+void main()
+{
+ gl_FragColor = texture(uniform_texture, tex_coord);
+}
diff --git a/resources/shaders/140/flat_texture.vs b/resources/shaders/140/flat_texture.vs
new file mode 100644
index 0000000000..57d8ca3b7c
--- /dev/null
+++ b/resources/shaders/140/flat_texture.vs
@@ -0,0 +1,15 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+ tex_coord = v_tex_coord;
+ gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs
new file mode 100644
index 0000000000..beb3a947bb
--- /dev/null
+++ b/resources/shaders/140/gouraud.fs
@@ -0,0 +1,86 @@
+#version 140
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+struct PrintVolumeDetection
+{
+ // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid
+ int type;
+ // type = 0 (rectangle):
+ // x = min.x, y = min.y, z = max.x, w = max.y
+ // type = 1 (circle):
+ // x = center.x, y = center.y, z = radius
+ vec4 xy_data;
+ // x = min z, y = max z
+ vec2 z_data;
+};
+
+struct SlopeDetection
+{
+ bool actived;
+ float normal_z;
+ mat3 volume_world_normal_matrix;
+};
+
+uniform vec4 uniform_color;
+uniform SlopeDetection slope;
+
+uniform bool offset_depth_buffer;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+ uniform sampler2D environment_tex;
+ uniform bool use_environment_tex;
+#endif // ENABLE_ENVIRONMENT_MAP
+
+uniform PrintVolumeDetection print_volume;
+
+in vec3 clipping_planes_dots;
+
+// x = diffuse, y = specular;
+in vec2 intensity;
+
+in vec4 world_pos;
+in float world_normal_z;
+in vec3 eye_normal;
+
+void main()
+{
+ if (any(lessThan(clipping_planes_dots, ZERO)))
+ discard;
+ vec3 color = uniform_color.rgb;
+ float alpha = uniform_color.a;
+
+ if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
+ color = vec3(0.7, 0.7, 1.0);
+ alpha = 1.0;
+ }
+
+ // if the fragment is outside the print volume -> use darker color
+ vec3 pv_check_min = ZERO;
+ vec3 pv_check_max = ZERO;
+ if (print_volume.type == 0) {
+ // rectangle
+ pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x);
+ pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y);
+ }
+ else if (print_volume.type == 1) {
+ // circle
+ float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy);
+ pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
+ pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
+ }
+ color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+ if (use_environment_tex)
+ gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
+ else
+#endif
+ gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
+
+ // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already
+ // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values
+ // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos.
+ gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0);
+}
diff --git a/resources/shaders/140/gouraud.vs b/resources/shaders/140/gouraud.vs
new file mode 100644
index 0000000000..aaf251c42d
--- /dev/null
+++ b/resources/shaders/140/gouraud.vs
@@ -0,0 +1,77 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SHININESS 5.0
+
+#define INTENSITY_AMBIENT 0.3
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+
+struct SlopeDetection
+{
+ bool actived;
+ float normal_z;
+ mat3 volume_world_normal_matrix;
+};
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+uniform mat4 volume_world_matrix;
+uniform SlopeDetection slope;
+
+// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
+uniform vec2 z_range;
+// Clipping plane - general orientation. Used by the SLA gizmo.
+uniform vec4 clipping_plane;
+
+in vec3 v_position;
+in vec3 v_normal;
+
+// x = diffuse, y = specular;
+out vec2 intensity;
+
+out vec3 clipping_planes_dots;
+
+out vec4 world_pos;
+out float world_normal_z;
+out vec3 eye_normal;
+
+void main()
+{
+ // First transform the normal into camera space and normalize the result.
+ eye_normal = normalize(normal_matrix * v_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec4 position = view_model_matrix * vec4(v_position, 1.0);
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular applied).
+ NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ // Point in homogenous coordinates.
+ world_pos = volume_world_matrix * vec4(v_position, 1.0);
+
+ // z component of normal vector in world coordinate used for slope shading
+ world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
+
+ gl_Position = projection_matrix * position;
+ // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
+ clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
+}
diff --git a/resources/shaders/140/gouraud_light.fs b/resources/shaders/140/gouraud_light.fs
new file mode 100644
index 0000000000..de616e066a
--- /dev/null
+++ b/resources/shaders/140/gouraud_light.fs
@@ -0,0 +1,12 @@
+#version 140
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+void main()
+{
+ gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/140/gouraud_light.vs b/resources/shaders/140/gouraud_light.vs
new file mode 100644
index 0000000000..b75a844058
--- /dev/null
+++ b/resources/shaders/140/gouraud_light.vs
@@ -0,0 +1,45 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT 0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 v_position;
+in vec3 v_normal;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+void main()
+{
+ // First transform the normal into camera space and normalize the result.
+ vec3 normal = normalize(normal_matrix * v_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec4 position = view_model_matrix * vec4(v_position, 1.0);
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular applied).
+ NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ gl_Position = projection_matrix * position;
+}
diff --git a/resources/shaders/140/gouraud_light_instanced.fs b/resources/shaders/140/gouraud_light_instanced.fs
new file mode 100644
index 0000000000..de616e066a
--- /dev/null
+++ b/resources/shaders/140/gouraud_light_instanced.fs
@@ -0,0 +1,12 @@
+#version 140
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+void main()
+{
+ gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/140/gouraud_light_instanced.vs b/resources/shaders/140/gouraud_light_instanced.vs
new file mode 100644
index 0000000000..b6b9ab8be7
--- /dev/null
+++ b/resources/shaders/140/gouraud_light_instanced.vs
@@ -0,0 +1,50 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT 0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+// vertex attributes
+in vec3 v_position;
+in vec3 v_normal;
+// instance attributes
+in vec3 i_offset;
+in vec2 i_scales;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+void main()
+{
+ // First transform the normal into camera space and normalize the result.
+ vec3 eye_normal = normalize(normal_matrix * v_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
+ vec4 eye_position = view_model_matrix * world_position;
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular applied).
+ NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ gl_Position = projection_matrix * eye_position;
+}
diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs
new file mode 100644
index 0000000000..4b2571749f
--- /dev/null
+++ b/resources/shaders/140/imgui.fs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform sampler2D Texture;
+
+in vec2 Frag_UV;
+in vec4 Frag_Color;
+
+void main()
+{
+ gl_FragColor = Frag_Color * texture(Texture, Frag_UV.st);
+}
\ No newline at end of file
diff --git a/resources/shaders/140/imgui.vs b/resources/shaders/140/imgui.vs
new file mode 100644
index 0000000000..fd743bdf2d
--- /dev/null
+++ b/resources/shaders/140/imgui.vs
@@ -0,0 +1,17 @@
+#version 140
+
+uniform mat4 ProjMtx;
+
+in vec2 Position;
+in vec2 UV;
+in vec4 Color;
+
+out vec2 Frag_UV;
+out vec4 Frag_Color;
+
+void main()
+{
+ Frag_UV = UV;
+ Frag_Color = Color;
+ gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/resources/shaders/140/mm_contour.fs b/resources/shaders/140/mm_contour.fs
new file mode 100644
index 0000000000..3681d76c18
--- /dev/null
+++ b/resources/shaders/140/mm_contour.fs
@@ -0,0 +1,13 @@
+#version 140
+
+const float EPSILON = 0.0001;
+
+uniform vec4 uniform_color;
+
+void main()
+{
+ gl_FragColor = uniform_color;
+ // Values inside depth buffer for fragments of the contour of a selected area are offset
+ // by small epsilon to solve z-fighting between painted triangles and contour lines.
+ gl_FragDepth = gl_FragCoord.z - EPSILON;
+}
diff --git a/resources/shaders/140/mm_contour.vs b/resources/shaders/140/mm_contour.vs
new file mode 100644
index 0000000000..7042671de2
--- /dev/null
+++ b/resources/shaders/140/mm_contour.vs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+
+void main()
+{
+ gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/mm_gouraud.fs b/resources/shaders/140/mm_gouraud.fs
new file mode 100644
index 0000000000..e59d844f26
--- /dev/null
+++ b/resources/shaders/140/mm_gouraud.fs
@@ -0,0 +1,63 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT 0.3
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+uniform vec4 uniform_color;
+
+uniform bool volume_mirrored;
+
+uniform mat4 view_model_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 clipping_planes_dots;
+in vec4 model_pos;
+
+void main()
+{
+ if (any(lessThan(clipping_planes_dots, ZERO)))
+ discard;
+ vec3 color = uniform_color.rgb;
+ float alpha = uniform_color.a;
+
+ vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz)));
+#ifdef FLIP_TRIANGLE_NORMALS
+ triangle_normal = -triangle_normal;
+#endif
+
+ if (volume_mirrored)
+ triangle_normal = -triangle_normal;
+
+ // First transform the normal into camera space and normalize the result.
+ vec3 eye_normal = normalize(normal_matrix * triangle_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+ // x = diffuse, y = specular;
+ vec2 intensity = vec2(0.0);
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec3 position = (view_model_matrix * model_pos).xyz;
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular applied).
+ NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
+}
diff --git a/resources/shaders/140/mm_gouraud.vs b/resources/shaders/140/mm_gouraud.vs
new file mode 100644
index 0000000000..30223f4eec
--- /dev/null
+++ b/resources/shaders/140/mm_gouraud.vs
@@ -0,0 +1,28 @@
+#version 140
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+uniform mat4 volume_world_matrix;
+// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
+uniform vec2 z_range;
+// Clipping plane - general orientation. Used by the SLA gizmo.
+uniform vec4 clipping_plane;
+
+in vec3 v_position;
+
+out vec3 clipping_planes_dots;
+out vec4 model_pos;
+
+void main()
+{
+ model_pos = vec4(v_position, 1.0);
+ // Point in homogenous coordinates.
+ vec4 world_pos = volume_world_matrix * model_pos;
+
+ gl_Position = projection_matrix * view_model_matrix * model_pos;
+ // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
+ clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
+}
diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs
new file mode 100644
index 0000000000..6d927a749c
--- /dev/null
+++ b/resources/shaders/140/printbed.fs
@@ -0,0 +1,35 @@
+#version 140
+
+const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
+const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
+
+uniform sampler2D in_texture;
+uniform bool transparent_background;
+uniform bool svg_source;
+
+in vec2 tex_coord;
+out vec4 frag_color;
+
+vec4 svg_color()
+{
+ // takes foreground from texture
+ vec4 fore_color = texture(in_texture, tex_coord);
+
+ // calculates radial gradient
+ vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
+
+ // blends foreground with background
+ return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0);
+}
+
+vec4 non_svg_color()
+{
+ // takes foreground from texture
+ vec4 color = texture(in_texture, tex_coord);
+ return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
+}
+
+void main()
+{
+ frag_color = svg_source ? svg_color() : non_svg_color();
+}
\ No newline at end of file
diff --git a/resources/shaders/140/printbed.vs b/resources/shaders/140/printbed.vs
new file mode 100644
index 0000000000..57d8ca3b7c
--- /dev/null
+++ b/resources/shaders/140/printbed.vs
@@ -0,0 +1,15 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+ tex_coord = v_tex_coord;
+ gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/toolpaths_cog.fs b/resources/shaders/140/toolpaths_cog.fs
new file mode 100644
index 0000000000..1c745dda99
--- /dev/null
+++ b/resources/shaders/140/toolpaths_cog.fs
@@ -0,0 +1,19 @@
+#version 140
+
+const vec4 BLACK = vec4(vec3(0.1), 1.0);
+const vec4 WHITE = vec4(vec3(1.0), 1.0);
+
+const float emission_factor = 0.25;
+
+uniform vec3 world_center;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+in vec3 world_position;
+
+void main()
+{
+ vec3 delta = world_position - world_center;
+ vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;
+ gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0);
+}
diff --git a/resources/shaders/140/toolpaths_cog.vs b/resources/shaders/140/toolpaths_cog.vs
new file mode 100644
index 0000000000..ef676a3751
--- /dev/null
+++ b/resources/shaders/140/toolpaths_cog.vs
@@ -0,0 +1,47 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT 0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 v_position;
+in vec3 v_normal;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+out vec3 world_position;
+
+void main()
+{
+ // First transform the normal into camera space and normalize the result.
+ vec3 normal = normalize(normal_matrix * v_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec4 position = view_model_matrix * vec4(v_position, 1.0);
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular applied).
+ NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ world_position = v_position;
+ gl_Position = projection_matrix * position;
+}
diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs
new file mode 100644
index 0000000000..cf1fc309cc
--- /dev/null
+++ b/resources/shaders/140/variable_layer_height.fs
@@ -0,0 +1,41 @@
+#version 140
+
+#define M_PI 3.1415926535897932384626433832795
+
+// 2D texture (1D texture split by the rows) of color along the object Z axis.
+uniform sampler2D z_texture;
+// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
+uniform float z_to_texture_row;
+uniform float z_texture_row_to_normalized;
+uniform float z_cursor;
+uniform float z_cursor_band_width;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+in float object_z;
+
+void main()
+{
+ float object_z_row = z_to_texture_row * object_z;
+ // Index of the row in the texture.
+ float z_texture_row = floor(object_z_row);
+ // Normalized coordinate from 0. to 1.
+ float z_texture_col = object_z_row - z_texture_row;
+ float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25;
+ // Calculate level of detail from the object Z coordinate.
+ // This makes the slowly sloping surfaces to be shown with high detail (with stripes),
+ // and the vertical surfaces to be shown with low detail (no stripes)
+ float z_in_cells = object_z_row * 190.;
+ // Gradient of Z projected on the screen.
+ float dx_vtc = dFdx(z_in_cells);
+ float dy_vtc = dFdy(z_in_cells);
+ float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.);
+ // Sample the Z texture. Texture coordinates are normalized to <0, 1>.
+ vec4 color = vec4(0.25, 0.25, 0.25, 1.0);
+ if (z_texture_row >= 0.0)
+ color = mix(texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.),
+ texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod);
+ // Mix the final color.
+ gl_FragColor = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
+}
diff --git a/resources/shaders/140/variable_layer_height.vs b/resources/shaders/140/variable_layer_height.vs
new file mode 100644
index 0000000000..dd463b9c7a
--- /dev/null
+++ b/resources/shaders/140/variable_layer_height.vs
@@ -0,0 +1,60 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS 20.0
+
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SHININESS 5.0
+
+#define INTENSITY_AMBIENT 0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+uniform mat4 volume_world_matrix;
+uniform float object_max_z;
+
+in vec3 v_position;
+in vec3 v_normal;
+in vec2 v_tex_coord;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+out float object_z;
+
+void main()
+{
+ // =====================================================
+ // NOTE:
+ // when object_max_z > 0.0 we are rendering the overlay
+ // when object_max_z == 0.0 we are rendering the volumes
+ // =====================================================
+
+ // First transform the normal into camera space and normalize the result.
+ vec3 normal = (object_max_z > 0.0) ? vec3(0.0, 0.0, 1.0) : normalize(normal_matrix * v_normal);
+
+ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+ // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+ float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+ intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+ vec4 position = view_model_matrix * vec4(v_position, 1.0);
+ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+ // Perform the same lighting calculation for the 2nd light source (no specular)
+ NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+
+ intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+ // Scaled to widths of the Z texture.
+ object_z = (object_max_z > 0.0) ? object_max_z * v_tex_coord.y : (volume_world_matrix * vec4(v_position, 1.0)).z;
+
+ gl_Position = projection_matrix * position;
+}
diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp
index a3e4aee311..e6b8201885 100644
--- a/src/libslic3r/Fill/Fill.cpp
+++ b/src/libslic3r/Fill/Fill.cpp
@@ -11,6 +11,7 @@
#include "FillBase.hpp"
#include "FillRectilinear.hpp"
+#include "FillLightning.hpp"
namespace Slic3r {
@@ -318,7 +319,7 @@ void export_group_fills_to_svg(const char *path, const std::vector
#endif
// friend to Layer
-void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree)
+void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator)
{
for (LayerRegion *layerm : m_regions)
layerm->fills.clear();
@@ -348,6 +349,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
f->angle = surface_fill.params.angle;
f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree;
+ if (surface_fill.params.pattern == ipLightning)
+ dynamic_cast(f.get())->generator = lightning_generator;
+
// calculate flow spacing for infill pattern generation
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
double link_max_length = 0.;
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 7ca0699c0f..c4f8d6f08f 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -46,9 +46,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipAdaptiveCubic: return new FillAdaptive::Filler();
case ipSupportCubic: return new FillAdaptive::Filler();
case ipSupportBase: return new FillSupportBase();
-#if HAS_LIGHTNING_INFILL
case ipLightning: return new FillLightning::Filler();
-#endif // HAS_LIGHTNING_INFILL
default: throw Slic3r::InvalidArgument("unknown type");
}
}
diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp
index 7d868860a7..264ae8a599 100644
--- a/src/libslic3r/Fill/FillRectilinear.cpp
+++ b/src/libslic3r/Fill/FillRectilinear.cpp
@@ -406,13 +406,15 @@ public:
// for the infill pattern, don't cut the corners.
// default miterLimt = 3
//double miterLimit = 10.;
- assert(aoffset1 < 0);
+ // FIXME: Resolve properly the cases when it is constructed with aoffset1 = 0 and aoffset2 = 0,
+ // that is used in sample_grid_pattern() for Lightning infill.
+ // assert(aoffset1 < 0);
assert(aoffset2 <= 0);
- assert(aoffset2 == 0 || aoffset2 < aoffset1);
+ // assert(aoffset2 == 0 || aoffset2 < aoffset1);
// bool sticks_removed =
remove_sticks(polygons_src);
// if (sticks_removed) BOOST_LOG_TRIVIAL(error) << "Sticks removed!";
- polygons_outer = offset(polygons_src, float(aoffset1), ClipperLib::jtMiter, miterLimit);
+ polygons_outer = aoffset1 == 0 ? polygons_src : offset(polygons_src, float(aoffset1), ClipperLib::jtMiter, miterLimit);
if (aoffset2 < 0)
polygons_inner = shrink(polygons_outer, float(aoffset1 - aoffset2), ClipperLib::jtMiter, miterLimit);
// Filter out contours with zero area or small area, contours with 2 points only.
diff --git a/src/libslic3r/Fill/Lightning/DistanceField.cpp b/src/libslic3r/Fill/Lightning/DistanceField.cpp
index 6df1d043ca..308ca41c60 100644
--- a/src/libslic3r/Fill/Lightning/DistanceField.cpp
+++ b/src/libslic3r/Fill/Lightning/DistanceField.cpp
@@ -10,27 +10,29 @@ namespace Slic3r::FillLightning
constexpr coord_t radius_per_cell_size = 6; // The cell-size should be small compared to the radius, but not so small as to be inefficient.
-DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const Polygons& current_overhang) :
- m_cell_size(radius / radius_per_cell_size),
- m_supporting_radius(radius)
+DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang) :
+ m_cell_size(radius / radius_per_cell_size),
+ m_supporting_radius(radius),
+ m_unsupported_points_bbox(current_outlines_bbox)
{
- m_supporting_radius2 = double(radius) * double(radius);
+ m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
// Sample source polygons with a regular grid sampling pattern.
- for (const ExPolygon &expoly : union_ex(current_outline)) {
+ for (const ExPolygon &expoly : union_ex(current_overhang)) {
for (const Point &p : sample_grid_pattern(expoly, m_cell_size)) {
// Find a squared distance to the source expolygon boundary.
double d2 = std::numeric_limits::max();
- for (size_t icontour = 0; icontour <= expoly.holes.size(); ++ icontour) {
+ for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
- d2 = std::min(d2, Line::distance_to_squared(p, prev, p2));
+ d2 = std::min(d2, Line::distance_to_squared(p, prev, p2));
prev = p2;
}
}
}
m_unsupported_points.emplace_back(p, sqrt(d2));
+ assert(m_unsupported_points_bbox.contains(p));
}
}
m_unsupported_points.sort([&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
@@ -41,8 +43,11 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
});
for (auto it = m_unsupported_points.begin(); it != m_unsupported_points.end(); ++it) {
UnsupportedCell& cell = *it;
- m_unsupported_points_grid.emplace(Point{ cell.loc.x() / m_cell_size, cell.loc.y() / m_cell_size }, it);
+ m_unsupported_points_grid.emplace(this->to_grid_point(cell.loc), it);
}
+ // Because the distance between two points is at least one axis equal to m_cell_size, every cell
+ // in m_unsupported_points_grid contains exactly one point.
+ assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
}
void DistanceField::update(const Point& to_node, const Point& added_leaf)
@@ -60,17 +65,24 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
grid.merge(to_node + iextent);
grid.merge(added_leaf - iextent);
grid.merge(added_leaf + iextent);
- grid.min /= m_cell_size;
- grid.max /= m_cell_size;
+
+ // Clip grid by m_unsupported_points_bbox. Mainly to ensure that grid.min is a non-negative value.
+ grid.min.x() = std::max(grid.min.x(), m_unsupported_points_bbox.min.x());
+ grid.min.y() = std::max(grid.min.y(), m_unsupported_points_bbox.min.y());
+ grid.max.x() = std::min(grid.max.x(), m_unsupported_points_bbox.max.x());
+ grid.max.y() = std::min(grid.max.y(), m_unsupported_points_bbox.max.y());
+
+ grid.min = this->to_grid_point(grid.min);
+ grid.max = this->to_grid_point(grid.max);
}
+ Point grid_addr;
Point grid_loc;
- for (coord_t row = grid.min.y(); row <= grid.max.y(); ++ row) {
- grid_loc.y() = row * m_cell_size;
- for (coord_t col = grid.min.x(); col <= grid.max.y(); ++ col) {
- grid_loc.x() = col * m_cell_size;
+ for (grid_addr.y() = grid.min.y(); grid_addr.y() <= grid.max.y(); ++grid_addr.y()) {
+ for (grid_addr.x() = grid.min.x(); grid_addr.x() <= grid.max.x(); ++grid_addr.x()) {
+ grid_loc = this->from_grid_point(grid_addr);
// Test inside a circle at the new leaf.
- if ((grid_loc - added_leaf).cast().squaredNorm() > m_supporting_radius2) {
+ if ((grid_loc - added_leaf).cast().squaredNorm() > m_supporting_radius2) {
// Not inside a circle at the end of the new leaf.
// Test inside a rotated rectangle.
Vec2d vx = (grid_loc - to_node).cast();
@@ -84,10 +96,10 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
}
// Inside a circle at the end of the new leaf, or inside a rotated rectangle.
// Remove unsupported leafs at this grid location.
- if (auto it = m_unsupported_points_grid.find(grid_loc); it != m_unsupported_points_grid.end()) {
+ if (auto it = m_unsupported_points_grid.find(grid_addr); it != m_unsupported_points_grid.end()) {
std::list::iterator& list_it = it->second;
UnsupportedCell& cell = *list_it;
- if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) {
+ if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) {
m_unsupported_points.erase(list_it);
m_unsupported_points_grid.erase(it);
}
@@ -96,4 +108,25 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
}
}
+#if 0
+void DistanceField::update(const Point &to_node, const Point &added_leaf)
+{
+ const Point supporting_radius_point(m_supporting_radius, m_supporting_radius);
+ const BoundingBox grid(this->to_grid_point(added_leaf - supporting_radius_point), this->to_grid_point(added_leaf + supporting_radius_point));
+
+ for (coord_t grid_y = grid.min.y(); grid_y <= grid.max.y(); ++grid_y) {
+ for (coord_t grid_x = grid.min.x(); grid_x <= grid.max.x(); ++grid_x) {
+ if (auto it = m_unsupported_points_grid.find({grid_x, grid_y}); it != m_unsupported_points_grid.end()) {
+ std::list::iterator &list_it = it->second;
+ UnsupportedCell &cell = *list_it;
+ if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) {
+ m_unsupported_points.erase(list_it);
+ m_unsupported_points_grid.erase(it);
+ }
+ }
+ }
+ }
+}
+#endif
+
} // namespace Slic3r::FillLightning
diff --git a/src/libslic3r/Fill/Lightning/DistanceField.hpp b/src/libslic3r/Fill/Lightning/DistanceField.hpp
index 7fdce434ce..beb46c5c57 100644
--- a/src/libslic3r/Fill/Lightning/DistanceField.hpp
+++ b/src/libslic3r/Fill/Lightning/DistanceField.hpp
@@ -4,6 +4,7 @@
#ifndef LIGHTNING_DISTANCE_FIELD_H
#define LIGHTNING_DISTANCE_FIELD_H
+#include "../../BoundingBox.hpp"
#include "../../Point.hpp"
#include "../../Polygon.hpp"
@@ -29,7 +30,7 @@ public:
* \param current_overhang The overhang that needs to be supported on this
* layer.
*/
- DistanceField(const coord_t& radius, const Polygons& current_outline, const Polygons& current_overhang);
+ DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang);
/*!
* Gets the next unsupported location to be supported by a new branch.
@@ -69,14 +70,14 @@ protected:
* branch of a tree.
*/
coord_t m_supporting_radius;
- double m_supporting_radius2;
+ int64_t m_supporting_radius2;
/*!
* Represents a small discrete area of infill that needs to be supported.
*/
struct UnsupportedCell
{
- UnsupportedCell(Point loc, coord_t dist_to_boundary) : loc(loc), dist_to_boundary(dist_to_boundary) {}
+ UnsupportedCell(const Point &loc, coord_t dist_to_boundary) : loc(loc), dist_to_boundary(dist_to_boundary) {}
// The position of the center of this cell.
Point loc;
// How far this cell is removed from the ``current_outline`` polygon, the edge of the infill area.
@@ -88,11 +89,30 @@ protected:
*/
std::list m_unsupported_points;
+ /*!
+ * BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers.
+ */
+ const BoundingBox m_unsupported_points_bbox;
+
/*!
* Links the unsupported points to a grid point, so that we can quickly look
* up the cell belonging to a certain position in the grid.
*/
std::unordered_map::iterator, PointHash> m_unsupported_points_grid;
+
+ /*!
+ * Maps the point to the grid coordinates.
+ */
+ Point to_grid_point(const Point &point) const {
+ return (point - m_unsupported_points_bbox.min) / m_cell_size;
+ }
+
+ /*!
+ * Maps the point to the grid coordinates.
+ */
+ Point from_grid_point(const Point &point) const {
+ return point * m_cell_size + m_unsupported_points_bbox.min;
+ }
};
} // namespace Slic3r::FillLightning
diff --git a/src/libslic3r/Fill/Lightning/Generator.cpp b/src/libslic3r/Fill/Lightning/Generator.cpp
index 87b593f89b..6a4a675cbe 100644
--- a/src/libslic3r/Fill/Lightning/Generator.cpp
+++ b/src/libslic3r/Fill/Lightning/Generator.cpp
@@ -35,17 +35,17 @@ Generator::Generator(const PrintObject &print_object)
// const int infill_extruder = region_config.infill_extruder.value;
const double default_infill_extrusion_width = Flow::auto_extrusion_width(FlowRole::frInfill, float(max_nozzle_diameter));
// Note: There's not going to be a layer below the first one, so the 'initial layer height' doesn't have to be taken into account.
- const double layer_thickness = object_config.layer_height;
+ const double layer_thickness = scaled(object_config.layer_height.value);
m_infill_extrusion_width = scaled(region_config.infill_extrusion_width.percent ? default_infill_extrusion_width * 0.01 * region_config.infill_extrusion_width : region_config.infill_extrusion_width);
- m_supporting_radius = scaled(m_infill_extrusion_width * 0.001 / region_config.fill_density);
+ m_supporting_radius = coord_t(m_infill_extrusion_width) * 100 / coord_t(region_config.fill_density.value);
- const double lightning_infill_overhang_angle = M_PI / 4; // 45 degrees
- const double lightning_infill_prune_angle = M_PI / 4; // 45 degrees
+ const double lightning_infill_overhang_angle = M_PI / 4; // 45 degrees
+ const double lightning_infill_prune_angle = M_PI / 4; // 45 degrees
const double lightning_infill_straightening_angle = M_PI / 4; // 45 degrees
- m_wall_supporting_radius = layer_thickness * std::tan(lightning_infill_overhang_angle);
- m_prune_length = layer_thickness * std::tan(lightning_infill_prune_angle);
- m_straightening_max_distance = layer_thickness * std::tan(lightning_infill_straightening_angle);
+ m_wall_supporting_radius = coord_t(layer_thickness * std::tan(lightning_infill_overhang_angle));
+ m_prune_length = coord_t(layer_thickness * std::tan(lightning_infill_prune_angle));
+ m_straightening_max_distance = coord_t(layer_thickness * std::tan(lightning_infill_straightening_angle));
generateInitialInternalOverhangs(print_object);
generateTrees(print_object);
@@ -54,19 +54,20 @@ Generator::Generator(const PrintObject &print_object)
void Generator::generateInitialInternalOverhangs(const PrintObject &print_object)
{
m_overhang_per_layer.resize(print_object.layers().size());
- const float infill_wall_offset = - m_infill_extrusion_width;
+ // FIXME: It can be adjusted to improve bonding between infill and perimeters.
+ const float infill_wall_offset = 0;// m_infill_extrusion_width;
Polygons infill_area_above;
//Iterate from top to bottom, to subtract the overhang areas above from the overhang areas on the layer below, to get only overhang in the top layer where it is overhanging.
- for (int layer_nr = print_object.layers().size() - 1; layer_nr >= 0; layer_nr--) {
+ for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; layer_nr--) {
Polygons infill_area_here;
for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions())
for (const Surface& surface : layerm->fill_surfaces.surfaces)
if (surface.surface_type == stInternal)
- append(infill_area_here, offset(surface.expolygon, infill_wall_offset));
+ append(infill_area_here, infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset));
//Remove the part of the infill area that is already supported by the walls.
- Polygons overhang = diff(offset(infill_area_here, -m_wall_supporting_radius), infill_area_above);
+ Polygons overhang = diff(offset(infill_area_here, -float(m_wall_supporting_radius)), infill_area_above);
m_overhang_per_layer[layer_nr] = overhang;
infill_area_above = std::move(infill_area_here);
@@ -82,16 +83,17 @@ const Layer& Generator::getTreesForLayer(const size_t& layer_id) const
void Generator::generateTrees(const PrintObject &print_object)
{
m_lightning_layers.resize(print_object.layers().size());
- const coord_t infill_wall_offset = - m_infill_extrusion_width;
+ // FIXME: It can be adjusted to improve bonding between infill and perimeters.
+ const coord_t infill_wall_offset = 0;// m_infill_extrusion_width;
std::vector infill_outlines(print_object.layers().size(), Polygons());
// For-each layer from top to bottom:
- for (int layer_id = print_object.layers().size() - 1; layer_id >= 0; layer_id--)
+ for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--)
for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions())
for (const Surface &surface : layerm->fill_surfaces.surfaces)
if (surface.surface_type == stInternal)
- append(infill_outlines[layer_id], offset(surface.expolygon, infill_wall_offset));
+ append(infill_outlines[layer_id], infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset));
// For various operations its beneficial to quickly locate nearby features on the polygon:
const size_t top_layer_id = print_object.layers().size() - 1;
@@ -99,16 +101,16 @@ void Generator::generateTrees(const PrintObject &print_object)
outlines_locator.create(infill_outlines[top_layer_id], locator_cell_size);
// For-each layer from top to bottom:
- for (int layer_id = top_layer_id; layer_id >= 0; layer_id--)
- {
- Layer& current_lightning_layer = m_lightning_layers[layer_id];
- Polygons& current_outlines = infill_outlines[layer_id];
+ for (int layer_id = int(top_layer_id); layer_id >= 0; layer_id--) {
+ Layer ¤t_lightning_layer = m_lightning_layers[layer_id];
+ const Polygons ¤t_outlines = infill_outlines[layer_id];
+ const BoundingBox ¤t_outlines_bbox = get_extents(current_outlines);
// register all trees propagated from the previous layer as to-be-reconnected
std::vector to_be_reconnected_tree_roots = current_lightning_layer.tree_roots;
- current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
- current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
+ current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
+ current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
// Initialize trees for next lower layer from the current one.
if (layer_id == 0)
diff --git a/src/libslic3r/Fill/Lightning/Generator.hpp b/src/libslic3r/Fill/Lightning/Generator.hpp
index c44ecfe7a2..b538c4dbe2 100644
--- a/src/libslic3r/Fill/Lightning/Generator.hpp
+++ b/src/libslic3r/Fill/Lightning/Generator.hpp
@@ -45,7 +45,7 @@ public:
* already be calculated at this point.
* \param mesh The mesh to generate infill for.
*/
- Generator(const PrintObject &print_object);
+ explicit Generator(const PrintObject &print_object);
/*!
* Get a tree of paths generated for a certain layer of the mesh.
diff --git a/src/libslic3r/Fill/Lightning/Layer.cpp b/src/libslic3r/Fill/Lightning/Layer.cpp
index 1b3936e340..1e1127a792 100644
--- a/src/libslic3r/Fill/Lightning/Layer.cpp
+++ b/src/libslic3r/Fill/Lightning/Layer.cpp
@@ -3,12 +3,11 @@
#include "Layer.hpp" //The class we're implementing.
-#include // advance
-
#include "DistanceField.hpp"
#include "TreeNode.hpp"
#include "../../Geometry.hpp"
+#include "Utils.hpp"
namespace Slic3r::FillLightning {
@@ -23,10 +22,15 @@ Point GroundingLocation::p() const
return tree_node ? tree_node->getLocation() : *boundary_location;
}
-void Layer::fillLocator(SparseNodeGrid &tree_node_locator)
+inline static Point to_grid_point(const Point &point, const BoundingBox &bbox)
{
- std::function add_node_to_locator_func = [&tree_node_locator](NodeSPtr node) {
- tree_node_locator.insert(std::make_pair(Point(node->getLocation().x() / locator_cell_size, node->getLocation().y() / locator_cell_size), node));
+ return (point - bbox.min) / locator_cell_size;
+}
+
+void Layer::fillLocator(SparseNodeGrid &tree_node_locator, const BoundingBox& current_outlines_bbox)
+{
+ std::function add_node_to_locator_func = [&tree_node_locator, ¤t_outlines_bbox](const NodeSPtr &node) {
+ tree_node_locator.insert(std::make_pair(to_grid_point(node->getLocation(), current_outlines_bbox), node));
};
for (auto& tree : tree_roots)
tree->visitNodes(add_node_to_locator_func);
@@ -36,38 +40,46 @@ void Layer::generateNewTrees
(
const Polygons& current_overhang,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outlines_locator,
const coord_t supporting_radius,
const coord_t wall_supporting_radius
)
{
- DistanceField distance_field(supporting_radius, current_outlines, current_overhang);
+ DistanceField distance_field(supporting_radius, current_outlines, current_outlines_bbox, current_overhang);
SparseNodeGrid tree_node_locator;
- fillLocator(tree_node_locator);
+ fillLocator(tree_node_locator, current_outlines_bbox);
// Until no more points need to be added to support all:
// Determine next point from tree/outline areas via distance-field
Point unsupported_location;
while (distance_field.tryGetNextPoint(&unsupported_location)) {
GroundingLocation grounding_loc = getBestGroundingLocation(
- unsupported_location, current_outlines, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
+ unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
NodeSPtr new_parent;
NodeSPtr new_child;
this->attach(unsupported_location, grounding_loc, new_child, new_parent);
- tree_node_locator.insert(std::make_pair(Point(new_child->getLocation().x() / locator_cell_size, new_child->getLocation().y() / locator_cell_size), new_child));
+ tree_node_locator.insert(std::make_pair(to_grid_point(new_child->getLocation(), current_outlines_bbox), new_child));
if (new_parent)
- tree_node_locator.insert(std::make_pair(Point(new_parent->getLocation().x() / locator_cell_size, new_parent->getLocation().y() / locator_cell_size), new_parent));
+ tree_node_locator.insert(std::make_pair(to_grid_point(new_parent->getLocation(), current_outlines_bbox), new_parent));
// update distance field
distance_field.update(grounding_loc.p(), unsupported_location);
}
+
+#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
+ {
+ static int iRun = 0;
+ export_to_svg(debug_out_path("FillLightning-TreeNodes-%d.svg", iRun++), current_outlines, this->tree_roots);
+ }
+#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */
}
-static bool polygonCollidesWithLineSegment(const Point from, const Point to, const EdgeGrid::Grid &loc_to_line)
+static bool polygonCollidesWithLineSegment(const Point &from, const Point &to, const EdgeGrid::Grid &loc_to_line)
{
struct Visitor {
- explicit Visitor(const EdgeGrid::Grid &grid) : grid(grid) {}
+ explicit Visitor(const EdgeGrid::Grid &grid, const Line &line) : grid(grid), line(line) {}
bool operator()(coord_t iy, coord_t ix) {
// Called with a row and colum of the grid cell, which is intersected by a line.
@@ -87,7 +99,7 @@ static bool polygonCollidesWithLineSegment(const Point from, const Point to, con
const EdgeGrid::Grid& grid;
Line line;
bool intersect = false;
- } visitor(loc_to_line);
+ } visitor(loc_to_line, {from, to});
loc_to_line.visit_cells_intersecting_line(from, to, visitor);
return visitor.intersect;
@@ -97,6 +109,7 @@ GroundingLocation Layer::getBestGroundingLocation
(
const Point& unsupported_location,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
const coord_t supporting_radius,
const coord_t wall_supporting_radius,
@@ -128,8 +141,8 @@ GroundingLocation Layer::getBestGroundingLocation
if (current_dist >= wall_supporting_radius) { // Only reconnect tree roots to other trees if they are not already close to the outlines.
const coord_t search_radius = std::min(current_dist, within_dist);
BoundingBox region(unsupported_location - Point(search_radius, search_radius), unsupported_location + Point(search_radius + locator_cell_size, search_radius + locator_cell_size));
- region.min /= locator_cell_size;
- region.max /= locator_cell_size;
+ region.min = to_grid_point(region.min, current_outlines_bbox);
+ region.max = to_grid_point(region.max, current_outlines_bbox);
Point grid_addr;
for (grid_addr.y() = region.min.y(); grid_addr.y() < region.max.y(); ++ grid_addr.y())
for (grid_addr.x() = region.min.x(); grid_addr.x() < region.max.x(); ++ grid_addr.x()) {
@@ -176,6 +189,7 @@ void Layer::reconnectRoots
(
std::vector& to_be_reconnected_tree_roots,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
const coord_t supporting_radius,
const coord_t wall_supporting_radius
@@ -184,10 +198,10 @@ void Layer::reconnectRoots
constexpr coord_t tree_connecting_ignore_offset = 100;
SparseNodeGrid tree_node_locator;
- fillLocator(tree_node_locator);
+ fillLocator(tree_node_locator, current_outlines_bbox);
const coord_t within_max_dist = outline_locator.resolution() * 2;
- for (auto root_ptr : to_be_reconnected_tree_roots)
+ for (const auto &root_ptr : to_be_reconnected_tree_roots)
{
auto old_root_it = std::find(tree_roots.begin(), tree_roots.end(), root_ptr);
@@ -203,7 +217,7 @@ void Layer::reconnectRoots
root_ptr->addChild(new_root);
new_root->reroot();
- tree_node_locator.insert(std::make_pair(Point(new_root->getLocation().x() / locator_cell_size, new_root->getLocation().y() / locator_cell_size), new_root));
+ tree_node_locator.insert(std::make_pair(to_grid_point(new_root->getLocation(), current_outlines_bbox), new_root));
*old_root_it = std::move(new_root); // replace old root with new root
continue;
@@ -217,6 +231,7 @@ void Layer::reconnectRoots
(
root_ptr->getLocation(),
current_outlines,
+ current_outlines_bbox,
outline_locator,
supporting_radius,
tree_connecting_ignore_width,
@@ -233,7 +248,7 @@ void Layer::reconnectRoots
attach_ptr->reroot();
new_root->addChild(attach_ptr);
- tree_node_locator.insert(std::make_pair(new_root->getLocation(), new_root));
+ tree_node_locator.insert(std::make_pair(to_grid_point(new_root->getLocation(), current_outlines_bbox), new_root));
*old_root_it = std::move(new_root); // replace old root with new root
}
@@ -256,15 +271,25 @@ void Layer::reconnectRoots
}
}
-/*
- * Implementation assumes moving inside, but moving outside should just as well be possible.
+/*!
+ * Moves the point \p from onto the nearest polygon or leaves the point as-is, when the comb boundary is not within the root of \p max_dist2 distance.
+ * Given a \p distance more than zero, the point will end up inside, and conversely outside.
+ * When the point is already in/outside by more than \p distance, \p from is unaltered, but the polygon is returned.
+ * When the point is in/outside by less than \p distance, \p from is moved to the correct place.
+ * Implementation assumes moving inside, but moving outside should just as well be possible.
+ *
+ * \param polygons The polygons onto which to move the point
+ * \param from[in,out] The point to move.
+ * \param distance The distance by which to move the point.
+ * \param max_dist2 The squared maximal allowed distance from the point to the nearest polygon.
+ * \return The index to the polygon onto which we have moved the point.
*/
static unsigned int moveInside(const Polygons& polygons, Point& from, int distance, int64_t maxDist2)
{
- Point ret = from;
- int64_t bestDist2 = std::numeric_limits::max();
- unsigned int bestPoly = static_cast(-1);
- bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary
+ Point ret = from;
+ int64_t bestDist2 = std::numeric_limits::max();
+ auto bestPoly = static_cast(-1);
+ bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
{
const Polygon &poly = polygons[poly_idx];
@@ -333,7 +358,7 @@ static unsigned int moveInside(const Polygons& polygons, Point& from, int distan
else
{ // x is projected to a point properly on the line segment (not onto a vertex). The case which looks like | .
projected_p_beyond_prev_segment = false;
- Point x = a + ab * dot_prod / ab_length2;
+ Point x = (a.cast() + ab.cast() * dot_prod / ab_length2).cast();
int64_t dist2 = (p - x).cast().squaredNorm();
if (dist2 < bestDist2)
diff --git a/src/libslic3r/Fill/Lightning/Layer.hpp b/src/libslic3r/Fill/Lightning/Layer.hpp
index 853c634f27..cc79c15b51 100644
--- a/src/libslic3r/Fill/Lightning/Layer.hpp
+++ b/src/libslic3r/Fill/Lightning/Layer.hpp
@@ -41,9 +41,10 @@ public:
(
const Polygons& current_overhang,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
- const coord_t supporting_radius,
- const coord_t wall_supporting_radius
+ coord_t supporting_radius,
+ coord_t wall_supporting_radius
);
/*! Determine & connect to connection point in tree/outline.
@@ -53,9 +54,10 @@ public:
(
const Point& unsupported_location,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
- const coord_t supporting_radius,
- const coord_t wall_supporting_radius,
+ coord_t supporting_radius,
+ coord_t wall_supporting_radius,
const SparseNodeGrid& tree_node_locator,
const NodeSPtr& exclude_tree = nullptr
);
@@ -71,16 +73,17 @@ public:
(
std::vector& to_be_reconnected_tree_roots,
const Polygons& current_outlines,
+ const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
- const coord_t supporting_radius,
- const coord_t wall_supporting_radius
+ coord_t supporting_radius,
+ coord_t wall_supporting_radius
);
- Polylines convertToLines(const Polygons& limit_to_outline, const coord_t line_width) const;
+ Polylines convertToLines(const Polygons& limit_to_outline, coord_t line_width) const;
coord_t getWeightedDistance(const Point& boundary_loc, const Point& unsupported_location);
- void fillLocator(SparseNodeGrid& tree_node_locator);
+ void fillLocator(SparseNodeGrid& tree_node_locator, const BoundingBox& current_outlines_bbox);
};
} // namespace Slic3r::FillLightning
diff --git a/src/libslic3r/Fill/Lightning/TreeNode.cpp b/src/libslic3r/Fill/Lightning/TreeNode.cpp
index 8ab11bd6d4..b36a66dbb7 100644
--- a/src/libslic3r/Fill/Lightning/TreeNode.cpp
+++ b/src/libslic3r/Fill/Lightning/TreeNode.cpp
@@ -4,7 +4,6 @@
#include "TreeNode.hpp"
#include "../../Geometry.hpp"
-#include "../../ClipperUtils.hpp"
namespace Slic3r::FillLightning {
@@ -107,7 +106,7 @@ NodeSPtr Node::deepCopy() const
return local_root;
}
-void Node::reroot(NodeSPtr new_parent /*= nullptr*/)
+void Node::reroot(const NodeSPtr &new_parent)
{
if (! m_is_root) {
auto old_parent = m_parent.lock();
@@ -142,7 +141,7 @@ NodeSPtr Node::closestNode(const Point& loc)
return result;
}
-bool inside(const Polygons &polygons, const Point p)
+bool inside(const Polygons &polygons, const Point &p)
{
int poly_count_inside = 0;
for (const Polygon &poly : polygons) {
@@ -181,7 +180,7 @@ bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeG
} visitor { outline_locator, a.cast(), b.cast() };
outline_locator.visit_cells_intersecting_line(a, b, visitor);
- return visitor.d2min < within_max_dist * within_max_dist;
+ return visitor.d2min < double(within_max_dist) * double(within_max_dist);
}
bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locator, std::vector& rerooted_parts)
@@ -226,14 +225,14 @@ bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locat
void Node::straighten(const coord_t magnitude, const coord_t max_remove_colinear_dist)
{
- straighten(magnitude, m_p, 0, max_remove_colinear_dist * max_remove_colinear_dist);
+ straighten(magnitude, m_p, 0, int64_t(max_remove_colinear_dist) * int64_t(max_remove_colinear_dist));
}
Node::RectilinearJunction Node::straighten(
const coord_t magnitude,
const Point& junction_above,
const coord_t accumulated_dist,
- const coord_t max_remove_colinear_dist2)
+ const int64_t max_remove_colinear_dist2)
{
constexpr coord_t junction_magnitude_factor_numerator = 3;
constexpr coord_t junction_magnitude_factor_denominator = 4;
@@ -245,13 +244,13 @@ Node::RectilinearJunction Node::straighten(
auto child_dist = coord_t((m_p - child_p->m_p).cast().norm());
RectilinearJunction junction_below = child_p->straighten(magnitude, junction_above, accumulated_dist + child_dist, max_remove_colinear_dist2);
coord_t total_dist_to_junction_below = junction_below.total_recti_dist;
- Point a = junction_above;
- Point b = junction_below.junction_loc;
+ const Point& a = junction_above;
+ Point b = junction_below.junction_loc;
if (a != b) // should always be true!
{
Point ab = b - a;
- Point destination = a + ab * accumulated_dist / std::max(coord_t(1), total_dist_to_junction_below);
- if ((destination - m_p).cast().squaredNorm() <= magnitude * magnitude)
+ Point destination = (a.cast() + ab.cast() * int64_t(accumulated_dist) / std::max(int64_t(1), int64_t(total_dist_to_junction_below))).cast();
+ if ((destination - m_p).cast().squaredNorm() <= int64_t(magnitude) * int64_t(magnitude))
m_p = destination;
else
m_p += ((destination - m_p).cast().normalized() * magnitude).cast();
@@ -262,7 +261,7 @@ Node::RectilinearJunction Node::straighten(
child_p = m_children.front(); //recursive call to straighten might have removed the child
const NodeSPtr& parent_node = m_parent.lock();
if (parent_node &&
- (child_p->m_p - parent_node->m_p).cast().squaredNorm() < max_remove_colinear_dist2 &&
+ (child_p->m_p - parent_node->m_p).cast().squaredNorm() < max_remove_colinear_dist2 &&
Line::distance_to_squared(m_p, parent_node->m_p, child_p->m_p) < close_enough * close_enough) {
child_p->m_parent = m_parent;
for (auto& sibling : parent_node->m_children)
@@ -347,7 +346,7 @@ coord_t Node::prune(const coord_t& pruning_distance)
void Node::convertToPolylines(Polygons& output, const coord_t line_width) const
{
Polygons result;
- output.emplace_back();
+ result.emplace_back();
convertToPolylines(0, result);
removeJunctionOverlap(result, line_width);
append(output, std::move(result));
@@ -386,7 +385,7 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt
coord_t to_be_reduced = reduction;
Point a = polyline.back();
- for (int point_idx = polyline.size() - 2; point_idx >= 0; point_idx--) {
+ for (int point_idx = int(polyline.size()) - 2; point_idx >= 0; point_idx--) {
const Point b = polyline[point_idx];
const Point ab = b - a;
const auto ab_len = coord_t(ab.cast().norm());
@@ -408,4 +407,29 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt
}
}
+#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
+void export_to_svg(const NodeSPtr &root_node, SVG &svg)
+{
+ for (const NodeSPtr &children : root_node->m_children) {
+ svg.draw(Line(root_node->getLocation(), children->getLocation()), "red");
+ export_to_svg(children, svg);
+ }
+}
+
+void export_to_svg(const std::string &path, const Polygons &contour, const std::vector &root_nodes) {
+ BoundingBox bbox = get_extents(contour);
+
+ bbox.offset(SCALED_EPSILON);
+ SVG svg(path, bbox);
+ svg.draw_outline(contour, "blue");
+
+ for (const NodeSPtr &root_node: root_nodes) {
+ for (const NodeSPtr &children: root_node->m_children) {
+ svg.draw(Line(root_node->getLocation(), children->getLocation()), "red");
+ export_to_svg(children, svg);
+ }
+ }
+}
+#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */
+
} // namespace Slic3r::FillLightning
diff --git a/src/libslic3r/Fill/Lightning/TreeNode.hpp b/src/libslic3r/Fill/Lightning/TreeNode.hpp
index bc2e76dc2f..55ef35e0a8 100644
--- a/src/libslic3r/Fill/Lightning/TreeNode.hpp
+++ b/src/libslic3r/Fill/Lightning/TreeNode.hpp
@@ -11,6 +11,9 @@
#include "../../EdgeGrid.hpp"
#include "../../Polygon.hpp"
+#include "SVG.hpp"
+
+//#define LIGHTNING_TREE_NODE_DEBUG_OUTPUT
namespace Slic3r::FillLightning
{
@@ -99,9 +102,9 @@ public:
std::vector& next_trees,
const Polygons& next_outlines,
const EdgeGrid::Grid& outline_locator,
- const coord_t prune_distance,
- const coord_t smooth_magnitude,
- const coord_t max_remove_colinear_dist
+ coord_t prune_distance,
+ coord_t smooth_magnitude,
+ coord_t max_remove_colinear_dist
) const;
/*!
@@ -156,7 +159,7 @@ public:
* This is then recursively bubbled up until it reaches the (former) root, which then will become a leaf.
* \param new_parent The (new) parent-node of the root, useful for recursing or immediately attaching the node to another tree.
*/
- void reroot(NodeSPtr new_parent = nullptr);
+ void reroot(const NodeSPtr &new_parent = nullptr);
/*!
* Retrieves the closest node to the specified location.
@@ -211,7 +214,7 @@ protected:
* \param magnitude The maximum allowed distance to move the node.
* \param max_remove_colinear_dist Maximum distance of the (compound) line-segment from which a co-linear point may be removed.
*/
- void straighten(const coord_t magnitude, const coord_t max_remove_colinear_dist);
+ void straighten(coord_t magnitude, coord_t max_remove_colinear_dist);
/*! Recursive part of \ref straighten(.)
* \param junction_above The last seen junction with multiple children above
@@ -219,7 +222,7 @@ protected:
* \param max_remove_colinear_dist2 Maximum distance _squared_ of the (compound) line-segment from which a co-linear point may be removed.
* \return the total distance along the tree from the last junction above to the first next junction below and the location of the next junction below
*/
- RectilinearJunction straighten(const coord_t magnitude, const Point& junction_above, const coord_t accumulated_dist, const coord_t max_remove_colinear_dist2);
+ RectilinearJunction straighten(coord_t magnitude, const Point& junction_above, coord_t accumulated_dist, int64_t max_remove_colinear_dist2);
/*! Prune the tree from the extremeties (leaf-nodes) until the pruning distance is reached.
* \return The distance that has been pruned. If less than \p distance, then the whole tree was puned away.
@@ -236,7 +239,7 @@ public:
*
* \param output all branches in this tree connected into polylines
*/
- void convertToPolylines(Polygons& output, const coord_t line_width) const;
+ void convertToPolylines(Polygons& output, coord_t line_width) const;
/*! If this was ever a direct child of the root, it'll have a previous grounding location.
*
@@ -257,7 +260,7 @@ protected:
*/
void convertToPolylines(size_t long_line_idx, Polygons& output) const;
- void removeJunctionOverlap(Polygons& polylines, const coord_t line_width) const;
+ void removeJunctionOverlap(Polygons& polylines, coord_t line_width) const;
bool m_is_root;
Point m_p;
@@ -265,10 +268,20 @@ protected:
std::vector m_children;
std::optional m_last_grounding_location; // &root_nodes);
+#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */
};
-bool inside(const Polygons &polygons, const Point p);
-bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, const coord_t within_max_dist);
+bool inside(const Polygons &polygons, const Point &p);
+bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, coord_t within_max_dist);
+
+#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
+void export_to_svg(const NodeSPtr &root_node, SVG &svg);
+void export_to_svg(const std::string &path, const Polygons &contour, const std::vector &root_nodes);
+#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */
} // namespace Slic3r::FillLightning
diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index 3bf7c4ffd3..a46103d6c8 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -36,6 +36,10 @@ static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
+#if ENABLE_PROCESS_G2_G3_LINES
+static const std::string INTERNAL_G2G3_TAG = "!#!#! internal only - from G2/G3 expansion !#!#!";
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
namespace Slic3r {
const std::vector GCodeProcessor::Reserved_Tags = {
@@ -737,9 +741,7 @@ void GCodeProcessorResult::reset() {
filament_diameters = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
custom_gcode_per_print_z = std::vector();
-#if ENABLE_SPIRAL_VASE_LAYERS
spiral_vase_layers = std::vector>>();
-#endif // ENABLE_SPIRAL_VASE_LAYERS
time = 0;
}
#else
@@ -755,9 +757,7 @@ void GCodeProcessorResult::reset() {
filament_diameters = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
custom_gcode_per_print_z = std::vector();
-#if ENABLE_SPIRAL_VASE_LAYERS
spiral_vase_layers = std::vector>>();
-#endif // ENABLE_SPIRAL_VASE_LAYERS
}
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -905,17 +905,13 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.max_print_height = config.max_print_height;
-#if ENABLE_SPIRAL_VASE_LAYERS
const ConfigOptionBool* spiral_vase = config.option("spiral_vase");
if (spiral_vase != nullptr)
m_spiral_vase_active = spiral_vase->value;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
-#if ENABLE_Z_OFFSET_CORRECTION
const ConfigOptionFloat* z_offset = config.option("z_offset");
if (z_offset != nullptr)
m_z_offset = z_offset->value;
-#endif // ENABLE_Z_OFFSET_CORRECTION
}
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@@ -1160,17 +1156,13 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (max_print_height != nullptr)
m_result.max_print_height = max_print_height->value;
-#if ENABLE_SPIRAL_VASE_LAYERS
const ConfigOptionBool* spiral_vase = config.option("spiral_vase");
if (spiral_vase != nullptr)
m_spiral_vase_active = spiral_vase->value;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
-#if ENABLE_Z_OFFSET_CORRECTION
const ConfigOptionFloat* z_offset = config.option("z_offset");
if (z_offset != nullptr)
m_z_offset = z_offset->value;
-#endif // ENABLE_Z_OFFSET_CORRECTION
}
void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
@@ -1203,9 +1195,7 @@ void GCodeProcessor::reset()
m_forced_height = 0.0f;
m_mm3_per_mm = 0.0f;
m_fan_speed = 0.0f;
-#if ENABLE_Z_OFFSET_CORRECTION
m_z_offset = 0.0f;
-#endif // ENABLE_Z_OFFSET_CORRECTION
m_extrusion_role = erNone;
m_extruder_id = 0;
@@ -1220,7 +1210,6 @@ void GCodeProcessor::reset()
m_extruded_last_z = 0.0f;
m_first_layer_height = 0.0f;
- m_processing_start_custom_gcode = false;
m_g1_line_id = 0;
m_layer_id = 0;
m_cp_color.reset();
@@ -1238,9 +1227,7 @@ void GCodeProcessor::reset()
m_options_z_corrector.reset();
-#if ENABLE_SPIRAL_VASE_LAYERS
m_spiral_vase_active = false;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_mm3_per_mm_compare.reset();
@@ -1596,6 +1583,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
switch (cmd[1]) {
case '0': { process_G0(line); break; } // Move
case '1': { process_G1(line); break; } // Move
+#if ENABLE_PROCESS_G2_G3_LINES
+ case '2': { process_G2_G3(line, true); break; } // CW Arc Move
+ case '3': { process_G2_G3(line, false); break; } // CCW Arc Move
+#endif // ENABLE_PROCESS_G2_G3_LINES
default: break;
}
break;
@@ -1826,7 +1817,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
set_extrusion_role(ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length())));
if (m_extrusion_role == erExternalPerimeter)
m_seams_detector.activate(true);
- m_processing_start_custom_gcode = (m_extrusion_role == erCustom && m_g1_line_id == 0);
return;
}
@@ -1950,7 +1940,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
// layer change tag
if (comment == reserved_tag(ETags::Layer_Change)) {
++m_layer_id;
-#if ENABLE_SPIRAL_VASE_LAYERS
if (m_spiral_vase_active) {
if (m_result.moves.empty())
m_result.spiral_vase_layers.push_back({ m_first_layer_height, { 0, 0 } });
@@ -1962,7 +1951,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
m_result.spiral_vase_layers.push_back({ static_cast(m_end_position[Z]), { move_id, move_id } });
}
}
-#endif // ENABLE_SPIRAL_VASE_LAYERS
return;
}
@@ -2453,9 +2441,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
{
- float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
- float filament_radius = 0.5f * filament_diameter;
- float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius);
+ const float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
+ const float filament_radius = 0.5f * filament_diameter;
+ const float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius);
+#if !ENABLE_PROCESS_G2_G3_LINES
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
if (axis == E)
@@ -2471,6 +2460,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
else
return m_start_position[axis];
};
+#endif // !ENABLE_PROCESS_G2_G3_LINES
auto move_type = [this](const AxisCoords& delta_pos) {
EMoveType type = EMoveType::Noop;
@@ -2498,7 +2488,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// updates axes positions from line
for (unsigned char a = X; a <= E; ++a) {
+#if ENABLE_PROCESS_G2_G3_LINES
+ m_end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
+#else
m_end_position[a] = absolute_position((Axis)a, line);
+#endif // ENABLE_PROCESS_G2_G3_LINES
}
// updates feedrate from line, if present
@@ -2517,11 +2511,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (max_abs_delta == 0.0f)
return;
- EMoveType type = move_type(delta_pos);
+ const EMoveType type = move_type(delta_pos);
if (type == EMoveType::Extrude) {
- float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
- float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
- float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
+ const float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
+ const float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
+ const float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
// save extruded volume to the cache
m_used_filaments.increase_caches(volume_extruded_filament);
@@ -2532,12 +2526,25 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
+#if ENABLE_PROCESS_G2_G3_LINES
if (m_forced_height > 0.0f)
m_height = m_forced_height;
+ else if (m_layer_id == 0)
+ m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height;
+ else if (line.comment() != INTERNAL_G2G3_TAG){
+ if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0)
+ m_height = m_end_position[Z] - m_extruded_last_z;
+ }
+#else
+ if (m_forced_height > 0.0f)
+ m_height = m_forced_height;
+ else if (m_layer_id == 0)
+ m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height;
else {
if (m_end_position[Z] > m_extruded_last_z + EPSILON)
m_height = m_end_position[Z] - m_extruded_last_z;
}
+#endif // ENABLE_PROCESS_G2_G3_LINES
if (m_height == 0.0f)
m_height = DEFAULT_TOOLPATH_HEIGHT;
@@ -2545,7 +2552,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
if (m_end_position[Z] == 0.0f)
m_end_position[Z] = m_height;
- m_extruded_last_z = m_end_position[Z];
+#if ENABLE_PROCESS_G2_G3_LINES
+ if (line.comment() != INTERNAL_G2G3_TAG)
+#endif // ENABLE_PROCESS_G2_G3_LINES
+ m_extruded_last_z = m_end_position[Z];
m_options_z_corrector.update(m_height);
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
@@ -2585,9 +2595,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f;
};
- float distance = move_length(delta_pos);
+ const float distance = move_length(delta_pos);
assert(distance != 0.0f);
- float inv_distance = 1.0f / distance;
+ const float inv_distance = 1.0f / distance;
for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i];
@@ -2618,7 +2628,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
if (curr.abs_axis_feedrate[a] != 0.0f) {
- float axis_max_feedrate = get_axis_max_feedrate(static_cast(i), static_cast(a));
+ const float axis_max_feedrate = get_axis_max_feedrate(static_cast(i), static_cast(a));
if (axis_max_feedrate != 0.0f)
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
}
@@ -2641,7 +2651,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
get_acceleration(static_cast(i)));
for (unsigned char a = X; a <= E; ++a) {
- float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a));
+ const float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a));
if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
acceleration = axis_max_acceleration;
}
@@ -2652,7 +2662,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
curr.safe_feedrate = block.feedrate_profile.cruise;
for (unsigned char a = X; a <= E; ++a) {
- float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a));
+ const float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a));
if (curr.abs_axis_feedrate[a] > axis_max_jerk)
curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
}
@@ -2686,7 +2696,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
}
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
- float jerk =
+ const float jerk =
(v_exit > v_entry) ?
((v_entry > 0.0f || v_exit < 0.0f) ?
// coasting
@@ -2700,7 +2710,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// axis reversal
std::max(-v_exit, v_entry));
- float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a));
+ const float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a));
if (jerk > axis_max_jerk) {
v_factor *= axis_max_jerk / jerk;
limited = true;
@@ -2712,14 +2722,14 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
- float vmax_junction_threshold = vmax_junction * 0.99f;
+ const float vmax_junction_threshold = vmax_junction * 0.99f;
// Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
vmax_junction = curr.safe_feedrate;
}
- float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
+ const float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
block.feedrate_profile.entry = std::min(vmax_junction, v_allowable);
block.max_entry_speed = vmax_junction;
@@ -2755,11 +2765,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// the threshold value = 0.0625f == 0.25 * 0.25 is arbitrary, we may find some smarter condition later
if ((new_pos - *first_vertex).squaredNorm() < 0.0625f) {
-#if ENABLE_Z_OFFSET_CORRECTION
set_end_position(0.5f * (new_pos + *first_vertex) + m_z_offset * Vec3f::UnitZ());
-#else
- set_end_position(0.5f * (new_pos + *first_vertex));
-#endif // ENABLE_Z_OFFSET_CORRECTION
store_move_vertex(EMoveType::Seam);
set_end_position(curr_pos);
}
@@ -2772,15 +2778,221 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
}
-#if ENABLE_SPIRAL_VASE_LAYERS
if (m_spiral_vase_active && !m_result.spiral_vase_layers.empty() && !m_result.moves.empty())
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
// store move
+#if ENABLE_PROCESS_G2_G3_LINES
+ store_move_vertex(type, line.comment() == INTERNAL_G2G3_TAG);
+#else
store_move_vertex(type);
+#endif // ENABLE_PROCESS_G2_G3_LINES
}
+#if ENABLE_PROCESS_G2_G3_LINES
+void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise)
+{
+ if (!line.has('X') || !line.has('Y') || !line.has('I') || !line.has('J'))
+ return;
+
+ // relative center
+ Vec3f rel_center = Vec3f::Zero();
+ if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y()))
+ return;
+
+ // scale center, if needed
+ if (m_units == EUnits::Inches)
+ rel_center *= INCHES_TO_MM;
+
+ struct Arc
+ {
+ Vec3d start{ Vec3d::Zero() };
+ Vec3d end{ Vec3d::Zero() };
+ Vec3d center{ Vec3d::Zero() };
+
+ double angle{ 0.0 };
+ double delta_x() const { return end.x() - start.x(); }
+ double delta_y() const { return end.y() - start.y(); }
+ double delta_z() const { return end.z() - start.z(); }
+
+ double length() const { return angle * start_radius(); }
+ double travel_length() const { return std::sqrt(sqr(length() + sqr(delta_z()))); }
+ double start_radius() const { return (start - center).norm(); }
+ double end_radius() const { return (end - center).norm(); }
+
+ Vec3d relative_start() const { return start - center; }
+ Vec3d relative_end() const { return end - center; }
+
+ bool closed() const { return end.isApprox(start); }
+ };
+
+ Arc arc;
+
+ // arc start endpoint
+ arc.start = Vec3d(m_start_position[X], m_start_position[Y], m_start_position[Z]);
+
+ // arc center
+ arc.center = arc.start + rel_center.cast();
+
+ const float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
+ const float filament_radius = 0.5f * filament_diameter;
+ const float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius);
+
+ AxisCoords end_position = m_start_position;
+ for (unsigned char a = X; a <= E; ++a) {
+ end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
+ }
+
+ // arc end endpoint
+ arc.end = Vec3d(end_position[X], end_position[Y], end_position[Z]);
+
+ // radii
+ if (std::abs(arc.end_radius() - arc.start_radius()) > EPSILON) {
+ // what to do ???
+ }
+
+ // updates feedrate from line
+ std::optional feedrate;
+ if (line.has_f())
+ feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
+
+ // updates extrusion from line
+ std::optional extrusion;
+ if (line.has_e())
+ extrusion = end_position[E] - m_start_position[E];
+
+ // relative arc endpoints
+ const Vec3d rel_arc_start = arc.relative_start();
+ const Vec3d rel_arc_end = arc.relative_end();
+
+ // arc angle
+ if (arc.closed())
+ arc.angle = 2.0 * PI;
+ else {
+ arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(),
+ rel_arc_start.x() * rel_arc_end.x() + rel_arc_start.y() * rel_arc_end.y());
+ if (arc.angle < 0.0)
+ arc.angle += 2.0 * PI;
+ if (clockwise)
+ arc.angle -= 2.0 * PI;
+ }
+
+ const double travel_length = arc.travel_length();
+ if (travel_length < 0.001)
+ return;
+
+ auto adjust_target = [this, area_filament_cross_section](const AxisCoords& target, const AxisCoords& prev_position) {
+ AxisCoords ret = target;
+ if (m_global_positioning_type == EPositioningType::Relative) {
+ for (unsigned char a = X; a <= E; ++a) {
+ ret[a] -= prev_position[a];
+ }
+ }
+ else if (m_e_local_positioning_type == EPositioningType::Relative)
+ ret[E] -= prev_position[E];
+
+ if (m_use_volumetric_e)
+ ret[E] *= area_filament_cross_section;
+
+ const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
+ for (unsigned char a = X; a <= E; ++a) {
+ ret[a] /= lengthsScaleFactor;
+ }
+ return ret;
+ };
+
+ auto internal_only_g1_line = [](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) {
+ std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
+ if (has_z)
+ ret += (boost::format(" Z%1%") % target[Z]).str();
+ if (feedrate.has_value())
+ ret += (boost::format(" F%1%") % *feedrate).str();
+ if (extrusion.has_value())
+ ret += (boost::format(" E%1%") % target[E]).str();
+
+ ret += (boost::format(" ;%1%\n") % INTERNAL_G2G3_TAG).str();
+
+ return ret;
+ };
+
+ // calculate arc segments
+ // reference:
+ // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc()
+
+ // segments count
+ static const double MM_PER_ARC_SEGMENT = 1.0;
+ const size_t segments = std::max(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1);
+
+ const double theta_per_segment = arc.angle / double(segments);
+ const double z_per_segment = arc.delta_z() / double(segments);
+ const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0;
+
+ double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
+ double sin_T = theta_per_segment;
+
+ AxisCoords prev_target = m_start_position;
+ AxisCoords arc_target;
+ double sin_Ti;
+ double cos_Ti;
+ double r_axisi;
+ size_t count = 0;
+
+ // Initialize the linear axis
+ arc_target[Z] = m_start_position[Z];
+
+ // Initialize the extruder axis
+ arc_target[E] = m_start_position[E];
+
+ static const size_t N_ARC_CORRECTION = 25;
+
+ Vec3d curr_rel_arc_start = arc.relative_start();
+
+ std::string gcode;
+
+ for (size_t i = 1; i < segments; ++i) { // Increment (segments-1)
+ if (count < N_ARC_CORRECTION) {
+ // Apply vector rotation matrix
+ r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T;
+ curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T;
+ curr_rel_arc_start.y() = r_axisi;
+ count++;
+ }
+ else {
+ // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+ // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+ cos_Ti = ::cos(double(i) * theta_per_segment);
+ sin_Ti = ::sin(double(i) * theta_per_segment);
+ curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
+ curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
+ count = 0;
+ }
+
+ // Update arc_target location
+ arc_target[X] = arc.center.x() + curr_rel_arc_start.x();
+ arc_target[Y] = arc.center.y() + curr_rel_arc_start.y();
+ arc_target[Z] += z_per_segment;
+ arc_target[E] += extruder_per_segment;
+
+ gcode += internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
+ prev_target = arc_target;
+
+ // feedrate is constant, we do not need to repeat it
+ feedrate.reset();
+ }
+
+ // Ensure last segment arrives at target location.
+ gcode += internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
+
+ // process fake gcode lines
+ GCodeReader parser;
+ parser.parse_buffer(gcode, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
+ // force all lines to share the same id
+ --m_line_id;
+ process_gcode_line(line, false);
+ });
+}
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
{
// stores retract move
@@ -3281,7 +3493,11 @@ void GCodeProcessor::process_T(const std::string_view command)
}
}
+#if ENABLE_PROCESS_G2_G3_LINES
+void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
+#else
void GCodeProcessor::store_move_vertex(EMoveType type)
+#endif // ENABLE_PROCESS_G2_G3_LINES
{
m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
m_line_id + 1 :
@@ -3293,11 +3509,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
m_extrusion_role,
m_extruder_id,
m_cp_color.current,
-#if ENABLE_Z_OFFSET_CORRECTION
- Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id],
-#else
- Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
-#endif // ENABLE_Z_OFFSET_CORRECTION
+ Vec3f(m_end_position[X], m_end_position[Y], m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id],
static_cast(m_end_position[E] - m_start_position[E]),
m_feedrate,
m_width,
@@ -3305,7 +3517,12 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
m_mm3_per_mm,
m_fan_speed,
m_extruder_temps[m_extruder_id],
+#if ENABLE_PROCESS_G2_G3_LINES
+ static_cast(m_result.moves.size()),
+ internal_only
+#else
static_cast(m_result.moves.size())
+#endif // ENABLE_PROCESS_G2_G3_LINES
});
// stores stop time placeholders for later use
@@ -3502,5 +3719,24 @@ void GCodeProcessor::update_estimated_times_stats()
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
}
+#if ENABLE_PROCESS_G2_G3_LINES
+double GCodeProcessor::extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section)
+{
+ if (line.has(Slic3r::Axis(axis))) {
+ bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
+ if (axis == E)
+ is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
+
+ const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
+ double ret = line.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
+ if (axis == E && m_use_volumetric_e)
+ ret /= area_filament_cross_section;
+ return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
+ }
+ else
+ return m_start_position[axis];
+}
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
} /* namespace Slic3r */
diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp
index 25375f61b6..1ef414c3f3 100644
--- a/src/libslic3r/GCode/GCodeProcessor.hpp
+++ b/src/libslic3r/GCode/GCodeProcessor.hpp
@@ -113,6 +113,9 @@ namespace Slic3r {
float fan_speed{ 0.0f }; // percentage
float temperature{ 0.0f }; // Celsius degrees
float time{ 0.0f }; // s
+#if ENABLE_PROCESS_G2_G3_LINES
+ bool internal_only{ false };
+#endif // ENABLE_PROCESS_G2_G3_LINES
float volumetric_rate() const { return feedrate * mm3_per_mm; }
};
@@ -131,9 +134,7 @@ namespace Slic3r {
std::vector filament_densities;
PrintEstimatedStatistics print_statistics;
std::vector custom_gcode_per_print_z;
-#if ENABLE_SPIRAL_VASE_LAYERS
std::vector>> spiral_vase_layers;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
@@ -542,16 +543,13 @@ namespace Slic3r {
float m_forced_height; // mm
float m_mm3_per_mm;
float m_fan_speed; // percentage
-#if ENABLE_Z_OFFSET_CORRECTION
float m_z_offset; // mm
-#endif // ENABLE_Z_OFFSET_CORRECTION
ExtrusionRole m_extrusion_role;
unsigned char m_extruder_id;
ExtruderColors m_extruder_colors;
ExtruderTemps m_extruder_temps;
float m_extruded_last_z;
float m_first_layer_height; // mm
- bool m_processing_start_custom_gcode;
unsigned int m_g1_line_id;
unsigned int m_layer_id;
CpColor m_cp_color;
@@ -559,9 +557,7 @@ namespace Slic3r {
SeamsDetector m_seams_detector;
OptionsZCorrector m_options_z_corrector;
size_t m_last_default_color_id;
-#if ENABLE_SPIRAL_VASE_LAYERS
bool m_spiral_vase_active;
-#endif // ENABLE_SPIRAL_VASE_LAYERS
#if ENABLE_GCODE_VIEWER_STATISTICS
std::chrono::time_point m_start_time;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -652,6 +648,11 @@ namespace Slic3r {
void process_G0(const GCodeReader::GCodeLine& line);
void process_G1(const GCodeReader::GCodeLine& line);
+#if ENABLE_PROCESS_G2_G3_LINES
+ // Arc Move
+ void process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise);
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
// Retract
void process_G10(const GCodeReader::GCodeLine& line);
@@ -752,7 +753,11 @@ namespace Slic3r {
void process_T(const GCodeReader::GCodeLine& line);
void process_T(const std::string_view command);
+#if ENABLE_PROCESS_G2_G3_LINES
+ void store_move_vertex(EMoveType type, bool internal_only = false);
+#else
void store_move_vertex(EMoveType type);
+#endif // ENABLE_PROCESS_G2_G3_LINES
void set_extrusion_role(ExtrusionRole role);
@@ -777,6 +782,10 @@ namespace Slic3r {
void simulate_st_synchronize(float additional_time = 0.0f);
void update_estimated_times_stats();
+
+#if ENABLE_PROCESS_G2_G3_LINES
+ double extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section);
+#endif // ENABLE_PROCESS_G2_G3_LINES
};
} /* namespace Slic3r */
diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp
index 0071c7f6e1..a308ac0b62 100644
--- a/src/libslic3r/Layer.hpp
+++ b/src/libslic3r/Layer.hpp
@@ -20,6 +20,10 @@ namespace FillAdaptive {
struct Octree;
};
+namespace FillLightning {
+ class Generator;
+};
+
class LayerRegion
{
public:
@@ -151,8 +155,8 @@ public:
}
void make_perimeters();
// Phony version of make_fills() without parameters for Perl integration only.
- void make_fills() { this->make_fills(nullptr, nullptr); }
- void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree);
+ void make_fills() { this->make_fills(nullptr, nullptr, nullptr); }
+ void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator);
void make_ironing();
void export_region_slices_to_svg(const char *path) const;
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index 51c26209e9..01d3c592a6 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -8,7 +8,7 @@
namespace Slic3r {
-static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance)
+static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
{
ExtrusionPaths paths;
ExtrusionPath path(role);
@@ -71,7 +71,7 @@ static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thi
path.height = new_flow.height();
} else {
thickness_delta = fabs(scale_(flow.width()) - w);
- if (thickness_delta <= tolerance) {
+ if (thickness_delta <= merge_tolerance) {
// the width difference between this line and the current flow width is
// within the accepted tolerance
path.polyline.append(line.b);
@@ -95,7 +95,7 @@ static void variable_width(const ThickPolylines& polylines, ExtrusionRole role,
// of segments, and any pruning shall be performed before we apply this tolerance.
const float tolerance = float(scale_(0.05));
for (const ThickPolyline &p : polylines) {
- ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance);
+ ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance, tolerance);
// Append paths to collection.
if (! paths.empty()) {
if (paths.front().first_point() == paths.back().last_point())
diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp
index e5dc334f59..6b430c2fef 100644
--- a/src/libslic3r/Point.hpp
+++ b/src/libslic3r/Point.hpp
@@ -177,6 +177,11 @@ inline bool operator<(const Point &l, const Point &r)
return l.x() < r.x() || (l.x() == r.x() && l.y() < r.y());
}
+inline Point operator* (const Point& l, const double &r)
+{
+ return {coord_t(l.x() * r), coord_t(l.y() * r)};
+}
+
inline bool is_approx(const Point &p1, const Point &p2, coord_t epsilon = coord_t(SCALED_EPSILON))
{
Point d = (p2 - p1).cwiseAbs();
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index c5e312a2bf..d99e24ca70 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -35,7 +35,13 @@ namespace FillAdaptive {
struct Octree;
struct OctreeDeleter;
using OctreePtr = std::unique_ptr;
-};
+}; // namespace FillAdaptive
+
+namespace FillLightning {
+ class Generator;
+ struct GeneratorDeleter;
+ using GeneratorPtr = std::unique_ptr;
+}; // namespace FillLightning
// Print step IDs for keeping track of the print state.
// The Print steps are applied in this order.
@@ -387,6 +393,7 @@ private:
void combine_infill();
void _generate_support_material();
std::pair prepare_adaptive_infill_data();
+ FillLightning::GeneratorPtr prepare_lightning_infill_data();
// XYZ in scaled coordinates
Vec3crd m_size;
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 5a674da846..b21ed56318 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -108,9 +108,7 @@ static const t_config_enum_values s_keys_map_InfillPattern {
{ "octagramspiral", ipOctagramSpiral },
{ "adaptivecubic", ipAdaptiveCubic },
{ "supportcubic", ipSupportCubic },
-#if HAS_LIGHTNING_INFILL
{ "lightning", ipLightning }
-#endif // HAS_LIGHTNING_INFILL
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern)
@@ -1155,9 +1153,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("octagramspiral");
def->enum_values.push_back("adaptivecubic");
def->enum_values.push_back("supportcubic");
-#if HAS_LIGHTNING_INFILL
def->enum_values.push_back("lightning");
-#endif // HAS_LIGHTNING_INFILL
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Aligned Rectilinear"));
def->enum_labels.push_back(L("Grid"));
@@ -1174,9 +1170,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Octagram Spiral"));
def->enum_labels.push_back(L("Adaptive Cubic"));
def->enum_labels.push_back(L("Support Cubic"));
-#if HAS_LIGHTNING_INFILL
def->enum_labels.push_back(L("Lightning"));
-#endif // HAS_LIGHTNING_INFILL
def->set_default_value(new ConfigOptionEnum(ipStars));
def = this->add("first_layer_acceleration", coFloat);
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index b97168e84e..950816fa91 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -57,14 +57,10 @@ enum class FuzzySkinType {
All,
};
-#define HAS_LIGHTNING_INFILL 0
-
enum InfillPattern : int {
ipRectilinear, ipMonotonic, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
- ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase,
-#if HAS_LIGHTNING_INFILL
- ipLightning,
-#endif // HAS_LIGHTNING_INFILL
+ ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase,
+ ipLightning,
ipCount,
};
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index 31d948db9d..9c6178f8b5 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -14,6 +14,7 @@
#include "TriangleMeshSlicer.hpp"
#include "Utils.hpp"
#include "Fill/FillAdaptive.hpp"
+#include "Fill/FillLightning.hpp"
#include "Format/STL.hpp"
#include
@@ -353,14 +354,15 @@ void PrintObject::infill()
if (this->set_started(posInfill)) {
auto [adaptive_fill_octree, support_fill_octree] = this->prepare_adaptive_infill_data();
+ auto lightning_generator = this->prepare_lightning_infill_data();
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
tbb::parallel_for(
tbb::blocked_range(0, m_layers.size()),
- [this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree](const tbb::blocked_range& range) {
+ [this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree, &lightning_generator](const tbb::blocked_range& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
m_print->throw_if_canceled();
- m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get());
+ m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), lightning_generator.get());
}
}
);
@@ -453,6 +455,18 @@ std::pair PrintObject::prepare
support_line_spacing ? build_octree(mesh, overhangs.front(), support_line_spacing, true) : OctreePtr());
}
+FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data()
+{
+ bool has_lightning_infill = false;
+ for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id)
+ if (const PrintRegionConfig &config = this->printing_region(region_id).config(); config.fill_density > 0 && config.fill_pattern == ipLightning) {
+ has_lightning_infill = true;
+ break;
+ }
+
+ return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this)) : FillLightning::GeneratorPtr();
+}
+
void PrintObject::clear_layers()
{
for (Layer *l : m_layers)
diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp
index 72cb96dd04..81ce0d6cb0 100644
--- a/src/libslic3r/SLAPrint.cpp
+++ b/src/libslic3r/SLAPrint.cpp
@@ -1174,7 +1174,8 @@ sla::SupportPoints SLAPrintObject::transformed_support_points() const
{
assert(m_model_object != nullptr);
auto spts = m_model_object->sla_support_points;
- auto tr = trafo().cast();
+ const Transform3d& vol_trafo = m_model_object->volumes.front()->get_transformation().get_matrix();
+ const Transform3f& tr = (trafo() * vol_trafo).cast();
for (sla::SupportPoint& suppt : spts) {
suppt.pos = tr * suppt.pos;
}
@@ -1186,8 +1187,10 @@ sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const
{
assert(m_model_object != nullptr);
auto pts = m_model_object->sla_drain_holes;
- auto tr = trafo().cast();
- auto sc = m_model_object->instances.front()->get_scaling_factor().cast();
+ const Transform3d& vol_trafo = m_model_object->volumes.front()->get_transformation().get_matrix();
+ const Geometry::Transformation trans(trafo() * vol_trafo);
+ const Transform3f& tr = trans.get_matrix().cast();
+ const Vec3f sc = trans.get_scaling_factor().cast();
for (sla::DrainHole &hl : pts) {
hl.pos = tr * hl.pos;
hl.normal = tr * hl.normal - tr.translation();
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 6d5668002c..62c90d210d 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -36,17 +36,6 @@
#define ENABLE_SMOOTH_NORMALS 0
-//================
-// 2.4.1.rc techs
-//================
-#define ENABLE_2_4_1_RC 1
-
-// Enable detection of layers for spiral vase prints
-#define ENABLE_SPIRAL_VASE_LAYERS (1 && ENABLE_2_4_1_RC)
-// Enable correction of toolpaths when z offset is set
-#define ENABLE_Z_OFFSET_CORRECTION (1 && ENABLE_2_4_1_RC)
-
-
//====================
// 2.5.0.alpha1 techs
//====================
@@ -94,5 +83,9 @@
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified rectangle selection
#define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
+// Enable alternative version of file_wildcards()
+#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1)
+// Enable processing of gcode G2 and G3 lines
+#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index ce308b777e..03893ebd7a 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -217,6 +217,8 @@ set(SLIC3R_GUI_SOURCES
GUI/DesktopIntegrationDialog.hpp
GUI/HintNotification.cpp
GUI/HintNotification.hpp
+ Utils/AppUpdater.cpp
+ Utils/AppUpdater.hpp
Utils/Http.cpp
Utils/Http.hpp
Utils/FixModelByWin10.cpp
@@ -254,6 +256,7 @@ if (APPLE)
list(APPEND SLIC3R_GUI_SOURCES
Utils/RetinaHelperImpl.mm
Utils/MacDarkMode.mm
+ Utils/MacUtils.mm
GUI/RemovableDriveManagerMM.mm
GUI/RemovableDriveManagerMM.h
GUI/Mouse3DHandlerMac.mm
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index 7824abf454..14a37d7ef5 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -131,11 +131,7 @@ void Bed3D::Axes::render()
if (!m_arrow.is_initialized())
m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -634,11 +630,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
#if ENABLE_LEGACY_OPENGL_REMOVAL
init_triangles();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("printbed");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -762,11 +754,7 @@ void Bed3D::render_model()
}
if (!m_model.get_filename().empty()) {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
shader->set_uniform("emission_factor", 0.0f);
@@ -830,11 +818,7 @@ void Bed3D::render_default(bool bottom, bool picking)
init_gridlines();
init_triangles();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 50e488686e..c9fb05439e 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -1085,14 +1085,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
return;
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat_attr");
- GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat_attr");
- assert(boost::algorithm::iends_with(shader->get_name(), "_attr"));
-#else
GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat");
GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
if (type == ERenderType::Transparent) {
diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp
index 44b0cd84a1..1370484c3d 100644
--- a/src/slic3r/GUI/Camera.cpp
+++ b/src/slic3r/GUI/Camera.cpp
@@ -106,26 +106,36 @@ double Camera::get_fov() const
void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h)
{
glsafe(::glViewport(0, 0, w, h));
+#if ENABLE_LEGACY_OPENGL_REMOVAL
+ m_viewport = { 0, 0, int(w), int(h) };
+#else
glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data()));
+#endif // ENABLE_LEGACY_OPENGL_REMOVAL
}
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
void Camera::apply_view_matrix()
{
glsafe(::glMatrixMode(GL_MODELVIEW));
glsafe(::glLoadIdentity());
glsafe(::glMultMatrixd(m_view_matrix.data()));
}
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z)
{
double w = 0.0;
double h = 0.0;
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
const double old_distance = m_distance;
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
if (m_distance != old_distance)
// the camera has been moved re-apply view matrix
apply_view_matrix();
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
if (near_z > 0.0)
m_frustrum_zs.first = std::max(std::min(m_frustrum_zs.first, near_z), FrustrumMinNearZ);
@@ -159,6 +169,35 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
}
}
+#if ENABLE_LEGACY_OPENGL_REMOVAL
+ switch (m_type)
+ {
+ default:
+ case EType::Ortho:
+ {
+ const double dz = m_frustrum_zs.second - m_frustrum_zs.first;
+ const double zz = m_frustrum_zs.first + m_frustrum_zs.second;
+ m_projection_matrix.matrix() << 1.0 / w, 0.0, 0.0, 0.0,
+ 0.0, 1.0 / h, 0.0, 0.0,
+ 0.0, 0.0, -2.0 / dz, -zz / dz,
+ 0.0, 0.0, 0.0, 1.0;
+ break;
+ }
+ case EType::Perspective:
+ {
+ const double n = m_frustrum_zs.first;
+ const double f = m_frustrum_zs.second;
+ const double dz = f - n;
+ const double zz = n + f;
+ const double fn = n * f;
+ m_projection_matrix.matrix() << n / w, 0.0, 0.0, 0.0,
+ 0.0, n / h, 0.0, 0.0,
+ 0.0, 0.0, -zz / dz, -2.0 * fn / dz,
+ 0.0, 0.0, -1.0, 0.0;
+ break;
+ }
+ }
+#else
glsafe(::glMatrixMode(GL_PROJECTION));
glsafe(::glLoadIdentity());
@@ -179,6 +218,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
glsafe(::glGetDoublev(GL_PROJECTION_MATRIX, m_projection_matrix.data()));
glsafe(::glMatrixMode(GL_MODELVIEW));
+#endif // ENABLE_LEGACY_OPENGL_REMOVAL
}
void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor)
@@ -298,8 +338,8 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo
// box in eye space
const BoundingBoxf3 eye_box = box.transformed(m_view_matrix);
- near_z = -eye_box.max(2);
- far_z = -eye_box.min(2);
+ near_z = -eye_box.max.z();
+ far_z = -eye_box.min.z();
// apply margin
near_z -= FrustrumZMargin;
@@ -465,19 +505,19 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up
m_distance = (position - target).norm();
const Vec3d new_position = m_target + m_distance * unit_z;
- m_view_matrix(0, 0) = unit_x(0);
- m_view_matrix(0, 1) = unit_x(1);
- m_view_matrix(0, 2) = unit_x(2);
+ m_view_matrix(0, 0) = unit_x.x();
+ m_view_matrix(0, 1) = unit_x.y();
+ m_view_matrix(0, 2) = unit_x.z();
m_view_matrix(0, 3) = -unit_x.dot(new_position);
- m_view_matrix(1, 0) = unit_y(0);
- m_view_matrix(1, 1) = unit_y(1);
- m_view_matrix(1, 2) = unit_y(2);
+ m_view_matrix(1, 0) = unit_y.x();
+ m_view_matrix(1, 1) = unit_y.y();
+ m_view_matrix(1, 2) = unit_y.z();
m_view_matrix(1, 3) = -unit_y.dot(new_position);
- m_view_matrix(2, 0) = unit_z(0);
- m_view_matrix(2, 1) = unit_z(1);
- m_view_matrix(2, 2) = unit_z(2);
+ m_view_matrix(2, 0) = unit_z.x();
+ m_view_matrix(2, 1) = unit_z.y();
+ m_view_matrix(2, 2) = unit_z.z();
m_view_matrix(2, 3) = -unit_z.dot(new_position);
m_view_matrix(3, 0) = 0.0;
diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp
index a61eb44ec5..a1d7426882 100644
--- a/src/slic3r/GUI/Camera.hpp
+++ b/src/slic3r/GUI/Camera.hpp
@@ -92,7 +92,9 @@ public:
double get_fov() const;
void apply_viewport(int x, int y, unsigned int w, unsigned int h);
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
void apply_view_matrix();
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
// Calculates and applies the projection matrix tighting the frustrum z range around the given box.
// If larger z span is needed, pass the desired values of near and far z (negative values are ignored)
void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0);
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index d33004f494..c2dd89c159 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -184,11 +184,7 @@ void GCodeViewer::COG::render()
init();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -331,11 +327,7 @@ void GCodeViewer::SequentialView::Marker::render()
if (!m_visible)
return;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -703,11 +695,7 @@ void GCodeViewer::init()
#if !DISABLE_GCODEVIEWER_INSTANCED_MODELS
if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- buffer.shader = "gouraud_light_instanced_attr";
-#else
buffer.shader = "gouraud_light_instanced";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
buffer.model.model.init_from(diamond(16));
buffer.model.color = option_color(type);
buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel;
@@ -716,12 +704,7 @@ void GCodeViewer::init()
#endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- buffer.shader = "gouraud_light_attr";
-#else
buffer.shader = "gouraud_light";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
-
buffer.model.data = diamond(16);
buffer.model.color = option_color(type);
buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel;
@@ -734,18 +717,14 @@ void GCodeViewer::init()
case EMoveType::Extrude: {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle;
buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- buffer.shader = "gouraud_light_attr";
-#else
buffer.shader = "gouraud_light";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
break;
}
case EMoveType::Travel: {
buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line;
#if ENABLE_GL_SHADERS_ATTRIBUTES
buffer.vertices.format = VBuffer::EFormat::Position;
- buffer.shader = "flat_attr";
+ buffer.shader = "flat";
#else
buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
buffer.shader = "toolpaths_lines";
@@ -2284,13 +2263,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
size_t move_id = i - seams_count;
if (move.type == EMoveType::Extrude) {
- // layers zs
- const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
- const double z = static_cast(move.position.z());
- if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
- m_layers.append(z, { last_travel_s_id, move_id });
- else
- m_layers.get_ranges().back().last = move_id;
+#if ENABLE_PROCESS_G2_G3_LINES
+ if (move.extrusion_role != erNone && !move.internal_only) {
+#endif // ENABLE_PROCESS_G2_G3_LINES
+ // layers zs
+ const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
+ const double z = static_cast(move.position.z());
+ if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
+ m_layers.append(z, { last_travel_s_id, move_id });
+ else
+ m_layers.get_ranges().back().last = move_id;
+#if ENABLE_PROCESS_G2_G3_LINES
+ }
+#endif // ENABLE_PROCESS_G2_G3_LINES
// extruder ids
m_extruder_ids.emplace_back(move.extruder_id);
// roles
@@ -2313,7 +2298,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
sort_remove_duplicates(m_extruder_ids);
m_extruder_ids.shrink_to_fit();
-#if ENABLE_SPIRAL_VASE_LAYERS
// replace layers for spiral vase mode
if (!gcode_result.spiral_vase_layers.empty()) {
m_layers.reset();
@@ -2321,7 +2305,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
m_layers.append(layer.first, { layer.second.first, layer.second.second });
}
}
-#endif // ENABLE_SPIRAL_VASE_LAYERS
// set layers z range
if (!m_layers.empty())
@@ -3163,11 +3146,8 @@ void GCodeViewer::render_toolpaths()
const int position_id = shader->get_attrib_location("v_position");
const int normal_id = shader->get_attrib_location("v_normal");
#else
- switch (buffer.render_primitive_type) {
- case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break;
- case TBuffer::ERenderPrimitiveType::Line: shader_init_as_lines(*shader); break;
- default: break;
- }
+ if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Line)
+ shader_init_as_lines(*shader);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
const int uniform_color = shader->get_uniform_location("uniform_color");
@@ -3324,11 +3304,7 @@ void GCodeViewer::render_shells()
if (!m_shells.visible || m_shells.volumes.empty())
return;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index ea08f98711..6535be25cb 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -161,11 +161,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
bool GLCanvas3D::LayersEditing::is_allowed() const
{
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- return wxGetApp().get_shader("variable_layer_height_attr") != nullptr && m_z_texture_id > 0;
-#else
return wxGetApp().get_shader("variable_layer_height") != nullptr && m_z_texture_id > 0;
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
}
bool GLCanvas3D::LayersEditing::is_enabled() const
@@ -328,11 +324,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas)
bool GLCanvas3D::LayersEditing::is_initialized() const
{
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- return wxGetApp().get_shader("variable_layer_height_attr") != nullptr;
-#else
return wxGetApp().get_shader("variable_layer_height") != nullptr;
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
}
std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) const
@@ -375,11 +367,8 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3
return;
const float cnv_inv_width = 1.0f / cnv_width;
-
- GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
-#else
- GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
+ GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
if (shader == nullptr)
return;
@@ -550,11 +539,7 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect)
m_profile.profile.init_from(std::move(init_data));
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -594,11 +579,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
if (current_shader != nullptr)
current_shader->stop_using();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -1075,11 +1056,7 @@ void GLCanvas3D::SequentialPrintClearance::render()
const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -1685,13 +1662,17 @@ void GLCanvas3D::render()
camera.requires_zoom_to_bed = false;
}
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
camera.apply_view_matrix();
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
camera.apply_projection(_max_bounding_box(true, true));
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam));
GLfloat position_top[4] = { -0.5f, -0.5f, 1.0f, 0.0f };
glsafe(::glLightfv(GL_LIGHT0, GL_POSITION, position_top));
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
wxGetApp().imgui()->new_frame();
@@ -2232,7 +2213,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
if (state.step[istep].state == PrintStateBase::DONE) {
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
assert(! mesh.empty());
- mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
+
+ // sla_trafo does not contain volume trafo. To get a mesh to create
+ // a new volume from, we have to apply vol trafo inverse separately.
+ const ModelObject& mo = *m_model->objects[volume.object_idx()];
+ Transform3d trafo = sla_print->sla_trafo(mo)
+ * mo.volumes.front()->get_transformation().get_matrix();
+ mesh.transform(trafo.inverse());
#if ENABLE_SMOOTH_NORMALS
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.init_from(mesh, true);
@@ -3451,6 +3438,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#endif // !ENABLE_NEW_RECTANGLE_SELECTION
else {
#if ENABLE_NEW_RECTANGLE_SELECTION
+ const bool rectangle_selection_dragging = m_rectangle_selection.is_dragging();
if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports &&
m_gizmos.get_current_type() != GLGizmosManager::FdmSupports &&
@@ -3467,8 +3455,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// during the scene manipulation.
#if ENABLE_NEW_RECTANGLE_SELECTION
- if (m_picking_enabled && (!any_gizmo_active || !evt.ShiftDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) &&
- !m_rectangle_selection.is_dragging()) {
+ if (m_picking_enabled && !any_gizmo_active && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && !rectangle_selection_dragging) {
#else
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION
@@ -3612,9 +3599,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
// do not process the dragging if the left mouse was set down in another canvas
#if ENABLE_NEW_CAMERA_MOVEMENTS
- else if (evt.LeftIsDown() || evt.MiddleIsDown()) {
+ else if (evt.LeftIsDown()) {
// if dragging over blank area with left button, rotate
- if ((any_gizmo_active || evt.CmdDown() || evt.MiddleIsDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
+ if ((any_gizmo_active || evt.CmdDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
#else
// if dragging over blank area with left button, rotate
else if (evt.LeftIsDown()) {
@@ -3638,13 +3625,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
m_mouse.drag.start_position_3D = Vec3d((double)pos.x(), (double)pos.y(), 0.0);
}
-#if ENABLE_NEW_CAMERA_MOVEMENTS
- else if (evt.RightIsDown()) {
- // If dragging with right button, pan.
-#else
else if (evt.MiddleIsDown() || evt.RightIsDown()) {
- // If dragging over blank area with right button, pan.
-#endif // ENABLE_NEW_CAMERA_MOVEMENTS
+ // If dragging over blank area with right/middle button, pan.
if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0
float z = 0.0f;
@@ -4578,7 +4560,9 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
camera.set_scene_box(scene_bounding_box());
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
camera.zoom_to_box(volumes_box);
+#if !ENABLE_LEGACY_OPENGL_REMOVAL
camera.apply_view_matrix();
+#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Transform3d& view_matrix = camera.get_view_matrix();
@@ -4602,11 +4586,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
camera.apply_projection(volumes_box, near_z, far_z);
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -5545,11 +5525,7 @@ void GLCanvas3D::_render_background()
m_background.init_from(std::move(init_data));
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("background_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("background");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
shader->set_uniform("top_color", use_error_color ? ERROR_BG_LIGHT_COLOR : DEFAULT_BG_LIGHT_COLOR);
@@ -5675,11 +5651,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type)
m_volumes.set_show_non_manifold_edges(!m_gizmos.is_hiding_instances() && m_gizmos.get_current_type() != GLGizmosManager::Simplify);
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
@@ -5904,11 +5876,7 @@ void GLCanvas3D::_render_overlays()
void GLCanvas3D::_render_volumes_for_picking() const
{
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -6097,50 +6065,45 @@ void GLCanvas3D::_render_camera_target()
#if ENABLE_LEGACY_OPENGL_REMOVAL
const Vec3f& target = wxGetApp().plater()->get_camera().get_target().cast();
- bool target_changed = !m_camera_target.target.isApprox(target.cast());
m_camera_target.target = target.cast();
for (int i = 0; i < 3; ++i) {
- if (!m_camera_target.axis[i].is_initialized() || target_changed) {
+ if (!m_camera_target.axis[i].is_initialized()) {
m_camera_target.axis[i].reset();
GLModel::Geometry init_data;
- init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
+ init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.color = (i == X) ? ColorRGBA::X() : ((i == Y) ? ColorRGBA::Y() : ColorRGBA::Z());
init_data.reserve_vertices(2);
init_data.reserve_indices(2);
// vertices
if (i == X) {
- init_data.add_vertex(Vec3f(target.x() - half_length, target.y(), target.z()));
- init_data.add_vertex(Vec3f(target.x() + half_length, target.y(), target.z()));
+ init_data.add_vertex(Vec3f(-half_length, 0.0f, 0.0f));
+ init_data.add_vertex(Vec3f(+half_length, 0.0f, 0.0f));
}
else if (i == Y) {
- init_data.add_vertex(Vec3f(target.x(), target.y() - half_length, target.z()));
- init_data.add_vertex(Vec3f(target.x(), target.y() + half_length, target.z()));
+ init_data.add_vertex(Vec3f(0.0f, -half_length, 0.0f));
+ init_data.add_vertex(Vec3f(0.0f, +half_length, 0.0f));
}
else {
- init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() - half_length));
- init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() + half_length));
+ init_data.add_vertex(Vec3f(0.0f, 0.0f, -half_length));
+ init_data.add_vertex(Vec3f(0.0f, 0.0f, +half_length));
}
// indices
- init_data.add_ushort_line(0, 1);
+ init_data.add_line(0, 1);
m_camera_target.axis[i].init_from(std::move(init_data));
}
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
- shader->set_uniform("view_model_matrix", camera.get_view_matrix());
+ shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_camera_target.target));
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
for (int i = 0; i < 3; ++i) {
@@ -6316,11 +6279,7 @@ void GLCanvas3D::_render_sla_slices()
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp
index b81287ecee..75998609be 100644
--- a/src/slic3r/GUI/GLModel.cpp
+++ b/src/slic3r/GUI/GLModel.cpp
@@ -861,7 +861,7 @@ void GLModel::render(const std::pair& range)
#if ENABLE_GL_SHADERS_ATTRIBUTES
position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
- glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format)));
+ glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(position_id));
}
#else
@@ -873,7 +873,7 @@ void GLModel::render(const std::pair& range)
#if ENABLE_GL_SHADERS_ATTRIBUTES
normal_id = shader->get_attrib_location("v_normal");
if (normal_id != -1) {
- glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format)));
+ glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(normal_id));
}
#else
@@ -885,7 +885,7 @@ void GLModel::render(const std::pair& range)
#if ENABLE_GL_SHADERS_ATTRIBUTES
tex_coord_id = shader->get_attrib_location("v_tex_coord");
if (tex_coord_id != -1) {
- glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::tex_coord_offset_bytes(data.format)));
+ glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::tex_coord_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(tex_coord_id));
}
#else
@@ -930,16 +930,12 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
{
- if (instances_vbo == 0)
+ if (instances_vbo == 0 || instances_count == 0)
return;
GLShaderProgram* shader = wxGetApp().get_current_shader();
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced_attr"))
-#else
if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced"))
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
return;
// vertex attributes
@@ -974,11 +970,12 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo));
#if ENABLE_LEGACY_OPENGL_REMOVAL
- glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0));
+ const size_t instance_stride = 5 * sizeof(float);
+ glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, instance_stride, (const void*)0));
glsafe(::glEnableVertexAttribArray(offset_id));
glsafe(::glVertexAttribDivisor(offset_id, 1));
- glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)(3 * sizeof(float))));
+ glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, instance_stride, (const void*)(3 * sizeof(float))));
glsafe(::glEnableVertexAttribArray(scales_id));
glsafe(::glVertexAttribDivisor(scales_id, 1));
#else
@@ -1000,8 +997,6 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
const GLenum mode = get_primitive_mode(data.format);
const GLenum index_type = get_index_type(data);
- shader->set_uniform("uniform_color", data.color);
-
const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format);
const bool position = Geometry::has_position(data.format);
const bool normal = Geometry::has_normal(data.format);
@@ -1009,15 +1004,17 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id));
if (position) {
- glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format)));
+ glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(position_id));
}
if (normal) {
- glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format)));
+ glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(normal_id));
}
+ shader->set_uniform("uniform_color", data.color);
+
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
glsafe(::glDrawElementsInstanced(mode, indices_count(), index_type, (const void*)0, instances_count));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
@@ -1133,6 +1130,7 @@ bool GLModel::send_to_gpu()
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
else {
+ data.index_type = Geometry::EIndexType::UINT;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp
index 19327b33a7..a8be0f84e2 100644
--- a/src/slic3r/GUI/GLSelectionRectangle.cpp
+++ b/src/slic3r/GUI/GLSelectionRectangle.cpp
@@ -131,11 +131,7 @@ namespace GUI {
glsafe(::glEnable(GL_LINE_STIPPLE));
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp
index 9f0b03ea0e..ab8dfb3e77 100644
--- a/src/slic3r/GUI/GLShadersManager.cpp
+++ b/src/slic3r/GUI/GLShadersManager.cpp
@@ -35,14 +35,15 @@ std::pair GLShadersManager::init()
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
+ const std::string prefix = GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/";
// imgui shader
- valid &= append_shader("imgui", { "imgui.vs", "imgui.fs" });
+ valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" });
// basic shader, used to render all what was previously rendered using the immediate mode
- valid &= append_shader("flat_attr", { "flat_attr.vs", "flat.fs" });
+ valid &= append_shader("flat", { prefix + "flat.vs", prefix + "flat.fs" });
// basic shader for textures, used to render textures
- valid &= append_shader("flat_texture_attr", { "flat_texture_attr.vs", "flat_texture.fs" });
+ valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" });
// used to render 3D scene background
- valid &= append_shader("background_attr", { "background_attr.vs", "background.fs" });
+ valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" });
#else
// basic shader, used to render all what was previously rendered using the immediate mode
valid &= append_shader("flat", { "flat.vs", "flat.fs" });
@@ -55,16 +56,16 @@ std::pair GLShadersManager::init()
#if ENABLE_SHOW_TOOLPATHS_COG
// used to render toolpaths center of gravity
#if ENABLE_GL_SHADERS_ATTRIBUTES
- valid &= append_shader("toolpaths_cog_attr", { "toolpaths_cog_attr.vs", "toolpaths_cog.fs" });
+ valid &= append_shader("toolpaths_cog", { prefix + "toolpaths_cog.vs", prefix + "toolpaths_cog.fs" });
#else
valid &= append_shader("toolpaths_cog", { "toolpaths_cog.vs", "toolpaths_cog.fs" });
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#endif // ENABLE_SHOW_TOOLPATHS_COG
#if ENABLE_GL_SHADERS_ATTRIBUTES
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
- valid &= append_shader("gouraud_light_attr", { "gouraud_light_attr.vs", "gouraud_light.fs" });
+ valid &= append_shader("gouraud_light", { prefix + "gouraud_light.vs", prefix + "gouraud_light.fs" });
// used to render printbed
- valid &= append_shader("printbed_attr", { "printbed_attr.vs", "printbed.fs" });
+ valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" });
#else
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" });
@@ -74,14 +75,14 @@ std::pair GLShadersManager::init()
// used to render options in gcode preview
if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
#if ENABLE_GL_SHADERS_ATTRIBUTES
- valid &= append_shader("gouraud_light_instanced_attr", { "gouraud_light_instanced_attr.vs", "gouraud_light_instanced.fs" });
+ valid &= append_shader("gouraud_light_instanced", { prefix + "gouraud_light_instanced.vs", prefix + "gouraud_light_instanced.fs" });
#else
valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" });
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
}
#if ENABLE_GL_SHADERS_ATTRIBUTES
// used to render objects in 3d editor
- valid &= append_shader("gouraud_attr", { "gouraud_attr.vs", "gouraud.fs" }
+ valid &= append_shader("gouraud", { prefix + "gouraud.vs", prefix + "gouraud.fs" }
#else
// used to render extrusion and travel paths as lines in gcode preview
valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" });
@@ -94,9 +95,9 @@ std::pair GLShadersManager::init()
);
#if ENABLE_GL_SHADERS_ATTRIBUTES
// used to render variable layers heights in 3d editor
- valid &= append_shader("variable_layer_height_attr", { "variable_layer_height_attr.vs", "variable_layer_height.fs" });
+ valid &= append_shader("variable_layer_height", { prefix + "variable_layer_height.vs", prefix + "variable_layer_height.fs" });
// used to render highlight contour around selected triangles inside the multi-material gizmo
- valid &= append_shader("mm_contour_attr", { "mm_contour_attr.vs", "mm_contour_attr.fs" });
+ valid &= append_shader("mm_contour", { prefix + "mm_contour.vs", prefix + "mm_contour.fs" });
#else
// used to render variable layers heights in 3d editor
valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" });
@@ -111,9 +112,9 @@ std::pair GLShadersManager::init()
// triangle normals inside fragment shader have the right direction.
#if ENABLE_GL_SHADERS_ATTRIBUTES
if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
- valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" }, { "FLIP_TRIANGLE_NORMALS"sv });
+ valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" }, { "FLIP_TRIANGLE_NORMALS"sv });
else
- valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" });
+ valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" });
#else
if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index 064ca1a18b..137a0a1096 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -358,11 +358,7 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
GLModel model;
model.init_from(std::move(init_data));
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_texture_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat_texture");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp
index a0b674e27e..72b8283074 100644
--- a/src/slic3r/GUI/GUI.cpp
+++ b/src/slic3r/GUI/GUI.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#if __APPLE__
#import
@@ -476,50 +477,135 @@ void about()
void desktop_open_datadir_folder()
{
+ boost::filesystem::path path(data_dir());
+ desktop_open_folder(std::move(path));
+}
+
+void desktop_open_folder(const boost::filesystem::path& path)
+{
+ if (!boost::filesystem::is_directory(path))
+ return;
+
// Execute command to open a file explorer, platform dependent.
- // FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade.
-
- const auto path = data_dir();
#ifdef _WIN32
- const wxString widepath = from_u8(path);
- const wchar_t *argv[] = { L"explorer", widepath.GetData(), nullptr };
- ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr);
+ const wxString widepath = path.wstring();
+ const wchar_t* argv[] = { L"explorer", widepath.GetData(), nullptr };
+ ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr);
#elif __APPLE__
- const char *argv[] = { "open", path.data(), nullptr };
- ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr);
+ const char* argv[] = { "open", path.string().c_str(), nullptr };
+ ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr);
#else
- const char *argv[] = { "xdg-open", path.data(), nullptr };
-
- // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
- // because they may mess up the environment expected by the file manager.
- // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
- if (wxGetEnv("APPIMAGE", nullptr)) {
- // We're running from AppImage
- wxEnvVariableHashMap env_vars;
- wxGetEnvMap(&env_vars);
-
- env_vars.erase("APPIMAGE");
- env_vars.erase("APPDIR");
- env_vars.erase("LD_LIBRARY_PATH");
- env_vars.erase("LD_PRELOAD");
- env_vars.erase("UNION_PRELOAD");
-
- wxExecuteEnv exec_env;
- exec_env.env = std::move(env_vars);
-
- wxString owd;
- if (wxGetEnv("OWD", &owd)) {
- // This is the original work directory from which the AppImage image was run,
- // set it as CWD for the child process:
- exec_env.cwd = std::move(owd);
- }
-
- ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env);
- } else {
- // Looks like we're NOT running from AppImage, we'll make no changes to the environment.
- ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr);
- }
+ const char* argv[] = { "xdg-open", path.string().c_str(), nullptr };
+ desktop_execute(argv);
#endif
}
-} }
+#ifdef __linux__
+namespace {
+wxExecuteEnv get_appimage_exec_env()
+{
+ // If we're running in an AppImage container, we need to remove AppImage's env vars,
+ // because they may mess up the environment expected by the file manager.
+ // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
+ wxEnvVariableHashMap env_vars;
+ wxGetEnvMap(&env_vars);
+
+ env_vars.erase("APPIMAGE");
+ env_vars.erase("APPDIR");
+ env_vars.erase("LD_LIBRARY_PATH");
+ env_vars.erase("LD_PRELOAD");
+ env_vars.erase("UNION_PRELOAD");
+
+ wxExecuteEnv exec_env;
+ exec_env.env = std::move(env_vars);
+
+ wxString owd;
+ if (wxGetEnv("OWD", &owd)) {
+ // This is the original work directory from which the AppImage image was run,
+ // set it as CWD for the child process:
+ exec_env.cwd = std::move(owd);
+ }
+ return exec_env;
+}
+} // namespace
+void desktop_execute(const char* argv[])
+{
+ if (sizeof(argv) == 0)
+ return;
+
+ // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
+ // because they may mess up the environment expected by the file manager.
+ // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
+ if (wxGetEnv("APPIMAGE", nullptr)) {
+ // We're running from AppImage
+ wxExecuteEnv exec_env = get_appimage_exec_env();
+ ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env);
+ }
+ else {
+ // Looks like we're NOT running from AppImage, we'll make no changes to the environment.
+ ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr);
+ }
+}
+void desktop_execute_get_result(wxString command, wxArrayString& output)
+{
+ output.Clear();
+ //Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
+ // because they may mess up the environment expected by the file manager.
+ // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
+ if (wxGetEnv("APPIMAGE", nullptr)) {
+ // We're running from AppImage
+ wxExecuteEnv exec_env = get_appimage_exec_env();
+ ::wxExecute(command, output, 0, &exec_env);
+ } else {
+ // Looks like we're NOT running from AppImage, we'll make no changes to the environment.
+ ::wxExecute(command, output);
+ }
+}
+#endif // __linux__
+
+#ifdef _WIN32
+bool create_process(const boost::filesystem::path& path, const std::wstring& cmd_opt, std::string& error_msg)
+{
+ // find updater exe
+ if (boost::filesystem::exists(path)) {
+ // Using quoted string as mentioned in CreateProcessW docs.
+ std::wstring wcmd = L"\"" + path.wstring() + L"\"";
+ if (!cmd_opt.empty())
+ wcmd += L" " + cmd_opt;
+
+ // additional information
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+
+ // set the size of the structures
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
+
+ // start the program up
+ if (CreateProcessW(NULL, // the path
+ wcmd.data(), // Command line
+ NULL, // Process handle not inheritable
+ NULL, // Thread handle not inheritable
+ FALSE, // Set handle inheritance to FALSE
+ 0, // No creation flags
+ NULL, // Use parent's environment block
+ NULL, // Use parent's starting directory
+ &si, // Pointer to STARTUPINFO structure
+ &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
+ )) {
+ // Close process and thread handles.
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return true;
+ }
+ else
+ error_msg = "CreateProcessW failed to create process " + boost::nowide::narrow(path.wstring());
+ }
+ else
+ error_msg = "Executable doesn't exists. Path: " + boost::nowide::narrow(path.wstring());
+ return false;
+}
+#endif //_WIN32
+
+} } // namespaces GUI / Slic3r
diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp
index 20c8828785..cb7cf54874 100644
--- a/src/slic3r/GUI/GUI.hpp
+++ b/src/slic3r/GUI/GUI.hpp
@@ -13,6 +13,7 @@ class wxWindow;
class wxMenuBar;
class wxComboCtrl;
class wxFileDialog;
+class wxArrayString;
class wxTopLevelWindow;
namespace Slic3r {
@@ -80,6 +81,24 @@ boost::filesystem::path into_path(const wxString &str);
extern void about();
// Ask the destop to open the datadir using the default file explorer.
extern void desktop_open_datadir_folder();
+// Ask the destop to open the directory specified by path using the default file explorer.
+void desktop_open_folder(const boost::filesystem::path& path);
+
+#ifdef __linux__
+// Calling wxExecute on Linux with proper handling of AppImage's env vars.
+// argv example: { "xdg-open", path.c_str(), nullptr }
+void desktop_execute(const char* argv[]);
+void desktop_execute_get_result(wxString command, wxArrayString& output);
+#endif // __linux__
+
+#ifdef _WIN32
+// Call CreateProcessW to start external proccess on path
+// returns true on success
+// path should contain path to the process
+// cmd_opt can be empty or contain command line options. Example: L"/silent"
+// error_msg will contain error message if create_process return false
+bool create_process(const boost::filesystem::path& path, const std::wstring& cmd_opt, std::string& error_msg);
+#endif //_WIN32
} // namespace GUI
} // namespace Slic3r
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 87913fb812..76f321d893 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -57,6 +57,7 @@
#include "../Utils/PrintHost.hpp"
#include "../Utils/Process.hpp"
#include "../Utils/MacDarkMode.hpp"
+#include "../Utils/AppUpdater.hpp"
#include "slic3r/Config/Snapshot.hpp"
#include "ConfigSnapshotDialog.hpp"
#include "FirmwareDialog.hpp"
@@ -430,50 +431,21 @@ bool static check_old_linux_datadir(const wxString& app_name) {
}
#endif
-
#ifdef _WIN32
+#if 0 // External Updater is replaced with AppUpdater.cpp
static bool run_updater_win()
{
// find updater exe
boost::filesystem::path path_updater = boost::dll::program_location().parent_path() / "prusaslicer-updater.exe";
- if (boost::filesystem::exists(path_updater)) {
- // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst
-
- // Using quoted string as mentioned in CreateProcessW docs, silent execution parameter.
- std::wstring wcmd = L"\"" + path_updater.wstring() + L"\" /silent";
-
- // additional information
- STARTUPINFOW si;
- PROCESS_INFORMATION pi;
-
- // set the size of the structures
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
- ZeroMemory(&pi, sizeof(pi));
-
- // start the program up
- if (CreateProcessW(NULL, // the path
- wcmd.data(), // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- FALSE, // Set handle inheritance to FALSE
- 0, // No creation flags
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &si, // Pointer to STARTUPINFO structure
- &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
- )) {
- // Close process and thread handles.
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return true;
- } else {
- BOOST_LOG_TRIVIAL(error) << "Failed to start prusaslicer-updater.exe with command " << wcmd;
- }
- }
- return false;
+ // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst
+ std::string msg;
+ bool res = create_process(path_updater, L"/silent", msg);
+ if (!res)
+ BOOST_LOG_TRIVIAL(error) << msg;
+ return res;
}
-#endif //_WIN32
+#endif // 0
+#endif // _WIN32
struct FileWildcards {
std::string_view title;
@@ -499,6 +471,44 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
/* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv, ".pwmx"sv } },
};
+#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
+wxString file_wildcards(FileType file_type)
+{
+ const FileWildcards& data = file_wildcards_by_type[file_type];
+ std::string title;
+ std::string mask;
+
+ // Generate cumulative first item
+ for (const std::string_view& ext : data.file_extensions) {
+ if (title.empty()) {
+ title = "*";
+ title += ext;
+ mask = title;
+ }
+ else {
+ title += ", *";
+ title += ext;
+ mask += ";*";
+ mask += ext;
+ }
+ mask += ";*";
+ mask += boost::to_upper_copy(std::string(ext));
+ }
+
+ wxString ret = GUI::format_wxstr("%s (%s)|%s", data.title, title, mask);
+
+ // Adds an item for each of the extensions
+ if (data.file_extensions.size() > 1) {
+ for (const std::string_view& ext : data.file_extensions) {
+ title = "*";
+ title += ext;
+ ret += GUI::format_wxstr("|%s (%s)|%s", data.title, title, title);
+ }
+ }
+
+ return ret;
+}
+#else
// This function produces a Win32 file dialog file template mask to be consumed by wxWidgets on all platforms.
// The function accepts a custom extension parameter. If the parameter is provided, the custom extension
// will be added as a fist to the list. This is important for a "file save" dialog on OSX, which strips
@@ -551,8 +561,10 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
mask += ";*";
mask += boost::to_upper_copy(std::string(ext));
}
+
return GUI::format_wxstr("%s (%s)|%s", data.title, title, mask);
}
+#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
@@ -776,18 +788,13 @@ void GUI_App::post_init()
CallAfter([this] {
bool cw_showed = this->config_wizard_startup();
this->preset_updater->sync(preset_bundle);
+ this->app_version_check(false);
if (! cw_showed) {
// The CallAfter is needed as well, without it, GL extensions did not show.
// Also, we only want to show this when the wizard does not, so the new user
// sees something else than "we want something" on the first start.
show_send_system_info_dialog_if_needed();
}
- #ifdef _WIN32
- // Run external updater on Windows if version check is enabled.
- if (this->preset_updater->version_check_enabled() && ! run_updater_win())
- // "prusaslicer-updater.exe" was not started, run our own update check.
- #endif // _WIN32
- this->preset_updater->slic3r_update_notify();
});
}
@@ -813,6 +820,8 @@ GUI_App::GUI_App(EAppMode mode)
{
//app config initializes early becasuse it is used in instance checking in PrusaSlicer.cpp
this->init_app_config();
+ // init app downloader after path to datadir is set
+ m_app_updater = std::make_unique();
}
GUI_App::~GUI_App()
@@ -1202,23 +1211,8 @@ bool GUI_App::on_init_inner()
#endif // __WXMSW__
preset_updater = new PresetUpdater();
- Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
- app_config->set("version_online", into_u8(evt.GetString()));
- app_config->save();
- std::string opt = app_config->get("notify_release");
- if (this->plater_ != nullptr && (opt == "all" || opt == "release")) {
- if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
- this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable
- , NotificationManager::NotificationLevel::ImportantNotificationLevel
- , Slic3r::format(_u8L("New release version %1% is available."), evt.GetString())
- , _u8L("See Download page.")
- , [](wxEvtHandler* evnthndlr) {wxGetApp().open_web_page_localized("https://www.prusa3d.com/slicerweb"); return true; }
- );
- }
- }
- });
+ Bind(EVT_SLIC3R_VERSION_ONLINE, &GUI_App::on_version_read, this);
Bind(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
- app_config->save();
if (this->plater_ != nullptr && app_config->get("notify_release") == "all") {
std::string evt_string = into_u8(evt.GetString());
if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(evt_string)) {
@@ -1232,6 +1226,22 @@ bool GUI_App::on_init_inner()
}
}
});
+ Bind(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, [this](const wxCommandEvent& evt) {
+ //lm:This does not force a render. The progress bar only updateswhen the mouse is moved.
+ if (this->plater_ != nullptr)
+ this->plater_->get_notification_manager()->set_download_progress_percentage((float)std::stoi(into_u8(evt.GetString())) / 100.f );
+ });
+
+ Bind(EVT_SLIC3R_APP_DOWNLOAD_FAILED, [this](const wxCommandEvent& evt) {
+ if (this->plater_ != nullptr)
+ this->plater_->get_notification_manager()->close_notification_of_type(NotificationType::AppDownload);
+ if(!evt.GetString().IsEmpty())
+ show_error(nullptr, evt.GetString());
+ });
+
+ Bind(EVT_SLIC3R_APP_OPEN_FAILED, [](const wxCommandEvent& evt) {
+ show_error(nullptr, evt.GetString());
+ });
}
else {
#ifdef __WXMSW__
@@ -2242,7 +2252,8 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
local_menu->Append(config_id_base + ConfigMenuSnapshots, _L("&Configuration Snapshots") + dots, _L("Inspect / activate configuration snapshots"));
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot"));
- local_menu->Append(config_id_base + ConfigMenuUpdate, _L("Check for Configuration Updates"), _L("Check for configuration updates"));
+ local_menu->Append(config_id_base + ConfigMenuUpdateConf, _L("Check for Configuration Updates"), _L("Check for configuration updates"));
+ local_menu->Append(config_id_base + ConfigMenuUpdateApp, _L("Check for Application Updates"), _L("Check for new version of application"));
#if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
//if (DesktopIntegrationDialog::integration_possible())
local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration"));
@@ -2284,9 +2295,12 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
case ConfigMenuWizard:
run_wizard(ConfigWizard::RR_USER);
break;
- case ConfigMenuUpdate:
+ case ConfigMenuUpdateConf:
check_updates(true);
break;
+ case ConfigMenuUpdateApp:
+ app_version_check(true);
+ break;
#ifdef __linux__
case ConfigMenuDesktopIntegration:
show_desktop_integration_dialog();
@@ -3226,5 +3240,87 @@ void GUI_App::associate_gcode_files()
}
#endif // __WXMSW__
+
+void GUI_App::on_version_read(wxCommandEvent& evt)
+{
+ app_config->set("version_online", into_u8(evt.GetString()));
+ app_config->save();
+ std::string opt = app_config->get("notify_release");
+ if (this->plater_ == nullptr || (opt != "all" && opt != "release")) {
+ return;
+ }
+ if (*Semver::parse(SLIC3R_VERSION) >= *Semver::parse(into_u8(evt.GetString()))) {
+ return;
+ }
+ // notification
+ /*
+ this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable
+ , NotificationManager::NotificationLevel::ImportantNotificationLevel
+ , Slic3r::format(_u8L("New release version %1% is available."), evt.GetString())
+ , _u8L("See Download page.")
+ , [](wxEvtHandler* evnthndlr) {wxGetApp().open_web_page_localized("https://www.prusa3d.com/slicerweb"); return true; }
+ );
+ */
+ // updater
+ // read triggered_by_user that was set when calling GUI_App::app_version_check
+ app_updater(m_app_updater->get_triggered_by_user());
+}
+
+void GUI_App::app_updater(bool from_user)
+{
+ DownloadAppData app_data = m_app_updater->get_app_data();
+
+ if (from_user && (!app_data.version || *app_data.version <= *Semver::parse(SLIC3R_VERSION)))
+ {
+ BOOST_LOG_TRIVIAL(info) << "There is no newer version online.";
+ MsgNoAppUpdates no_update_dialog;
+ no_update_dialog.ShowModal();
+ return;
+
+ }
+
+ assert(!app_data.url.empty());
+ assert(!app_data.target_path.empty());
+
+ // dialog with new version info
+ AppUpdateAvailableDialog dialog(*Semver::parse(SLIC3R_VERSION), *app_data.version);
+ auto dialog_result = dialog.ShowModal();
+ // checkbox "do not show again"
+ if (dialog.disable_version_check()) {
+ app_config->set("notify_release", "none");
+ }
+ // Doesn't wish to update
+ if (dialog_result != wxID_OK) {
+ return;
+ }
+ // dialog with new version download (installer or app dependent on system) including path selection
+ AppUpdateDownloadDialog dwnld_dlg(*app_data.version, app_data.target_path);
+ dialog_result = dwnld_dlg.ShowModal();
+ // Doesn't wish to download
+ if (dialog_result != wxID_OK) {
+ return;
+ }
+ app_data.target_path =dwnld_dlg.get_download_path();
+
+ // start download
+ this->plater_->get_notification_manager()->push_download_progress_notification(_utf8("Download"), std::bind(&AppUpdater::cancel_callback, this->m_app_updater.get()));
+ app_data.start_after = dwnld_dlg.run_after_download();
+ m_app_updater->set_app_data(std::move(app_data));
+ m_app_updater->sync_download();
+}
+
+void GUI_App::app_version_check(bool from_user)
+{
+ if (from_user) {
+ if (m_app_updater->get_download_ongoing()) {
+ MessageDialog msgdlg(nullptr, _L("Download of new version is already ongoing. Do you wish to continue?"), _L("Notice"), wxYES_NO);
+ if (msgdlg.ShowModal() != wxID_YES)
+ return;
+ }
+ }
+ std::string version_check_url = app_config->version_check_url();
+ m_app_updater->sync_version(version_check_url, from_user);
+}
+
} // GUI
} //Slic3r
diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp
index 8b4177a8d7..ce07fb7723 100644
--- a/src/slic3r/GUI/GUI_App.hpp
+++ b/src/slic3r/GUI/GUI_App.hpp
@@ -32,6 +32,7 @@ class PresetUpdater;
class ModelObject;
class PrintHostJobQueue;
class Model;
+class AppUpdater;
namespace GUI{
@@ -71,13 +72,18 @@ enum FileType
FT_SIZE,
};
+#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
+extern wxString file_wildcards(FileType file_type);
+#else
extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string{});
+#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
enum ConfigMenuIDs {
ConfigMenuWizard,
ConfigMenuSnapshots,
ConfigMenuTakeSnapshot,
- ConfigMenuUpdate,
+ ConfigMenuUpdateConf,
+ ConfigMenuUpdateApp,
ConfigMenuDesktopIntegration,
ConfigMenuPreferences,
ConfigMenuModeSimple,
@@ -152,6 +158,7 @@ private:
std::unique_ptr m_imgui;
std::unique_ptr m_printhost_job_queue;
std::unique_ptr m_other_instance_message_handler;
+ std::unique_ptr m_app_updater;
std::unique_ptr m_single_instance_checker;
std::string m_instance_hash_string;
size_t m_instance_hash_int;
@@ -356,6 +363,11 @@ private:
// Returns true if the configuration is fine.
// Returns true if the configuration is not compatible and the user decided to rather close the slicer instead of reconfiguring.
bool check_updates(const bool verbose);
+ void on_version_read(wxCommandEvent& evt);
+ // if the data from version file are already downloaded, shows dialogs to start download of new version of app
+ void app_updater(bool from_user);
+ // inititate read of version file online in separate thread
+ void app_version_check(bool from_user);
bool m_datadir_redefined { false };
};
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 766c48becf..353577944f 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -821,7 +821,7 @@ void ObjectList::paste_objects_into_list(const std::vector& object_idxs)
wxDataViewItemArray items;
for (const size_t object : object_idxs)
{
- add_object_to_list(object);
+ add_object_to_list(object, false);
items.Add(m_objects_model->GetItemById(object));
}
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 2cac5e3566..9f62fa0b85 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -859,6 +859,36 @@ void Preview::update_moves_slider()
if (view.endpoints.last < view.endpoints.first)
return;
+#if ENABLE_PROCESS_G2_G3_LINES
+ assert(view.endpoints.first <= view.current.first && view.current.first <= view.endpoints.last);
+ assert(view.endpoints.first <= view.current.last && view.current.last <= view.endpoints.last);
+
+ std::vector values;
+ values.reserve(view.endpoints.last - view.endpoints.first + 1);
+ std::vector alternate_values;
+ alternate_values.reserve(view.endpoints.last - view.endpoints.first + 1);
+ unsigned int last_gcode_id = view.gcode_ids[view.endpoints.first];
+ for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i) {
+ if (i > view.endpoints.first) {
+ // skip consecutive moves with same gcode id (resulting from processing G2 and G3 lines)
+ if (last_gcode_id == view.gcode_ids[i]) {
+ values.back() = static_cast(i + 1);
+ alternate_values.back() = static_cast(view.gcode_ids[i]);
+ continue;
+ }
+ else
+ last_gcode_id = view.gcode_ids[i];
+ }
+
+ values.emplace_back(static_cast(i + 1));
+ alternate_values.emplace_back(static_cast(view.gcode_ids[i]));
+ }
+
+ m_moves_slider->SetSliderValues(values);
+ m_moves_slider->SetSliderAlternateValues(alternate_values);
+ m_moves_slider->SetMaxValue(int(values.size()) - 1);
+ m_moves_slider->SetSelectionSpan(values.front() - 1 - view.endpoints.first, values.back() - 1 - view.endpoints.first);
+#else
std::vector values(view.endpoints.last - view.endpoints.first + 1);
std::vector alternate_values(view.endpoints.last - view.endpoints.first + 1);
unsigned int count = 0;
@@ -873,6 +903,7 @@ void Preview::update_moves_slider()
m_moves_slider->SetSliderAlternateValues(alternate_values);
m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first);
m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first);
+#endif // ENABLE_PROCESS_G2_G3_LINES
}
void Preview::enable_moves_slider(bool enable)
@@ -966,6 +997,11 @@ void Preview::load_print_as_fff(bool keep_z_range)
Refresh();
zs = m_canvas->get_volumes_print_zs(true);
}
+ else {
+ m_left_sizer->Hide(m_bottom_toolbar_panel);
+ m_left_sizer->Layout();
+ Refresh();
+ }
if (!zs.empty() && !m_keep_current_preview_type) {
unsigned int number_extruders = wxGetApp().is_editor() ?
@@ -1040,7 +1076,6 @@ void Preview::load_print_as_sla()
if (IsShown()) {
m_canvas->load_sla_preview();
m_left_sizer->Hide(m_bottom_toolbar_panel);
- m_left_sizer->Hide(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index 4b10c19871..c95b059513 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -134,11 +134,7 @@ void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
void GLGizmoBase::render_grabbers(float size) const
{
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
shader->start_using();
@@ -153,11 +149,7 @@ void GLGizmoBase::render_grabbers(float size) const
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
index 5c9b08a93c..9a87d5a459 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
@@ -107,11 +107,7 @@ void GLGizmoCut::on_render()
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
const Vec3d diff = plane_center - m_old_center;
@@ -197,11 +193,7 @@ void GLGizmoCut::on_render()
shader->stop_using();
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
glsafe(::glColor3f(1.0, 1.0, 0.0));
::glBegin(GL_LINES);
@@ -222,11 +214,7 @@ void GLGizmoCut::on_render()
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("flat_attr");
-#else
shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
index 48c81bc5a1..aa291f6231 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
@@ -105,11 +105,7 @@ void GLGizmoFlatten::on_render()
const Selection& selection = m_parent.get_selection();
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -165,11 +161,7 @@ void GLGizmoFlatten::on_render_for_picking()
const Selection& selection = m_parent.get_selection();
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
index ebf8aa21b5..88b319f252 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
@@ -104,11 +104,7 @@ void GLGizmoHollow::on_render_for_picking()
void GLGizmoHollow::render_points(const Selection& selection, bool picking)
{
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -122,9 +118,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
+ Geometry::Transformation trafo = vol->get_instance_transformation() * vol->get_volume_transformation();
+
#if ENABLE_GL_SHADERS_ATTRIBUTES
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
- const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix();
+ const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix();
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d& view_matrix = camera.get_view_matrix();
@@ -132,8 +130,8 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
shader->set_uniform("projection_matrix", projection_matrix);
#else
- const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
- const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
+ const Transform3d& instance_scaling_matrix_inverse = trafo.get_matrix(true, true, false, true).inverse();
+ const Transform3d& instance_matrix = trafo.get_matrix();
glsafe(::glPushMatrix());
glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift()));
@@ -222,7 +220,7 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
auto sel_info = m_c->selection_info();
int active_inst = m_c->selection_info()->get_active_instance();
const ModelInstance* mi = sel_info->model_object()->instances[active_inst];
- const Transform3d& trafo = mi->get_transformation().get_matrix();
+ const Transform3d& trafo = mi->get_transformation().get_matrix() * sel_info->model_object()->volumes.front()->get_matrix();
Vec3d transformed_point = trafo * point;
transformed_point(2) += sel_info->get_sla_shift();
@@ -241,7 +239,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera();
const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
- Geometry::Transformation trafo = volume->get_instance_transformation();
+ Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
double clp_dist = m_c->object_clipper()->get_position();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
index 49eb8cb95b..308100d7fe 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
@@ -170,11 +170,7 @@ void GLGizmoMmuSegmentation::data_changed()
void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
{
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- auto* shader = wxGetApp().get_shader("mm_gouraud_attr");
-#else
auto *shader = wxGetApp().get_shader("mm_gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (!shader)
return;
shader->start_using();
@@ -598,16 +594,13 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
auto *shader = wxGetApp().get_current_shader();
if (!shader)
return;
+ assert(shader->get_name() == "mm_gouraud");
#if ENABLE_GL_SHADERS_ATTRIBUTES
- assert(shader->get_name() == "mm_gouraud_attr");
-
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
-#else
- assert(shader->get_name() == "mm_gouraud");
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) {
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index c3d1110dc7..ff9b788909 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -230,11 +230,7 @@ void GLGizmoMove3D::on_render()
if (m_hover_id == -1) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -291,11 +287,7 @@ void GLGizmoMove3D::on_render()
else {
// draw axis
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
@@ -309,11 +301,7 @@ void GLGizmoMove3D::on_render()
shader->stop_using();
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data()));
::glBegin(GL_LINES);
@@ -429,11 +417,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
index 03d60440ad..01dc595148 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
@@ -80,11 +80,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl
void GLGizmoPainterBase::render_triangles(const Selection& selection) const
{
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- auto* shader = wxGetApp().get_shader("gouraud_attr");
-#else
auto* shader = wxGetApp().get_shader("gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (! shader)
return;
shader->start_using();
@@ -250,11 +246,7 @@ void GLGizmoPainterBase::render_cursor_circle()
m_circle.init_from(std::move(init_data));
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -292,11 +284,7 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
}
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -927,11 +915,9 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
auto* shader = wxGetApp().get_current_shader();
if (! shader)
return;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- assert(shader->get_name() == "gouraud_attr");
-#else
+
assert(shader->get_name() == "gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
+
ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);});
shader->set_uniform("offset_depth_buffer", true);
for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color),
@@ -1288,11 +1274,7 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
if (curr_shader != nullptr)
curr_shader->stop_using();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
@@ -1375,11 +1357,7 @@ void TriangleSelectorGUI::render_paint_contour()
if (curr_shader != nullptr)
curr_shader->stop_using();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
-#else
auto* contour_shader = wxGetApp().get_shader("mm_contour");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (contour_shader != nullptr) {
contour_shader->start_using();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index bfc30fb93c..9e1f5bb353 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -185,11 +185,7 @@ void GLGizmoRotate::on_render()
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
@@ -642,11 +638,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
const double size = m_dragging ? double(m_grabbers.front().get_dragging_half_size(mean_size)) : double(m_grabbers.front().get_half_size(mean_size));
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index 3b1a69003e..5c47ef7aaa 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -406,11 +406,7 @@ void GLGizmoScale3D::on_render()
if (m_hover_id == -1) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
// draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -457,11 +453,7 @@ void GLGizmoScale3D::on_render()
else if (m_hover_id == 0 || m_hover_id == 1) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
// draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -474,11 +466,7 @@ void GLGizmoScale3D::on_render()
}
// draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
// draw connection
glsafe(::glColor4fv(AXES_COLOR[0].data()));
@@ -498,11 +486,7 @@ void GLGizmoScale3D::on_render()
else if (m_hover_id == 2 || m_hover_id == 3) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
// draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -515,11 +499,7 @@ void GLGizmoScale3D::on_render()
}
// draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
// draw connection
glsafe(::glColor4fv(AXES_COLOR[1].data()));
@@ -539,11 +519,7 @@ void GLGizmoScale3D::on_render()
else if (m_hover_id == 4 || m_hover_id == 5) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
// draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -556,11 +532,7 @@ void GLGizmoScale3D::on_render()
}
// draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
// draw connection
glsafe(::glColor4fv(AXES_COLOR[2].data()));
@@ -580,11 +552,7 @@ void GLGizmoScale3D::on_render()
else if (m_hover_id >= 6) {
#if ENABLE_LEGACY_OPENGL_REMOVAL
// draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -600,11 +568,7 @@ void GLGizmoScale3D::on_render()
}
// draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
// draw connection
glsafe(::glColor4fv(m_drag_color.data()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
index 1a383187c6..bce1123e00 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
@@ -737,14 +737,11 @@ void GLGizmoSimplify::on_render()
GLModel &glmodel = it->second;
const Transform3d trafo_matrix = selected_volume->world_matrix();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- auto* gouraud_shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
+#if !ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(trafo_matrix.data()));
-
- auto *gouraud_shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
+#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
+ auto* gouraud_shader = wxGetApp().get_shader("gouraud_light");
glsafe(::glPushAttrib(GL_DEPTH_TEST));
glsafe(::glEnable(GL_DEPTH_TEST));
gouraud_shader->start_using();
@@ -759,11 +756,7 @@ void GLGizmoSimplify::on_render()
gouraud_shader->stop_using();
if (m_show_wireframe) {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
-#else
auto *contour_shader = wxGetApp().get_shader("mm_contour");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
contour_shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
contour_shader->set_uniform("view_model_matrix", view_model_matrix);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 3173cb10dd..7c61673b45 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -130,11 +130,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
return;
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -151,18 +147,17 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
- const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
+ Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix());
+ const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse();
#if ENABLE_GL_SHADERS_ATTRIBUTES
- const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix();
-
+ const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * transformation.get_matrix();
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d& view_matrix = camera.get_view_matrix();
const Transform3d& projection_matrix = camera.get_projection_matrix();
shader->set_uniform("projection_matrix", projection_matrix);
#else
- const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
-
+ const Transform3d& instance_matrix = transformation.get_matrix();
const float z_shift = m_c->selection_info()->get_sla_shift();
glsafe(::glPushMatrix());
glsafe(::glTranslated(0.0, 0.0, z_shift));
@@ -344,7 +339,7 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
auto sel_info = m_c->selection_info();
int active_inst = m_c->selection_info()->get_active_instance();
const ModelInstance* mi = sel_info->model_object()->instances[active_inst];
- const Transform3d& trafo = mi->get_transformation().get_matrix();
+ const Transform3d& trafo = mi->get_transformation().get_matrix() * sel_info->model_object()->volumes.front()->get_matrix();
Vec3d transformed_point = trafo * point;
transformed_point(2) += sel_info->get_sla_shift();
@@ -363,7 +358,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera();
const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
- Geometry::Transformation trafo = volume->get_instance_transformation();
+ Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
double clp_dist = m_c->object_clipper()->get_position();
@@ -1238,7 +1233,7 @@ void GLGizmoSlaSupports::get_data_from_backend()
if (po->model_object()->id() == mo->id()) {
m_normal_cache.clear();
const std::vector& points = po->get_support_points();
- auto mat = po->trafo().inverse().cast();
+ auto mat = (po->trafo() * po->model_object()->volumes.front()->get_transformation().get_matrix()).inverse().cast();
for (unsigned int i=0; iget_canvas();
const PrintObjects& print_objects = canvas->sla_print()->objects();
- const SLAPrintObject* print_object = m_print_object_idx != -1
+ const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size()))
? print_objects[m_print_object_idx]
: nullptr;
@@ -276,7 +276,7 @@ void HollowedMesh::on_update()
const TriangleMesh& backend_mesh = print_object->get_mesh_to_slice();
if (! backend_mesh.empty()) {
m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh));
- Transform3d trafo_inv = canvas->sla_print()->sla_trafo(*mo).inverse();
+ Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse();
m_hollowed_mesh_transformed->transform(trafo_inv);
m_drainholes = print_object->model_object()->sla_drain_holes;
m_old_hollowing_timestamp = timestamp;
@@ -474,7 +474,7 @@ void SupportsClipper::on_update()
const GLCanvas3D* canvas = get_pool()->get_canvas();
const PrintObjects& print_objects = canvas->sla_print()->objects();
- const SLAPrintObject* print_object = m_print_object_idx != -1
+ const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size()))
? print_objects[m_print_object_idx]
: nullptr;
diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index 613b168415..d5dfa276ce 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -1475,10 +1475,10 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
- GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
- GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
- GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
- GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
+ GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
+ GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
+ GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
+ GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
GLint last_texture_env_mode; glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_texture_env_mode));
glsafe(::glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT));
glsafe(::glEnable(GL_BLEND));
@@ -1528,19 +1528,15 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
glsafe(::glLoadIdentity());
#endif // ENABLE_GL_IMGUI_SHADERS
-#if ENABLE_GL_IMGUI_SHADERS
// Will project scissor/clipping rectangles into framebuffer space
- const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
-#else
- const ImVec2 pos = draw_data->DisplayPos;
-#endif // ENABLE_GL_IMGUI_SHADERS
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; ++n) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
- const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
#if ENABLE_GL_IMGUI_SHADERS
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
@@ -1557,17 +1553,17 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
const int position_id = shader->get_attrib_location("Position");
if (position_id != -1) {
- glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
+ glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, pos)));
glsafe(::glEnableVertexAttribArray(position_id));
}
const int uv_id = shader->get_attrib_location("UV");
if (uv_id != -1) {
- glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
+ glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, uv)));
glsafe(::glEnableVertexAttribArray(uv_id));
}
const int color_id = shader->get_attrib_location("Color");
if (color_id != -1) {
- glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
+ glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, col)));
glsafe(::glEnableVertexAttribArray(color_id));
}
#else
@@ -1596,18 +1592,20 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
#else
- const ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
- if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) {
- // Apply scissor/clipping rectangle
- glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
+ // Project scissor/clipping rectangles into framebuffer space
+ const ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ const ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+ continue;
- // Bind texture, Draw
- glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
- glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
- }
+ // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
+ glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
+
+ // Bind texture, Draw
+ glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
+ glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset));
#endif // ENABLE_GL_IMGUI_SHADERS
}
- idx_buffer += pcmd->ElemCount;
}
#if ENABLE_GL_IMGUI_SHADERS
@@ -1639,11 +1637,14 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
glsafe(::glPopMatrix());
#endif // !ENABLE_GL_IMGUI_SHADERS
glsafe(::glPopAttrib());
- glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]));
+ glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
+ glsafe(::glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1])));
glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]));
glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]));
#if ENABLE_GL_IMGUI_SHADERS
+ shader->stop_using();
+
if (curr_shader != nullptr)
curr_shader->start_using();
#endif // ENABLE_GL_IMGUI_SHADERS
diff --git a/src/slic3r/GUI/Jobs/BusyCursorJob.hpp b/src/slic3r/GUI/Jobs/BusyCursorJob.hpp
index 530213b1d5..8504d1eb93 100644
--- a/src/slic3r/GUI/Jobs/BusyCursorJob.hpp
+++ b/src/slic3r/GUI/Jobs/BusyCursorJob.hpp
@@ -4,6 +4,7 @@
#include "Job.hpp"
#include
+#include
namespace Slic3r { namespace GUI {
@@ -16,7 +17,11 @@ struct CursorSetterRAII
}
~CursorSetterRAII()
{
- ctl.call_on_main_thread([] { wxEndBusyCursor(); });
+ try {
+ ctl.call_on_main_thread([] { wxEndBusyCursor(); });
+ } catch(...) {
+ BOOST_LOG_TRIVIAL(error) << "Can't revert cursor from busy to normal";
+ }
}
};
diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp
index e7e9ba2fbe..bbdcdeb346 100644
--- a/src/slic3r/GUI/MeshUtils.cpp
+++ b/src/slic3r/GUI/MeshUtils.cpp
@@ -87,11 +87,7 @@ void MeshClipper::render_cut()
if (curr_shader != nullptr)
curr_shader->stop_using();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader != nullptr) {
shader->start_using();
#if ENABLE_GL_SHADERS_ATTRIBUTES
diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp
index 6e9bc267fd..fc20e43f5d 100644
--- a/src/slic3r/GUI/NotificationManager.cpp
+++ b/src/slic3r/GUI/NotificationManager.cpp
@@ -318,7 +318,8 @@ void NotificationManager::PopNotification::count_lines()
}
m_lines_count++;
}
- // hypertext calculation
+ // original hypertext calculation (when there was no text2)
+ /*
if (!m_hypertext.empty()) {
int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; // m_endlines.size() - 2 because we are fitting hypertext instead of last endline
if (ImGui::CalcTextSize((escape_string_cstyle(text.substr(prev_end, last_end - prev_end)) + m_hypertext).c_str()).x > m_window_width - m_window_width_offset) {
@@ -326,9 +327,84 @@ void NotificationManager::PopNotification::count_lines()
m_lines_count++;
}
}
+ */
+ int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0;
+ int size_of_last_line = ImGui::CalcTextSize(text.substr(prev_end, last_end - prev_end).c_str()).x;
+ // hypertext calculation
+ if (!m_hypertext.empty()) {
+ if (size_of_last_line + ImGui::CalcTextSize(m_hypertext.c_str()).x > m_window_width - m_window_width_offset) {
+ // hypertext on new line
+ size_of_last_line = ImGui::CalcTextSize((m_hypertext + " ").c_str()).x;
+ m_endlines.push_back(last_end);
+ m_lines_count++;
+ }
+ else {
+ size_of_last_line += ImGui::CalcTextSize((m_hypertext + " ").c_str()).x;
+ }
+ }
+ // text after hypertext calculation
+ if (!m_text2.empty()) {
+ text = m_text2;
+ last_end = 0;
+ m_endlines2.clear();
+ // if size_of_last_line too large to fit anything
+ size_t first_end = std::min(text.find_first_of('\n'), text.find_first_of(' '));
+ if (size_of_last_line >= m_window_width - m_window_width_offset - ImGui::CalcTextSize(text.substr(0, first_end).c_str()).x) {
+ m_endlines2.push_back(0);
+ size_of_last_line = 0;
+ }
+ while (last_end < text.length() - 1)
+ {
+ size_t next_hard_end = text.find_first_of('\n', last_end);
+ if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
+ //next line is ended by '/n'
+ m_endlines2.push_back(next_hard_end);
+ last_end = next_hard_end + 1;
+ }
+ else {
+ // find next suitable endline
+ if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset - size_of_last_line) {
+ // more than one line till end
+ size_t next_space = text.find_first_of(' ', last_end);
+ if (next_space > 0) {
+ size_t next_space_candidate = text.find_first_of(' ', next_space + 1);
+ while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
+ next_space = next_space_candidate;
+ next_space_candidate = text.find_first_of(' ', next_space + 1);
+ }
+ }
+ else {
+ next_space = text.length();
+ }
+ // when one word longer than line.
+ if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset - size_of_last_line ||
+ ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x + size_of_last_line < (m_window_width - m_window_width_offset) / 5 * 3
+ ) {
+ float width_of_a = ImGui::CalcTextSize("a").x;
+ int letter_count = (int)((m_window_width - m_window_width_offset - size_of_last_line) / width_of_a);
+ while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
+ letter_count += get_utf8_sequence_length(text, last_end + letter_count);
+ }
+ m_endlines2.push_back(last_end + letter_count);
+ last_end += letter_count;
+ }
+ else {
+ m_endlines2.push_back(next_space);
+ last_end = next_space + 1;
+ }
+ }
+ else {
+ m_endlines2.push_back(text.length());
+ last_end = text.length();
+ }
- // m_text_2 (text after hypertext) is not used for regular notifications right now.
- // its caluculation is in HintNotification::count_lines()
+ }
+ if (size_of_last_line == 0) // if first line is continuation of previous text, do not add to line count.
+ m_lines_count++;
+ size_of_last_line = 0; // should countain value only for first line (with hypertext)
+
+ }
+ }
}
void NotificationManager::PopNotification::init()
@@ -394,8 +470,29 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext);
}
- // text2 (text after hypertext) is not rendered for regular notifications
- // its rendering is in HintNotification::render_text
+ // text2
+ if (!m_text2.empty() && (m_multiline|| m_lines_count <= 2)) {
+ starting_y += (m_endlines.size() - 1) * shift_y;
+ last_end = 0;
+ for (size_t i = 0; i < (m_multiline ? m_endlines2.size() : 2); i++) {
+ if (i == 0) //first line X is shifted by hypertext
+ ImGui::SetCursorPosX(x_offset + ImGui::CalcTextSize((line + m_hypertext + (line.empty() ? " " : " ")).c_str()).x);
+ else
+ ImGui::SetCursorPosX(x_offset);
+
+ ImGui::SetCursorPosY(starting_y + i * shift_y);
+ line.clear();
+ if (m_endlines2.size() > i && m_text2.size() >= m_endlines2[i]) {
+
+ // regular line
+ line = m_text2.substr(last_end, m_endlines2[i] - last_end);
+ last_end = m_endlines2[i];
+ if (m_text2.size() > m_endlines2[i])
+ last_end += (m_text2[m_endlines2[i]] == '\n' || m_text2[m_endlines2[i]] == ' ' ? 1 : 0);
+ imgui.text(line.c_str());
+ }
+ }
+ }
}
void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui, const float text_x, const float text_y, const std::string text, bool more)
@@ -819,6 +916,120 @@ void NotificationManager::ProgressBarNotification::render_bar(ImGuiWrapper& imgu
imgui.text(text.c_str());
}
}
+//------ProgressBarWithCancelNotification----------------
+
+void NotificationManager::ProgressBarWithCancelNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+ if (m_percentage < 0.f || m_percentage >= 1.f)
+ render_close_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+ else
+ render_cancel_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+}
+void NotificationManager::ProgressBarWithCancelNotification::render_close_button_inner(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+ ImVec2 win_size(win_size_x, win_size_y);
+ ImVec2 win_pos(win_pos_x, win_pos_y);
+ ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
+ push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
+ push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
+
+
+ std::string button_text;
+ button_text = ImGui::CloseNotifButton;
+
+ if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
+ ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
+ true))
+ {
+ button_text = ImGui::CloseNotifHoverButton;
+ }
+ ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
+ ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
+ ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
+ ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
+ if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
+ {
+ close();
+ }
+
+ //invisible large button
+ ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
+ ImGui::SetCursorPosY(0);
+ if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
+ {
+ close();
+ }
+ ImGui::PopStyleColor(5);
+
+}
+
+void NotificationManager::ProgressBarWithCancelNotification::render_cancel_button_inner(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+ ImVec2 win_size(win_size_x, win_size_y);
+ ImVec2 win_pos(win_pos_x, win_pos_y);
+ ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
+ push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
+ push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
+
+
+ std::string button_text;
+ button_text = ImGui::CancelButton;
+
+ if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
+ ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
+ true))
+ {
+ button_text = ImGui::CancelHoverButton;
+ }
+ ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
+ ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
+ ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
+ ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
+ if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
+ {
+ on_cancel_button();
+ }
+
+ //invisible large button
+ ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
+ ImGui::SetCursorPosY(0);
+ if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
+ {
+ on_cancel_button();
+ }
+ ImGui::PopStyleColor(5);
+
+}
+
+void NotificationManager::ProgressBarWithCancelNotification::on_cancel_button()
+{
+ if (m_cancel_callback) {
+ if (m_cancel_callback()) {
+ close();
+ }
+ }
+}
+
+void NotificationManager::ProgressBarWithCancelNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+ ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+ std::string text;
+ if (m_percentage < 0.f) {
+ text = _u8L("ERROR");
+ } else {
+ std::stringstream stream;
+ stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%";
+ text = stream.str();
+ }
+ ImGui::SetCursorPosX(m_left_indentation);
+ ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
+ imgui.text(text.c_str());
+}
+
//------PrintHostUploadNotification----------------
void NotificationManager::PrintHostUploadNotification::init()
{
@@ -1427,10 +1638,11 @@ void NotificationManager::push_notification(NotificationType type,
const std::string& text,
const std::string& hypertext,
std::function callback,
+ const std::string& text_after,
int timestamp)
{
int duration = get_standard_duration(level);
- push_notification_data({ type, level, duration, text, hypertext, callback }, timestamp);
+ push_notification_data({ type, level, duration, text, hypertext, callback, text_after }, timestamp);
}
void NotificationManager::push_delayed_notification(const NotificationType type, std::function condition_callback, int64_t initial_delay, int64_t delay_interval)
@@ -1653,11 +1865,42 @@ void NotificationManager::upload_job_notification_show_error(int id, const std::
}
}
+void NotificationManager::push_download_progress_notification(const std::string& text, std::function cancel_callback)
+{
+ // If already exists, change text and reset progress
+ for (std::unique_ptr& notification : m_pop_notifications) {
+ if (notification->get_type() == NotificationType::AppDownload) {
+ notification->update({ NotificationType::AppDownload, NotificationLevel::ProgressBarNotificationLevel, 10, text });
+ auto* pbwcn = dynamic_cast(notification.get());
+ pbwcn->set_percentage(0.0f);
+ pbwcn->set_cancel_callback(cancel_callback);
+ return;
+ }
+ }
+ // push new one
+ NotificationData data{ NotificationType::AppDownload, NotificationLevel::ProgressBarNotificationLevel, 10, text };
+ push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, cancel_callback), 0);
+}
+void NotificationManager::set_download_progress_percentage(float percentage)
+{
+ for (std::unique_ptr& notification : m_pop_notifications) {
+ if (notification->get_type() == NotificationType::AppDownload) {
+ ProgressBarWithCancelNotification* pbwcn = dynamic_cast(notification.get());
+ // if this changes the percentage, it should be shown now
+ float percent_b4 = pbwcn->get_percentage();
+ pbwcn->set_percentage(percentage);
+ if (pbwcn->get_percentage() != percent_b4)
+ wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
+ return;
+ }
+ }
+}
+
void NotificationManager::init_slicing_progress_notification(std::function cancel_callback)
{
for (std::unique_ptr& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
- dynamic_cast(notification.get())->set_cancel_callback(cancel_callback);
+ dynamic_cast(notification.get())->set_cancel_callback(cancel_callback);
return;
}
}
diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp
index 9265cb55e4..c6a24d997d 100644
--- a/src/slic3r/GUI/NotificationManager.hpp
+++ b/src/slic3r/GUI/NotificationManager.hpp
@@ -78,6 +78,8 @@ enum class NotificationType
ProgressBar,
// Progress bar with info from Print Host Upload Queue dialog.
PrintHostUpload,
+ // Progress bar of download next version app.
+ AppDownload,
// Progress bar with cancel button, cannot be closed
// On end of slicing and G-code processing (the full G-code preview is available),
// contains a hyperlink to export the G-code to a removable media or hdd.
@@ -152,7 +154,7 @@ public:
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotificationLevel.
// ErrorNotificationLevel are never faded out.
void push_notification(NotificationType type, NotificationLevel level, const std::string& text, const std::string& hypertext = "",
- std::function callback = std::function(), int timestamp = 0);
+ std::function callback = std::function(), const std::string& text_after = "", int timestamp = 0);
// Pushes basic_notification with delay. See push_delayed_notification_data.
void push_delayed_notification(const NotificationType type, std::function condition_callback, int64_t initial_delay, int64_t delay_interval);
// Removes all notifications of type from m_waiting_notifications
@@ -203,6 +205,9 @@ public:
void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage);
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
+ // Download App progress
+ void push_download_progress_notification(const std::string& text, std::function cancel_callback);
+ void set_download_progress_percentage(float percentage);
// slicing progress
void init_slicing_progress_notification(std::function cancel_callback);
void set_slicing_progress_began();
@@ -437,6 +442,7 @@ private:
ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) { }
virtual void set_percentage(float percent) { m_percentage = percent; }
+ float get_percentage() const { return m_percentage; }
protected:
virtual void init() override;
virtual void render_text(ImGuiWrapper& imgui,
@@ -459,7 +465,35 @@ private:
};
-
+ class ProgressBarWithCancelNotification : public ProgressBarNotification
+ {
+ public:
+ ProgressBarWithCancelNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function cancel_callback)
+ : ProgressBarNotification(n, id_provider, evt_handler)
+ , m_cancel_callback(cancel_callback)
+ {
+ }
+ void set_percentage(float percent) override { m_percentage = percent; if(m_percentage >= 1.f) m_state = EState::FadingOut; else m_state = EState::NotFading; }
+ void set_cancel_callback(std::function cancel_callback) { m_cancel_callback = cancel_callback; }
+
+ protected:
+ void render_close_button(ImGuiWrapper& imgui,
+ const float win_size_x, const float win_size_y,
+ const float win_pos_x, const float win_pos_y) override;
+ void render_close_button_inner(ImGuiWrapper& imgui,
+ const float win_size_x, const float win_size_y,
+ const float win_pos_x, const float win_pos_y);
+ void render_cancel_button_inner(ImGuiWrapper& imgui,
+ const float win_size_x, const float win_size_y,
+ const float win_pos_x, const float win_pos_y);
+ void render_bar(ImGuiWrapper& imgui,
+ const float win_size_x, const float win_size_y,
+ const float win_pos_x, const float win_pos_y) override;
+ void on_cancel_button();
+
+ std::function m_cancel_callback;
+ long m_hover_time{ 0 };
+ };
class PrintHostUploadNotification : public ProgressBarNotification
{
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 7f542b8323..a74ae28b3b 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -2225,7 +2225,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1";
sidebar->collapse(is_collapsed);
}
-}
+ }
Plater::priv::~priv()
{
@@ -5578,7 +5578,7 @@ bool Plater::load_files(const wxArrayString& filenames)
if (!model().objects.empty()) {
if ((boost::algorithm::iends_with(filename, ".3mf") && !is_project_3mf(it->string())) ||
(boost::algorithm::iends_with(filename, ".amf") && !boost::algorithm::iends_with(filename, ".zip.amf")))
- load_type = LoadType::OpenProject;
+ load_type = LoadType::LoadGeometry;
else {
if (wxGetApp().app_config->get("show_drop_project_dialog") == "1") {
ProjectDropDialog dlg(filename);
@@ -5931,11 +5931,17 @@ void Plater::export_gcode(bool prefer_removable)
fs::path output_path;
{
- std::string ext = default_output_file.extension().string();
+#if !ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
+ std::string ext = default_output_file.extension().string();
+#endif // !ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _L("Save G-code file as:") : _L("Save SL1 / SL1S file as:"),
start_dir,
from_path(default_output_file.filename()),
+#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
+ GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_SL1),
+#else
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_SL1, ext),
+#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
);
if (dlg.ShowModal() == wxID_OK) {
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 4b02b9208c..282d6a0399 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -1512,11 +1512,7 @@ void Selection::render_center(bool gizmo_is_dragging)
return;
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -1561,11 +1557,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field)
return;
#if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat_attr" : "gouraud_light_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
@@ -2351,11 +2343,7 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con
glsafe(::glLineWidth(2.0f * m_scale_factor));
-#if ENABLE_GL_SHADERS_ATTRIBUTES
- GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
if (shader == nullptr)
return;
diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp
index f80975ce52..0441e866f3 100644
--- a/src/slic3r/GUI/UpdateDialogs.cpp
+++ b/src/slic3r/GUI/UpdateDialogs.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
@@ -14,11 +15,13 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp"
+#include "../Utils/AppUpdater.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "ConfigWizard.hpp"
#include "wxExtensions.hpp"
+#include "format.hpp"
namespace Slic3r {
namespace GUI {
@@ -88,6 +91,125 @@ bool MsgUpdateSlic3r::disable_version_check() const
return cbox->GetValue();
}
+ wxSize AppUpdateAvailableDialog::AUAD_size;
+// AppUpdater
+AppUpdateAvailableDialog::AppUpdateAvailableDialog(const Semver& ver_current, const Semver& ver_online)
+ : MsgDialog(nullptr, _(L("App Update available")), wxString::Format(_(L("New version of %s is available.\nDo you wish to download it?")), SLIC3R_APP_NAME))
+{
+ auto* versions = new wxFlexGridSizer(1, 0, VERT_SPACING);
+ versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:"))));
+ versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string()));
+ versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:"))));
+ versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string()));
+ content_sizer->Add(versions);
+ content_sizer->AddSpacer(VERT_SPACING);
+
+ cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more")));
+ content_sizer->Add(cbox);
+ content_sizer->AddSpacer(VERT_SPACING);
+
+ AUAD_size = content_sizer->GetSize();
+
+
+ add_button(wxID_CANCEL);
+
+ if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) {
+ btn_ok->SetLabel(_L("Next"));
+ }
+
+ finalize();
+}
+
+AppUpdateAvailableDialog::~AppUpdateAvailableDialog() {}
+
+
+bool AppUpdateAvailableDialog::disable_version_check() const
+{
+ return cbox->GetValue();
+}
+
+// AppUpdateDownloadDialog
+AppUpdateDownloadDialog::AppUpdateDownloadDialog( const Semver& ver_online, boost::filesystem::path& path)
+ : MsgDialog(nullptr, _(L("App Update download")), wxString::Format(_(L("New version of %s is available.")), SLIC3R_APP_NAME))
+{
+ auto* versions = new wxFlexGridSizer(2, 0, VERT_SPACING);
+ versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:"))));
+ versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string()));
+ content_sizer->Add(versions);
+ content_sizer->AddSpacer(VERT_SPACING);
+#ifndef __linux__
+ cbox_run = new wxCheckBox(this, wxID_ANY, _(L("Run installer after download. (Otherwise file explorer will be opened)")));
+ content_sizer->Add(cbox_run);
+#endif
+ content_sizer->AddSpacer(VERT_SPACING);
+ content_sizer->AddSpacer(VERT_SPACING);
+ content_sizer->Add(new wxStaticText(this, wxID_ANY, _(L("Target path:"))));
+ content_sizer->AddSpacer(VERT_SPACING);
+ txtctrl_path = new wxTextCtrl(this, wxID_ANY, path.wstring());
+ content_sizer->Add(txtctrl_path, 1, wxEXPAND);
+ content_sizer->AddSpacer(VERT_SPACING);
+
+ wxButton* btn = new wxButton(this, wxID_ANY, _L("Select path"));
+ content_sizer->Add(btn/*, 1, wxEXPAND*/);
+
+ // button to open file dialog
+ btn->Bind(wxEVT_BUTTON, ([this, path](wxCommandEvent& e) {
+ std::string extension = path.filename().extension().string();
+ wxString wildcard;
+ if (!extension.empty()) {
+ extension = extension.substr(1);
+ wxString wxext = boost::nowide::widen(extension);
+ wildcard = GUI::format_wxstr("%1% Files (*.%2%)|*.%2%", wxext.Upper(), wxext);
+ }
+ wxFileDialog save_dlg(
+ this
+ , _L("Save as:")
+ , txtctrl_path->GetValue()
+ , boost::nowide::widen(AppUpdater::get_filename_from_url(txtctrl_path->GetValue().ToUTF8().data()))
+ , wildcard
+ , wxFD_SAVE | wxFD_OVERWRITE_PROMPT
+ );
+ if (save_dlg.ShowModal() == wxID_OK) {
+ txtctrl_path->SetValue(save_dlg.GetPath());
+ }
+ }));
+
+ content_sizer->SetMinSize(AppUpdateAvailableDialog::AUAD_size);
+
+ add_button(wxID_CANCEL);
+
+ if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) {
+ btn_ok->SetLabel(_L("Download"));
+ btn_ok->Bind(wxEVT_BUTTON, ([this, path](wxCommandEvent& e){
+ if (boost::filesystem::exists(boost::filesystem::path(txtctrl_path->GetValue().ToUTF8().data()))) {
+ MessageDialog msgdlg(nullptr, GUI::format_wxstr(_L("File %1% already exists. Do you wish to overwrite it?"), txtctrl_path->GetValue()),_L("Notice"), wxYES_NO);
+ if (msgdlg.ShowModal() != wxID_YES)
+ return;
+ }
+ this->EndModal(wxID_OK);
+ }));
+ }
+
+
+ finalize();
+}
+
+AppUpdateDownloadDialog::~AppUpdateDownloadDialog() {}
+
+
+bool AppUpdateDownloadDialog::run_after_download() const
+{
+#ifndef __linux__
+ return cbox_run->GetValue();
+#endif
+ return false;
+}
+
+boost::filesystem::path AppUpdateDownloadDialog::get_download_path() const
+{
+ return std::move(boost::filesystem::path(txtctrl_path->GetValue().ToUTF8().data()));
+}
+
// MsgUpdateConfig
MsgUpdateConfig::MsgUpdateConfig(const std::vector &updates, bool force_before_wizard/* = false*/) :
@@ -314,5 +436,25 @@ MsgNoUpdates::MsgNoUpdates() :
MsgNoUpdates::~MsgNoUpdates() {}
+// MsgNoAppUpdates
+MsgNoAppUpdates::MsgNoAppUpdates() :
+ MsgDialog(nullptr, _(L("App update")), _(L("No updates available")), wxICON_ERROR | wxOK)
+{
+
+ auto* text = new wxStaticText(this, wxID_ANY, wxString::Format(
+ _(L(
+ "%s has no version updates available."
+ )),
+ SLIC3R_APP_NAME
+ ));
+ text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
+ content_sizer->Add(text);
+ content_sizer->AddSpacer(VERT_SPACING);
+
+ finalize();
+}
+
+MsgNoAppUpdates::~MsgNoAppUpdates() {}
+
}
}
diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp
index 435a8ccbd8..2eb4ff8d4f 100644
--- a/src/slic3r/GUI/UpdateDialogs.hpp
+++ b/src/slic3r/GUI/UpdateDialogs.hpp
@@ -6,6 +6,8 @@
#include
#include
+#include
+
#include "libslic3r/Semver.hpp"
#include "MsgDialog.hpp"
@@ -37,6 +39,42 @@ private:
};
+class AppUpdateAvailableDialog : public MsgDialog
+{
+public:
+ AppUpdateAvailableDialog(const Semver& ver_current, const Semver& ver_online);
+ AppUpdateAvailableDialog(AppUpdateAvailableDialog&&) = delete;
+ AppUpdateAvailableDialog(const AppUpdateAvailableDialog&) = delete;
+ AppUpdateAvailableDialog& operator=(AppUpdateAvailableDialog&&) = delete;
+ AppUpdateAvailableDialog& operator=(const AppUpdateAvailableDialog&) = delete;
+ virtual ~AppUpdateAvailableDialog();
+
+ // Tells whether the user checked the "don't bother me again" checkbox
+ bool disable_version_check() const;
+ static wxSize AUAD_size;
+private:
+ wxCheckBox* cbox;
+};
+
+class AppUpdateDownloadDialog : public MsgDialog
+{
+public:
+ AppUpdateDownloadDialog(const Semver& ver_online, boost::filesystem::path& path);
+ AppUpdateDownloadDialog(AppUpdateDownloadDialog&&) = delete;
+ AppUpdateDownloadDialog(const AppUpdateDownloadDialog&) = delete;
+ AppUpdateDownloadDialog& operator=(AppUpdateDownloadDialog&&) = delete;
+ AppUpdateDownloadDialog& operator=(const AppUpdateDownloadDialog&) = delete;
+ virtual ~AppUpdateDownloadDialog();
+
+ // Tells whether the user checked the "don't bother me again" checkbox
+ bool run_after_download() const;
+ boost::filesystem::path get_download_path() const;
+
+private:
+ wxCheckBox* cbox_run;
+ wxTextCtrl* txtctrl_path;
+};
+
// Confirmation dialog informing about configuration update. Lists updated bundles & their versions.
class MsgUpdateConfig : public MsgDialog
{
@@ -129,6 +167,18 @@ public:
~MsgNoUpdates();
};
+// Informs about absence of new version online.
+class MsgNoAppUpdates : public MsgDialog
+{
+public:
+ MsgNoAppUpdates();
+ MsgNoAppUpdates(MsgNoAppUpdates&&) = delete;
+ MsgNoAppUpdates(const MsgNoAppUpdates&) = delete;
+ MsgNoAppUpdates& operator=(MsgNoUpdates&&) = delete;
+ MsgNoAppUpdates& operator=(const MsgNoAppUpdates&) = delete;
+ ~MsgNoAppUpdates();
+};
+
}
}
diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp
new file mode 100644
index 0000000000..60739ccb39
--- /dev/null
+++ b/src/slic3r/Utils/AppUpdater.cpp
@@ -0,0 +1,618 @@
+#include "AppUpdater.hpp"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "slic3r/GUI/format.hpp"
+#include "slic3r/GUI/GUI_App.hpp"
+#include "slic3r/GUI/GUI.hpp"
+#include "slic3r/Utils/Http.hpp"
+
+#include "libslic3r/Utils.hpp"
+
+#ifdef _WIN32
+#include
+#include
+#include
+#include
+#include
+#endif // _WIN32
+
+
+namespace Slic3r {
+
+namespace {
+
+#ifdef _WIN32
+ bool run_file(const boost::filesystem::path& path)
+ {
+ std::string msg;
+ bool res = GUI::create_process(path, std::wstring(), msg);
+ if (!res) {
+ std::string full_message = GUI::format("Running downloaded instaler of %1% has failed:\n%2%", SLIC3R_APP_NAME, msg);
+ BOOST_LOG_TRIVIAL(error) << full_message; // lm: maybe UI error msg? // dk: bellow. (maybe some general show error evt would be better?)
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
+ evt->SetString(full_message);
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+ return res;
+ }
+
+ std::string get_downloads_path()
+ {
+ std::string ret;
+ PWSTR path = NULL;
+ HRESULT hr = SHGetKnownFolderPath(FOLDERID_Downloads, 0, NULL, &path);
+ if (SUCCEEDED(hr)) {
+ ret = boost::nowide::narrow(path);
+ }
+ CoTaskMemFree(path);
+ return ret;
+ }
+#elif __APPLE__
+ bool run_file(const boost::filesystem::path& path)
+ {
+ if (boost::filesystem::exists(path)) {
+ // attach downloaded dmg file
+ const char* argv1[] = { "hdiutil", "attach", path.string().c_str(), nullptr };
+ ::wxExecute(const_cast(argv1), wxEXEC_ASYNC, nullptr);
+ // open inside attached as a folder in finder
+ const char* argv2[] = { "open", "/Volumes/PrusaSlicer", nullptr };
+ ::wxExecute(const_cast(argv2), wxEXEC_ASYNC, nullptr);
+ return true;
+ }
+ return false;
+ }
+
+ std::string get_downloads_path()
+ {
+ // call objective-c implementation
+ return get_downloads_path_mac();
+ }
+#else
+ bool run_file(const boost::filesystem::path& path)
+ {
+ return false;
+ }
+
+ std::string get_downloads_path()
+ {
+ wxString command = "xdg-user-dir DOWNLOAD";
+ wxArrayString output;
+ GUI::desktop_execute_get_result(command, output);
+ if (output.GetCount() > 0) {
+ return output[0].ToUTF8().data(); //lm:I would use wxString::ToUTF8(), although on Linux, nothing at all should work too.
+ }
+ return std::string();
+ }
+#endif // _WIN32 / __apple__ / else
+} // namespace
+
+wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
+wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
+wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent);
+wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent);
+wxDEFINE_EVENT(EVT_SLIC3R_APP_OPEN_FAILED, wxCommandEvent);
+
+// priv handles all operations in separate thread
+// 1) download version file and parse it.
+// 2) download new app file and open in folder / run it.
+struct AppUpdater::priv {
+ priv();
+ // Download file. What happens with the data is specified in completefn.
+ bool http_get_file(const std::string& url
+ , size_t size_limit
+ , std::function progress_fn
+ , std::function completefn
+ , std::string& error_message
+ ) const;
+
+ // Download installer / app
+ boost::filesystem::path download_file(const DownloadAppData& data) const;
+ // Run file in m_last_dest_path
+ bool run_downloaded_file(boost::filesystem::path path);
+ // gets version file via http
+ void version_check(const std::string& version_check_url);
+#if 0
+ // parsing of Prusaslicer.version2
+ void parse_version_string_old(const std::string& body) const;
+#endif
+ // parses ini tree of version file, saves to m_online_version_data and queue event(s) to UI
+ void parse_version_string(const std::string& body);
+ // thread
+ std::thread m_thread;
+ std::atomic_bool m_cancel;
+ std::mutex m_data_mutex;
+ // used to tell if notify user hes about to stop ongoing download
+ std::atomic_bool m_download_ongoing { false };
+ bool get_download_ongoing() const { return m_download_ongoing; }
+ // read only variable used to init m_online_version_data.target_path
+ boost::filesystem::path m_default_dest_folder; // readonly
+ // DownloadAppData read / write needs to be locked by m_data_mutex
+ DownloadAppData m_online_version_data;
+ DownloadAppData get_app_data();
+ void set_app_data(DownloadAppData data);
+ // set only before version file is downloaded, to keep information to show info dialog about no updates
+ // should never change during thread run
+ std::atomic_bool m_triggered_by_user {false};
+ bool get_triggered_by_user() const { return m_triggered_by_user; }
+};
+
+AppUpdater::priv::priv() :
+ m_cancel (false)
+#ifdef __linux__
+ , m_default_dest_folder (boost::filesystem::path("/tmp"))
+#else
+ , m_default_dest_folder (boost::filesystem::path(data_dir()) / "cache")
+#endif //_WIN32
+{
+ boost::filesystem::path downloads_path = boost::filesystem::path(get_downloads_path());
+ if (!downloads_path.empty()) {
+ m_default_dest_folder = std::move(downloads_path);
+ }
+ BOOST_LOG_TRIVIAL(trace) << "App updater default download path: " << m_default_dest_folder; //lm:Is this an error? // dk: changed to trace
+
+}
+
+bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, std::function progress_fn, std::function complete_fn, std::string& error_message) const
+{
+ bool res = false;
+ Http::get(url)
+ .size_limit(size_limit)
+ .on_progress([&, progress_fn](Http::Progress progress, bool& cancel) {
+ // progress function returns true as success (to continue)
+ cancel = (this->m_cancel ? true : !progress_fn(std::move(progress)));
+ if (cancel) {
+ error_message = GUI::format("Error getting: `%1%`: Download was canceled.", //lm:typo //dk: am i blind? :)
+ url);
+ BOOST_LOG_TRIVIAL(debug) << "AppUpdater::priv::http_get_file message: "<< error_message;
+ }
+ })
+ .on_error([&](std::string body, std::string error, unsigned http_status) {
+ error_message = GUI::format("Error getting: `%1%`: HTTP %2%, %3%",
+ url,
+ http_status,
+ error);
+ BOOST_LOG_TRIVIAL(error) << error_message;
+ })
+ .on_complete([&](std::string body, unsigned /* http_status */) {
+ assert(complete_fn != nullptr);
+ res = complete_fn(body, error_message);
+ })
+ .perform_sync();
+
+ return res;
+}
+
+boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& data) const
+{
+ boost::filesystem::path dest_path;
+ size_t last_gui_progress = 0;
+ size_t expected_size = data.size;
+ dest_path = data.target_path;
+ assert(!dest_path.empty());
+ if (dest_path.empty())
+ {
+ BOOST_LOG_TRIVIAL(error) << "Download from " << data.url << " could not start. Destination path is empty.";
+ return boost::filesystem::path();
+ }
+ std::string error_message;
+ bool res = http_get_file(data.url, 130 * 1024 * 1024 //2.4.0 windows installer is 65MB //lm:I don't know, but larger. The binaries will grow. // dk: changed to 130, to have 100% more space. We should put this information into version file.
+ // on_progress
+ , [&last_gui_progress, expected_size](Http::Progress progress) {
+ // size check
+ if (progress.dltotal > 0 && progress.dltotal > expected_size) {
+ std::string message = GUI::format("Downloading new %1% has failed. The file has incorrect file size. Aborting download.\nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);
+ BOOST_LOG_TRIVIAL(error) << message;
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
+ evt->SetString(message);
+ GUI::wxGetApp().QueueEvent(evt);
+ return false;
+ } else if (progress.dltotal > 0 && progress.dltotal < expected_size) {
+ //lm:When will this happen? Is that not an error? // dk: It is possible error, but we cannot know until the download is finished. Somehow the total size can grow during the download.
+ BOOST_LOG_TRIVIAL(info) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);
+ }
+ // progress event
+ size_t gui_progress = progress.dltotal > 0 ? 100 * progress.dlnow / progress.dltotal : 0;
+ BOOST_LOG_TRIVIAL(error) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal;
+ if (last_gui_progress < gui_progress && (last_gui_progress != 0 || gui_progress != 100)) {
+ last_gui_progress = gui_progress;
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS);
+ evt->SetString(GUI::from_u8(std::to_string(gui_progress)));
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+ return true;
+ }
+ // on_complete
+ , [dest_path, expected_size](std::string body, std::string& error_message){
+ // Size check. Does always 1 char == 1 byte?
+ size_t body_size = body.size();
+ if (body_size != expected_size) {
+ //lm:UI message? // dk: changed. Now it propagates to UI.
+ error_message = GUI::format("Downloaded file has wrong size. Expected size: %1% Downloaded size: %2%", expected_size, body_size);
+ return false;
+ }
+ boost::filesystem::path tmp_path = dest_path;
+ tmp_path += format(".%1%%2%", get_current_pid(), ".download");
+ try
+ {
+ boost::filesystem::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
+ file.write(body.c_str(), body.size());
+ file.close();
+ boost::filesystem::rename(tmp_path, dest_path);
+ }
+ catch (const std::exception&)
+ {
+ error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
+ return false;
+ }
+ return true;
+ }
+ , error_message
+ );
+ if (!res)
+ {
+ if (this->m_cancel)
+ {
+ BOOST_LOG_TRIVIAL(info) << error_message; //lm:Is this an error? // dk: changed to info
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); // FAILED with empty msg only closes progress notification
+ GUI::wxGetApp().QueueEvent(evt);
+ } else {
+ std::string message = GUI::format("Downloading new %1% has failed:\n%2%", SLIC3R_APP_NAME, error_message);
+ BOOST_LOG_TRIVIAL(error) << message;
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
+ evt->SetString(message);
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+ return boost::filesystem::path();
+ }
+
+ return dest_path;
+}
+
+bool AppUpdater::priv::run_downloaded_file(boost::filesystem::path path)
+{
+ assert(!path.empty());
+ return run_file(path);
+}
+
+void AppUpdater::priv::version_check(const std::string& version_check_url)
+{
+ assert(!version_check_url.empty());
+ std::string error_message;
+ bool res = http_get_file(version_check_url, 1024
+ // on_progress
+ , [](Http::Progress progress) { return true; }
+ // on_complete
+ , [&](std::string body, std::string& error_message) {
+ boost::trim(body);
+ parse_version_string(body);
+ return true;
+ }
+ , error_message
+ );
+ //lm:In case the internet is not available, it will report no updates if run by user.
+ // We might save a flag that we don't know or try to run the version_check again, reporting
+ // the failure.
+ // dk: changed to download version every time. Dialog will show if m_triggered_by_user.
+ if (!res) {
+ std::string message = GUI::format("Downloading %1% version file has failed:\n%2%", SLIC3R_APP_NAME, error_message);
+ BOOST_LOG_TRIVIAL(error) << message;
+ if (m_triggered_by_user) {
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED);
+ evt->SetString(message);
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+ }
+}
+
+void AppUpdater::priv::parse_version_string(const std::string& body)
+{
+ size_t start = body.find('[');
+ if (start == std::string::npos) {
+#if 0
+ BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Starting old parsing.";
+ parse_version_string_old(body);
+ return;
+#endif // 0
+ BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Checking for application update has failed.";
+ return;
+ }
+ std::string tree_string = body.substr(start);
+ boost::property_tree::ptree tree;
+ std::stringstream ss(tree_string);
+ try {
+ boost::property_tree::read_ini(ss, tree);
+ } catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
+ //throw Slic3r::RuntimeError(format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string).c_str());
+ BOOST_LOG_TRIVIAL(error) << format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string);
+ return;
+ }
+
+ DownloadAppData new_data;
+
+ for (const auto& section : tree) {
+ std::string section_name = section.first;
+
+ // online release version info
+ if (section_name ==
+#ifdef _WIN32
+ "release:win64"
+#elif __APPLE__
+ "release:osx"
+#else
+ "release:linux"
+#endif
+//lm:Related to the ifdefs. We should also support BSD, which behaves similar to Linux in most cases.
+// Unless you have a reason not to, I would consider doing _WIN32, elif __APPLE__, else ... Not just here.
+// dk: so its ok now or we need to specify BSD?
+ ) {
+ for (const auto& data : section.second) {
+ if (data.first == "url") {
+ new_data.url = data.second.data();
+ new_data.target_path = m_default_dest_folder / AppUpdater::get_filename_from_url(new_data.url);
+ BOOST_LOG_TRIVIAL(error) << format("parsing version string: url: %1%", new_data.url);
+ } else if (data.first == "size"){
+ new_data.size = std::stoi(data.second.data());
+ BOOST_LOG_TRIVIAL(error) << format("parsing version string: expected size: %1%", new_data.size);
+ }
+ }
+ }
+
+ // released versions - to be send to UI layer
+ if (section_name == "common") {
+ std::vector prerelease_versions;
+ for (const auto& data : section.second) {
+ // release version - save and send to UI layer
+ if (data.first == "release") {
+ std::string version = data.second.data();
+ boost::optional release_version = Semver::parse(version);
+ if (!release_version) {
+ BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from version file: Not a correct semver: `%1%`", version);
+ return;
+ }
+ new_data.version = release_version;
+ // Send after all data is read
+ /*
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
+ */
+ // prerelease versions - write down to be sorted and send to UI layer
+ } else if (data.first == "alpha") {
+ prerelease_versions.emplace_back(data.second.data());
+ } else if (data.first == "beta") {
+ prerelease_versions.emplace_back(data.second.data());
+ } else if (data.first == "rc") {
+ prerelease_versions.emplace_back(data.second.data());
+ }
+ }
+ // find recent version that is newer than last full release.
+ boost::optional recent_version;
+ std::string version_string;
+ for (const std::string& ver_string : prerelease_versions) {
+ boost::optional ver = Semver::parse(ver_string);
+ if (ver && *new_data.version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) {
+ recent_version = ver;
+ version_string = ver_string;
+ }
+ }
+ // send prerelease version to UI layer
+ if (recent_version) {
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version_string);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version_string));
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+ }
+ }
+ assert(!new_data.url.empty());
+ assert(new_data.version);
+ // save
+ set_app_data(new_data);
+ // send
+ std::string version = new_data.version.get().to_string();
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
+}
+
+#if 0 //lm:is this meant to be ressurected? //dk: it is code that parses PrusaSlicer.version2 in 2.4.0, It was deleted from PresetUpdater.cpp and I would keep it here for possible reference.
+void AppUpdater::priv::parse_version_string_old(const std::string& body) const
+{
+
+ // release version
+ std::string version;
+ const auto first_nl_pos = body.find_first_of("\n\r");
+ if (first_nl_pos != std::string::npos)
+ version = body.substr(0, first_nl_pos);
+ else
+ version = body;
+ boost::optional release_version = Semver::parse(version);
+ if (!release_version) {
+ BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
+ return;
+ }
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
+
+ // alpha / beta version
+ std::vector prerelease_versions;
+ size_t nexn_nl_pos = first_nl_pos;
+ while (nexn_nl_pos != std::string::npos && body.size() > nexn_nl_pos + 1) {
+ const auto last_nl_pos = nexn_nl_pos;
+ nexn_nl_pos = body.find_first_of("\n\r", last_nl_pos + 1);
+ std::string line;
+ if (nexn_nl_pos == std::string::npos)
+ line = body.substr(last_nl_pos + 1);
+ else
+ line = body.substr(last_nl_pos + 1, nexn_nl_pos - last_nl_pos - 1);
+
+ // alpha
+ if (line.substr(0, 6) == "alpha=") {
+ version = line.substr(6);
+ if (!Semver::parse(version)) {
+ BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for alpha release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
+ return;
+ }
+ prerelease_versions.emplace_back(version);
+ // beta
+ }
+ else if (line.substr(0, 5) == "beta=") {
+ version = line.substr(5);
+ if (!Semver::parse(version)) {
+ BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for beta release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
+ return;
+ }
+ prerelease_versions.emplace_back(version);
+ }
+ }
+ // find recent version that is newer than last full release.
+ boost::optional recent_version;
+ for (const std::string& ver_string : prerelease_versions) {
+ boost::optional ver = Semver::parse(ver_string);
+ if (ver && *release_version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) {
+ recent_version = ver;
+ version = ver_string;
+ }
+ }
+ if (recent_version) {
+ BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
+ wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE);
+ evt->SetString(GUI::from_u8(version));
+ GUI::wxGetApp().QueueEvent(evt);
+ }
+}
+#endif // 0
+
+DownloadAppData AppUpdater::priv::get_app_data()
+{
+ const std::lock_guard lock(m_data_mutex);
+ DownloadAppData ret_val(m_online_version_data);
+ return ret_val;
+}
+
+void AppUpdater::priv::set_app_data(DownloadAppData data)
+{
+ const std::lock_guard lock(m_data_mutex);
+ m_online_version_data = data;
+}
+
+AppUpdater::AppUpdater()
+ :p(new priv())
+{
+}
+AppUpdater::~AppUpdater()
+{
+ if (p && p->m_thread.joinable()) {
+ // This will stop transfers being done by the thread, if any.
+ // Cancelling takes some time, but should complete soon enough.
+ p->m_cancel = true;
+ p->m_thread.join();
+ }
+}
+void AppUpdater::sync_download()
+{
+ assert(p);
+ // join thread first - it could have been in sync_version
+ if (p->m_thread.joinable()) {
+ // This will stop transfers being done by the thread, if any.
+ // Cancelling takes some time, but should complete soon enough.
+ p->m_cancel = true;
+ p->m_thread.join();
+ }
+ p->m_cancel = false;
+
+ DownloadAppData input_data = p->get_app_data();
+ assert(!input_data.url.empty());
+
+ p->m_thread = std::thread(
+ [this, input_data]() {
+ p->m_download_ongoing = true;
+ if (boost::filesystem::path dest_path = p->download_file(input_data); boost::filesystem::exists(dest_path)){
+ if (input_data.start_after) {
+ p->run_downloaded_file(std::move(dest_path));
+ } else {
+ GUI::desktop_open_folder(dest_path.parent_path());
+ }
+ }
+ p->m_download_ongoing = false;
+ });
+}
+
+void AppUpdater::sync_version(const std::string& version_check_url, bool from_user)
+{
+ assert(p);
+ // join thread first - it could have been in sync_download
+ if (p->m_thread.joinable()) {
+ // This will stop transfers being done by the thread, if any.
+ // Cancelling takes some time, but should complete soon enough.
+ p->m_cancel = true;
+ p->m_thread.join();
+ }
+ p->m_triggered_by_user = from_user;
+ p->m_cancel = false;
+ p->m_thread = std::thread(
+ [this, version_check_url]() {
+ p->version_check(version_check_url);
+ });
+}
+
+void AppUpdater::cancel()
+{
+ p->m_cancel = true;
+}
+bool AppUpdater::cancel_callback()
+{
+ cancel();
+ return true;
+}
+
+std::string AppUpdater::get_default_dest_folder()
+{
+ return p->m_default_dest_folder.string();
+}
+
+std::string AppUpdater::get_filename_from_url(const std::string& url)
+{
+ size_t slash = url.rfind('/');
+ return (slash != std::string::npos ? url.substr(slash + 1) : url);
+}
+
+std::string AppUpdater::get_file_extension_from_url(const std::string& url)
+{
+ size_t dot = url.rfind('.');
+ return (dot != std::string::npos ? url.substr(dot) : url);
+}
+
+void AppUpdater::set_app_data(DownloadAppData data)
+{
+ p->set_app_data(std::move(data));
+}
+
+DownloadAppData AppUpdater::get_app_data()
+{
+ return p->get_app_data();
+}
+
+bool AppUpdater::get_triggered_by_user() const
+{
+ return p->get_triggered_by_user();
+}
+
+bool AppUpdater::get_download_ongoing() const
+{
+ return p->get_download_ongoing();
+}
+
+} //namespace Slic3r
diff --git a/src/slic3r/Utils/AppUpdater.hpp b/src/slic3r/Utils/AppUpdater.hpp
new file mode 100644
index 0000000000..16d0d668f1
--- /dev/null
+++ b/src/slic3r/Utils/AppUpdater.hpp
@@ -0,0 +1,66 @@
+#ifndef slic3r_AppUpdate_hpp_
+#define slic3r_AppUpdate_hpp_
+
+#include
+#include
+#include "libslic3r/Utils.hpp"
+#include "wx/event.h"
+
+//class boost::filesystem::path;
+
+namespace Slic3r {
+
+#ifdef __APPLE__
+// implmented at MacUtils.mm
+std::string get_downloads_path_mac();
+#endif //__APPLE__
+
+struct DownloadAppData
+{
+ std::string url;
+ bool start_after;
+ boost::optional version;
+ size_t size;
+ boost::filesystem::path target_path;
+};
+
+class AppUpdater
+{
+public:
+ AppUpdater();
+ ~AppUpdater();
+ AppUpdater(AppUpdater&&) = delete;
+ AppUpdater(const AppUpdater&) = delete;
+ AppUpdater& operator=(AppUpdater&&) = delete;
+ AppUpdater& operator=(const AppUpdater&) = delete;
+
+ // downloads app file
+ void sync_download();
+ // downloads version file
+ void sync_version(const std::string& version_check_url, bool from_user);
+ void cancel();
+ bool cancel_callback();
+
+ std::string get_default_dest_folder();
+
+ static std::string get_filename_from_url(const std::string& url);
+ static std::string get_file_extension_from_url(const std::string& url);
+
+ // atomic bool
+ bool get_triggered_by_user() const;
+ bool get_download_ongoing() const;
+ // mutex access
+ void set_app_data(DownloadAppData data);
+ DownloadAppData get_app_data();
+private:
+ struct priv;
+ std::unique_ptr p;
+};
+
+wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
+wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
+wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent);
+wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent);
+wxDECLARE_EVENT(EVT_SLIC3R_APP_OPEN_FAILED, wxCommandEvent);
+} //namespace Slic3r
+#endif
diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp
index 63c26f7217..68ddda0410 100644
--- a/src/slic3r/Utils/Http.cpp
+++ b/src/slic3r/Utils/Http.cpp
@@ -207,7 +207,6 @@ size_t Http::priv::writecb(void *data, size_t size, size_t nmemb, void *userp)
auto self = static_cast(userp);
const char *cdata = static_cast(data);
const size_t realsize = size * nmemb;
-
const size_t limit = self->limit > 0 ? self->limit : DEFAULT_SIZE_LIMIT;
if (self->buffer.size() + realsize > limit) {
// This makes curl_easy_perform return CURLE_WRITE_ERROR
diff --git a/src/slic3r/Utils/MacUtils.mm b/src/slic3r/Utils/MacUtils.mm
new file mode 100644
index 0000000000..31a28f14e4
--- /dev/null
+++ b/src/slic3r/Utils/MacUtils.mm
@@ -0,0 +1,18 @@
+#import "AppUpdater.hpp"
+
+#import
+
+namespace Slic3r {
+
+// AppUpdater.hpp
+std::string get_downloads_path_mac()
+{
+ // 1)
+ NSArray * paths = NSSearchPathForDirectoriesInDomains (NSDownloadsDirectory, NSUserDomainMask, YES);
+ NSString * desktopPath = [paths objectAtIndex:0];
+ return std::string([desktopPath UTF8String]);
+ // 2)
+ //[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"]];
+ //return std::string();
+}
+}
diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp
index 2b458df537..f4863ff20a 100644
--- a/src/slic3r/Utils/PresetUpdater.cpp
+++ b/src/slic3r/Utils/PresetUpdater.cpp
@@ -135,10 +135,6 @@ struct Updates
std::vector updates;
};
-
-wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
-wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
-
struct PresetUpdater::priv
{
std::vector index_db;
@@ -162,8 +158,6 @@ struct PresetUpdater::priv
void set_download_prefs(AppConfig *app_config);
bool get_file(const std::string &url, const fs::path &target_path) const;
void prune_tmps() const;
- void sync_version() const;
- void parse_version_string(const std::string& body) const;
void sync_config(const VendorMap vendors);
void check_install_indices() const;
@@ -238,101 +232,6 @@ void PresetUpdater::priv::prune_tmps() const
}
}
-// Get Slic3rPE version available online, save in AppConfig.
-void PresetUpdater::priv::sync_version() const
-{
- if (! enabled_version_check) { return; }
-
- BOOST_LOG_TRIVIAL(info) << format("Downloading %1% online version from: `%2%`", SLIC3R_APP_NAME, version_check_url);
-
- Http::get(version_check_url)
- .size_limit(SLIC3R_VERSION_BODY_MAX)
- .on_progress([this](Http::Progress, bool &cancel) {
- cancel = this->cancel;
- })
- .on_error([&](std::string body, std::string error, unsigned http_status) {
- (void)body;
- BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
- version_check_url,
- http_status,
- error);
- })
- .on_complete([&](std::string body, unsigned /* http_status */) {
- boost::trim(body);
- parse_version_string(body);
- })
- .perform_sync();
-}
-
-// Parses version string obtained in sync_version() and sends events to UI thread.
-// Version string must contain release version on first line. Follows non-mandatory alpha / beta releases on following lines (alpha=2.0.0-alpha1).
-void PresetUpdater::priv::parse_version_string(const std::string& body) const
-{
- // release version
- std::string version;
- const auto first_nl_pos = body.find_first_of("\n\r");
- if (first_nl_pos != std::string::npos)
- version = body.substr(0, first_nl_pos);
- else
- version = body;
- boost::optional release_version = Semver::parse(version);
- if (!release_version) {
- BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
- return;
- }
- BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
- wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
- evt->SetString(GUI::from_u8(version));
- GUI::wxGetApp().QueueEvent(evt);
-
- // alpha / beta version
- std::vector prerelease_versions;
- size_t nexn_nl_pos = first_nl_pos;
- while (nexn_nl_pos != std::string::npos && body.size() > nexn_nl_pos + 1) {
- const auto last_nl_pos = nexn_nl_pos;
- nexn_nl_pos = body.find_first_of("\n\r", last_nl_pos + 1);
- std::string line;
- if (nexn_nl_pos == std::string::npos)
- line = body.substr(last_nl_pos + 1);
- else
- line = body.substr(last_nl_pos + 1, nexn_nl_pos - last_nl_pos - 1);
-
- // alpha
- if (line.substr(0, 6) == "alpha=") {
- version = line.substr(6);
- if (!Semver::parse(version)) {
- BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for alpha release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
- return;
- }
- prerelease_versions.emplace_back(version);
- // beta
- }
- else if (line.substr(0, 5) == "beta=") {
- version = line.substr(5);
- if (!Semver::parse(version)) {
- BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for beta release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version);
- return;
- }
- prerelease_versions.emplace_back(version);
- }
- }
- // find recent version that is newer than last full release.
- boost::optional recent_version;
- for (const std::string& ver_string : prerelease_versions) {
- boost::optional ver = Semver::parse(ver_string);
- if (ver && *release_version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) {
- recent_version = ver;
- version = ver_string;
- }
- }
- if (recent_version) {
- BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version);
- wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE);
- evt->SetString(GUI::from_u8(version));
- GUI::wxGetApp().QueueEvent(evt);
- }
-}
-
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
// Both are saved in cache.
void PresetUpdater::priv::sync_config(const VendorMap vendors)
@@ -743,7 +642,6 @@ void PresetUpdater::sync(PresetBundle *preset_bundle)
p->thread = std::thread([this, vendors]() {
this->p->prune_tmps();
- this->p->sync_version();
this->p->sync_config(std::move(vendors));
});
}
diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp
index 97d85a4eae..974a7dcfae 100644
--- a/src/slic3r/Utils/PresetUpdater.hpp
+++ b/src/slic3r/Utils/PresetUpdater.hpp
@@ -65,7 +65,7 @@ private:
std::unique_ptr p;
};
-wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
-wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
+//wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
+//wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent);
}
#endif
diff --git a/tests/libslic3r/test_voronoi.cpp b/tests/libslic3r/test_voronoi.cpp
index db12e2fec1..7f25797f56 100644
--- a/tests/libslic3r/test_voronoi.cpp
+++ b/tests/libslic3r/test_voronoi.cpp
@@ -2055,6 +2055,50 @@ TEST_CASE("Voronoi missing vertex 3", "[VoronoiMissingVertex3]")
// REQUIRE(!has_missing_voronoi_vertices(poly, vd));
}
+TEST_CASE("Voronoi missing vertex 4", "[VoronoiMissingVertex4]")
+{
+ // Probably the reason why Voronoi vertex is missing is that 19299999 and 19300000 are very close.
+ Polygon polygon_1 = {
+ Point(27000000, -18900000),
+ Point(27000000, 20000000),
+ Point(19000000, 20000000),
+ Point(19000000, 19299999),
+ Point(26000000, -18000000),
+ Point(-19000000, -18000000),
+ Point(-27000000, 19300000),
+ Point(-19000000, 19300000),
+ Point(-19000000, 20000000),
+ Point(-28000000, 20000000),
+ Point(-20000000, -18900000),
+ };
+
+ // Maybe this is the same case as the previous, but the missing Voronoi vertex is different.
+ Polygon polygon_2 = {
+ Point(27000000, -18900000),
+ Point(27000000, 20000000),
+ Point(19000000, 20000000),
+ Point(19000000, 19299999),
+ Point(19000000, -18000000), // Just this point is different other points are the same as previous.
+ Point(-19000000, -18000000),
+ Point(-27000000, 19300000),
+ Point(-19000000, 19300000),
+ Point(-19000000, 20000000),
+ Point(-28000000, 20000000),
+ Point(-20000000, -18900000),
+ };
+
+ Geometry::VoronoiDiagram vd_1;
+ Geometry::VoronoiDiagram vd_2;
+ Lines lines_1 = to_lines(polygon_1);
+ Lines lines_2 = to_lines(polygon_2);
+ construct_voronoi(lines_1.begin(), lines_1.end(), &vd_1);
+ construct_voronoi(lines_2.begin(), lines_2.end(), &vd_2);
+#ifdef VORONOI_DEBUG_OUT
+ dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-1-out.svg").c_str(), vd_1, Points(), lines_1);
+ dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-2-out.svg").c_str(), vd_2, Points(), lines_2);
+#endif
+}
+
// In this case, the Voronoi vertex (146873, -146873) is included twice.
// Also, near to those duplicate Voronoi vertices is another Voronoi vertex (146872, -146872).
// Rotating the polygon will help solve this problem, but then there arise three very close Voronoi vertices.