diff --git a/resources/profiles/gCreate.idx b/resources/profiles/gCreate.idx
new file mode 100644
index 000000000..70770916c
--- /dev/null
+++ b/resources/profiles/gCreate.idx
@@ -0,0 +1,3 @@
+min_slic3r_version = 2.4.0-alpha0
+1.0.0 Initial version
+
diff --git a/resources/profiles/gCreate.ini b/resources/profiles/gCreate.ini
new file mode 100644
index 000000000..61d6047ce
--- /dev/null
+++ b/resources/profiles/gCreate.ini
@@ -0,0 +1,1152 @@
+# Print profiles for the gCreate printers.
+#
+# GTL Modified 210706 (at gCreate Shop)
+#
+
+[vendor]
+# Vendor name will be shown by the Config Wizard.
+name = gCreate
+# 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
+# Where to get the updates from?
+config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/gCreate/
+# 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.
+
+
+#Basic methodology
+
+# Common settings are overridden by settings further down the line as they get more specific
+#
+# Common printer settings > Common settings based on layer height > Name displayed on quality dropdown
+#
+# Common filament settings > common filament settings based on type > Specific settings based on vendor
+#
+
+[printer_model:GMAX15P]
+name = gMax 1.5XT Plus
+variants = 0.5; 0.3; 0.4; 0.8; 1.0
+technology = FFF
+family = GMAX
+bed_model = gmax15p_bed.stl
+bed_texture = gmax15p.svg
+default_materials = Generic PLA @GCREATE; Generic PETG @GCREATE; Generic ABS @GCREATE; Prusament PLA @GCREATE; Prusament PETG @GCREATE; Generic TPU 90A @GCREATE; Generic CF PETG @GCREATE; Generic CF Nylon @GCREATE; Generic CF PLA @GCREATE
+
+[printer_model:GMAX2]
+name = gMax 2
+variants = 0.5; 0.3; 0.4; 0.8; 1.0
+technology = FFF
+family = GMAX
+#has to be named (printer)_bed.stl
+bed_model = gmax2_bed.stl
+bed_texture = gmax2.svg
+default_materials = Generic PLA @GCREATE; Generic PETG @GCREATE; Generic ABS @GCREATE; Prusament PLA @GCREATE; Prusament PETG @GCREATE; Generic TPU 90A @GCREATE; Generic CF PETG @GCREATE; Generic CF Nylon @GCREATE; Generic CF PLA @GCREATE
+
+
+[printer_model:GMAX2PRO]
+name = gMax 2 Pro
+variants = 0.5; 0.3; 0.4; 0.8; 1.0
+technology = FFF
+family = GMAX
+#has to be named (printer)_bed.stl
+bed_model = gmax2_bed.stl
+bed_texture = gmax2.svg
+default_materials = Generic PLA @GCREATE; Generic PETG @GCREATE; Generic ABS @GCREATE; Prusament PLA @GCREATE; Prusament PETG @GCREATE; Generic TPU 90A @GCREATE; Generic CF PETG @GCREATE; Generic CF Nylon @GCREATE; Generic CF PLA @GCREATE
+
+[printer_model:GMAX2DUAL2IN1]
+name = gMax 2 Dual 2in1
+variants = 0.5
+technology = FFF
+family = GMAX
+#has to be named (printer)_bed.stl
+bed_model = gmax2_bed.stl
+bed_texture = gmax2.svg
+default_materials = Generic PLA @GCREATE; Generic PETG @GCREATE; Generic ABS @GCREATE; Prusament PLA @GCREATE; Prusament PETG @GCREATE; Generic TPU 90A @GCREATE; Generic CF PETG @GCREATE; Generic CF Nylon @GCREATE; Generic CF PLA @GCREATE
+
+[printer_model:GMAX2DUAL]
+name = gMax 2 Dual Chimera
+variants = 0.5
+technology = FFF
+family = GMAX
+#has to be named (printer)_bed.stl
+bed_model = gmax2_bed.stl
+bed_texture = gmax2.svg
+default_materials = Generic PLA @GCREATE; Generic PETG @GCREATE; Generic ABS @GCREATE; Prusament PLA @GCREATE; Prusament PETG @GCREATE; Generic TPU 90A @GCREATE; Generic CF PETG @GCREATE; Generic CF Nylon @GCREATE; Generic CF PLA @GCREATE
+
+# All presets starting with asterisk, for example *common*, are intermediate and they will
+# not make it into the user interface.
+
+# Common print presets for every printer model. will be overtaken by presets further down that are printer, filament nozzle or layer height specific
+[print:*common*]
+avoid_crossing_perimeters = 0
+bridge_angle = 0
+bridge_flow_ratio = 0.95
+bridge_speed = 35
+brim_width = 0
+clip_multipart_objects = 1
+compatible_printers =
+complete_objects = 0
+default_acceleration = 400
+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
+external_perimeter_speed = 65%
+extra_perimeters = 0
+extruder_clearance_height = 25
+extruder_clearance_radius = 45
+extrusion_width = 0
+fill_angle = 45
+fill_density = 20%
+fill_pattern = 3dhoneycomb
+first_layer_extrusion_width = 0
+first_layer_height = 125%
+first_layer_speed = 65%
+gap_fill_speed = 30
+gcode_comments = 0
+infill_every_layers = 1
+infill_extruder = 1
+infill_extrusion_width = 0
+infill_first = 0
+infill_only_where_needed = 0
+infill_overlap = 25%
+infill_speed = 50
+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 = 15
+notes =
+overhangs = 0
+only_retract_when_crossing_perimeters = 0
+ooze_prevention = 0
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}.gcode
+perimeters = 2
+perimeter_extruder = 1
+perimeter_extrusion_width = 0
+perimeter_speed = 60
+post_process =
+print_settings_id =
+raft_layers = 0
+resolution = 0
+seam_position = nearest
+single_extruder_multi_material_priming = 0
+skirts = 1
+skirt_distance = 2
+skirt_height = 1
+small_perimeter_speed = 50%
+solid_infill_below_area = 0
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0
+solid_infill_speed = 80%
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 0
+support_material_extruder = 0
+support_material_extrusion_width = 0
+support_material_interface_extruder = 0
+support_material_angle = 0
+support_material_buildplate_only = 0
+support_material_enforce_layers = 0
+support_material_contact_distance = 0.2
+support_material_interface_contact_loops = 0
+support_material_interface_layers = 4
+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
+top_solid_infill_speed = 50%
+travel_speed = 100
+wipe_tower = 0
+wipe_tower_bridging = 10
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 75
+wipe_tower_x = 170
+wipe_tower_y = 140
+xy_size_compensation = 0
+
+##################################
+# SET LAYER HEIGHT VARIANTS #
+##################################
+
+#common layer height variants
+
+[print:*0.10mm*]
+inherits = *common*
+layer_height = 0.10
+first_layer_height = 150%
+perimeters = 3
+bottom_solid_layers = 6
+top_solid_layers = 8
+
+[print:*0.15mm*]
+inherits = *common*
+layer_height = 0.15
+first_layer_height = 125%
+perimeters = 3
+bottom_solid_layers = 5
+top_solid_layers = 6
+
+[print:*0.20mm*]
+inherits = *common*
+layer_height = 0.2
+first_layer_height = 125%
+first_layer_speed = 50%
+perimeters = 3
+bottom_solid_layers = 3
+top_solid_layers = 4
+
+
+[print:*0.25mm*]
+inherits = *common*
+layer_height = 0.25
+first_layer_height = 100%
+first_layer_speed = 50%
+top_infill_extrusion_width = 0
+bottom_solid_layers = 3
+top_solid_layers = 4
+
+[print:*0.3mm*]
+inherits = *common*
+layer_height = 0.3
+first_layer_height = 100%
+first_layer_speed = 50%
+top_infill_extrusion_width = 0
+bottom_solid_layers = 3
+top_solid_layers = 4
+
+[print:*0.4mm*]
+inherits = *common*
+layer_height = 0.4
+first_layer_height = 100%
+first_layer_speed = 50%
+top_infill_extrusion_width = 0
+bottom_solid_layers = 3
+top_solid_layers = 4
+
+
+[print:*0.5mm*]
+inherits = *common*
+layer_height = 0.5
+first_layer_height = 100%
+first_layer_speed = 45%
+top_infill_extrusion_width = 0
+bottom_solid_layers = 3
+top_solid_layers = 3
+
+[print:*0.6mm*]
+inherits = *common*
+layer_height = 0.6
+first_layer_height = 100%
+first_layer_speed = 40%
+top_infill_extrusion_width = 0
+bottom_solid_layers = 3
+top_solid_layers = 3
+
+[print:*SLOW*]
+#SPEED
+perimeter_speed = 40
+small_perimeter_speed = 35
+external_perimeter_speed = 35
+infill_speed = 40
+solid_infill_speed = 40
+top_solid_infill_speed = 30
+support_material_speed = 35
+bridge_speed = 35
+gap_fill_speed = 30
+
+[print:*FAST*]
+#SPEED
+perimeter_speed = 70
+small_perimeter_speed = 85%
+external_perimeter_speed = 75%
+infill_speed = 85%
+solid_infill_speed = 70%
+top_solid_infill_speed = 65%
+support_material_speed = 75%
+bridge_speed = 45
+gap_fill_speed = 30
+
+
+#############################################################################
+# SET PRINTER AND NOZZLE SPECIFIC PROFLIES (THESE SHOW INT HE DROPDOWN) #
+#############################################################################
+
+#we can add specific changes for specific printers and nozzle sizes. Just put in conditionals
+# compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/ and printer_model=~/.*GMAX2PRO.*/ and nozzle_diameter[0]==0.5
+
+
+#TEMPLATE
+
+#SPEED SETTINGS
+#[print:0.10mm - Very Thin Layers @GCREATE]
+#perimeter_speed = 100%
+#small_perimeter_speed = 100%
+#external_perimeter_speed = 100%
+#infill_speed = 100%
+#solid_infill_speed = 100%
+#top_solid_infill_speed = 100%
+#support_material_speed = 100%
+#bridge_speed = 100%
+#don't adjust gap speed above 30 or it causes layer shifting
+#gap_fill_speed = 30
+
+#ADVANCED
+#
+
+
+
+[print:0.10mm - Very Thin Layers @GCREATE]
+inherits = *0.10mm*
+#Below works. Will only allow gMax 2 and gMax 2 Pro with specific nozzle sizes
+#compatible_printers_condition = nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5 and printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2.*/
+compatible_printers_condition = (nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.15mm - Thin Layers @GCREATE]
+inherits = *0.15mm*
+#Below works. Will only allow gMax 2 and gMax 2 Pro with specific nozzle sizes
+#compatible_printers_condition = nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5 and printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2.*/
+compatible_printers_condition = (nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.20mm - Standard Layers @GCREATE]
+inherits = *0.20mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.20mm - Standard Layers Slow (PETG and TPU) @GCREATE]
+inherits = *0.20mm*; *SLOW*
+compatible_printers_condition = (nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.20mm - Standard Layers Fast @GCREATE]
+inherits = *0.20mm*; *FAST*
+compatible_printers_condition = (nozzle_diameter[0]==0.3 or nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.25mm - Thick Layers @GCREATE]
+inherits = *0.25mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.30mm - Very Thick Layers @GCREATE]
+inherits = *0.3mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.4 or nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.40mm - High Output Layers @GCREATE]
+inherits = *0.4mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.5 or nozzle_diameter[0]==0.8 or nozzle_diameter[0]==1.0) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.50mm - High Output Layers @GCREATE]
+inherits = *0.5mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.8 or nozzle_diameter[0]==1.0) and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.60mm - High Output Layers @GCREATE]
+inherits = *0.6mm*
+compatible_printers_condition = nozzle_diameter[0]==0.8 or nozzle_diameter[0]==1.0 and (printer_model=~/.*GMAX2PRO.*/ or printer_model=~/.*GMAX2/ or printer_model=~/.*GMAX15P.*/) and ! (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+
+[print:0.20mm - Dual 2in1 @GCREATE]
+inherits = *0.20mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2DUAL2IN1/)
+wipe_tower = 1
+wipe_tower_bridging = 10
+wipe_tower_no_sparse_layers = 1
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 75
+wipe_tower_x = 100
+wipe_tower_y = 300
+
+[print:0.20mm - Dual Chimera @GCREATE]
+inherits = *0.20mm*
+compatible_printers_condition = (nozzle_diameter[0]==0.5) and (printer_model=~/.*GMAX2DUAL/)
+# wipe tower
+wipe_tower = 1
+wipe_tower_bridging = 10
+wipe_tower_no_sparse_layers = 1
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 75
+wipe_tower_x = 100
+wipe_tower_y = 300
+# ooze prevention
+ooze_prevention = 1
+standby_temperature_delta = -15
+
+[print:0.20mm - Dual 2in1 PLA with PVA Support @GCREATE]
+inherits = *0.20mm*; 0.20mm - Dual 2in1 @GCREATE
+compatible_printers_condition = (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/)
+avoid_crossing_perimeters = 0
+avoid_crossing_perimeters_max_detour = 0
+bottom_fill_pattern = monotonic
+bottom_solid_layers = 3
+bottom_solid_min_thickness = 0
+bridge_acceleration = 0
+bridge_angle = 0
+bridge_flow_ratio = 1
+bridge_speed = 60
+brim_width = 0
+clip_multipart_objects = 1
+compatible_printers =
+complete_objects = 0
+default_acceleration = 400
+dont_support_bridges = 0
+draft_shield = 0
+elefant_foot_compensation = 0.2
+ensure_vertical_shell_thickness = 0
+external_perimeter_extrusion_width = 0
+external_perimeter_speed = 75%
+external_perimeters_first = 0
+extra_perimeters = 1
+extruder_clearance_height = 20
+extruder_clearance_radius = 20
+extrusion_width = 0
+fill_angle = 45
+first_layer_acceleration = 0
+first_layer_extrusion_width = 0
+first_layer_height = 0.23
+first_layer_speed = 35
+gap_fill_speed = 30
+gcode_comments = 0
+gcode_label_objects = 1
+infill_acceleration = 0
+infill_anchor = 600%
+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 = 25%
+infill_speed = 80
+interface_shells = 0
+ironing = 0
+ironing_flowrate = 15%
+ironing_spacing = 0.1
+ironing_speed = 15
+ironing_type = top
+max_print_speed = 80
+max_volumetric_speed = 0
+min_skirt_length = 15
+notes =
+only_retract_when_crossing_perimeters = 1
+ooze_prevention = 0
+output_filename_format = [input_filename_base].gcode
+overhangs = 1
+perimeter_acceleration = 0
+perimeter_extruder = 1
+perimeter_extrusion_width = 0
+perimeter_speed = 65
+perimeters = 4
+post_process =
+print_settings_id = 0.20mm - Dual 2in1 @GCREATE PLA PVA Support
+raft_layers = 0
+resolution = 0
+seam_position = aligned
+single_extruder_multi_material_priming = 0
+skirt_distance = 6
+skirt_height = 1
+skirts = 1
+slice_closing_radius = 0.049
+small_perimeter_speed = 30
+solid_infill_below_area = 70
+solid_infill_every_layers = 0
+solid_infill_extruder = 1
+solid_infill_extrusion_width = 0
+solid_infill_speed = 35
+spiral_vase = 0
+standby_temperature_delta = -5
+support_material = 1
+support_material_angle = 0
+support_material_auto = 1
+support_material_buildplate_only = 0
+support_material_contact_distance = 0
+support_material_enforce_layers = 0
+support_material_extruder = 2
+support_material_extrusion_width = 0
+support_material_interface_contact_loops = 0
+support_material_interface_extruder = 2
+support_material_interface_layers = 4
+support_material_interface_spacing = 0
+support_material_interface_speed = 90%
+support_material_pattern = rectilinear-grid
+support_material_spacing = 3
+support_material_speed = 65
+support_material_synchronize_layers = 1
+support_material_threshold = 0
+support_material_with_sheath = 1
+support_material_xy_spacing = 0
+thin_walls = 1
+threads = 8
+top_fill_pattern = monotonic
+top_infill_extrusion_width = 0
+top_solid_infill_speed = 35
+top_solid_layers = 4
+top_solid_min_thickness = 0
+travel_speed = 130
+wipe_tower = 1
+wipe_tower_bridging = 20
+wipe_tower_no_sparse_layers = 0
+wipe_tower_rotation_angle = 0
+wipe_tower_width = 75
+wipe_tower_x = 50
+wipe_tower_y = 400
+
+
+
+##################################
+# SET FILAMENT VARIANTS #
+##################################
+
+# TEMPLATE
+
+#[filament:*PLA*]
+#inherits = *common*
+
+#filament_type = PLA
+#filament_density = 1.24
+#filament_cost = 20
+
+#first_layer_bed_temperature = 60
+#first_layer_temperature = 200
+#temperature = 200
+#bed_temperature = 60
+
+#fan_always_on = 1
+#cooling = 1
+#disable_fan_first_layers = 1
+#max_fan_speed = 90
+#min_fan_speed = 90
+#bridge_fan_speed = 75
+
+#fan_below_layer_time = 15
+#slowdown_below_layer_time = 10
+
+#compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+
+# Common filament preset across all filaments
+[filament:*common*]
+cooling = 0
+extrusion_multiplier = 1
+filament_diameter = 1.75
+filament_notes = ""
+filament_settings_id = ""
+min_print_speed = 15
+slowdown_below_layer_time = 10
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+
+# Common filament preset across all PLA filaments
+[filament:*PLA*]
+inherits = *common*
+bed_temperature = 60
+fan_below_layer_time = 15
+filament_colour = #FF3232
+filament_max_volumetric_speed = 0
+filament_type = PLA
+filament_density = 1.24
+filament_cost = 20
+first_layer_bed_temperature = 60
+first_layer_temperature = 200
+
+filament_cooling_moves = 0
+filament_loading_speed = 30
+filament_loading_speed_start = 30
+filament_ramming_parameters = "0"
+filament_unload_time = 0
+filament_unloading_speed = 30
+filament_unloading_speed_start = 30
+
+fan_always_on = 1
+cooling = 1
+disable_fan_first_layers = 1
+max_fan_speed = 80
+min_fan_speed = 40
+bridge_fan_speed = 80
+temperature = 200
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*PET*]
+inherits = *common*
+bed_temperature = 70
+cooling = 1
+disable_fan_first_layers = 3
+fan_below_layer_time = 15
+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 = 50
+temperature = 240
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*ABS*]
+inherits = *common*
+bed_temperature = 70
+cooling = 0
+disable_fan_first_layers = 3
+fan_below_layer_time = 15
+filament_colour = #FF8000
+filament_max_volumetric_speed = 8
+filament_type = ABS
+filament_density = 1.27
+filament_cost = 30
+first_layer_bed_temperature = 80
+first_layer_temperature = 235
+fan_always_on = 0
+max_fan_speed = 50
+min_fan_speed = 20
+bridge_fan_speed = 50
+temperature = 235
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*TPU90A*]
+inherits = *common*
+filament_type = TPU
+
+filament_density = 1.20
+filament_cost = 25
+
+first_layer_bed_temperature = 60
+first_layer_temperature = 215
+temperature = 215
+bed_temperature = 60
+
+fan_always_on = 1
+cooling = 1
+disable_fan_first_layers = 1
+max_fan_speed = 50
+min_fan_speed = 35
+bridge_fan_speed = 60
+
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*CFPETG*]
+inherits = *common*; *PET*
+filament_type = Carbon Fiber
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*CFNYLON*]
+inherits = *common*
+filament_type = Carbon Fiber
+
+#need to add speed, cooling, retraction and brim
+temperature = 250
+bed_temperature = 65
+bridge_fan_speed = 50
+first_layer_temperature = 250
+first_layer_bed_temperature = 65
+#filament_cost = 24.99
+filament_density = 1.06
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*CFPLA*]
+inherits = *common*
+filament_type = Carbon Fiber
+
+#need to add speed, cooling, retraction and brim
+
+#temperature = 245
+#bed_temperature = 70
+#first_layer_temperature = 245
+#first_layer_bed_temperature = 70
+#filament_cost = 24.99
+#filament_density = 1.27
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+[filament:*WOODFILLPLA*]
+inherits = *common*; *PLA*
+
+#need to add speed, cooling, retraction and brim
+
+#temperature = 245
+#bed_temperature = 70
+#first_layer_temperature = 245
+#first_layer_bed_temperature = 70
+#filament_cost = 24.99
+#filament_density = 1.27
+
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_GCREATE.*/
+
+#specific filament settings per brand. These are the names displayed in the list
+[filament:Prusament PLA @GCREATE]
+inherits = *PLA*
+filament_vendor = Prusa Polymers
+temperature = 205
+bed_temperature = 60
+first_layer_temperature = 215
+first_layer_bed_temperature = 50
+filament_cost = 24.99
+filament_density = 1.24
+
+[filament:Prusament PETG @GCREATE]
+inherits = *PET*
+filament_vendor = Prusa Polymers
+temperature = 245
+bed_temperature = 70
+bridge_fan_speed = 50
+first_layer_temperature = 245
+first_layer_bed_temperature = 70
+filament_cost = 24.99
+filament_density = 1.27
+
+[filament:Generic ABS @GCREATE]
+inherits = *ABS*
+filament_vendor = Generic
+
+[filament:Generic PLA @GCREATE]
+inherits = *PLA*
+filament_vendor = Generic
+
+[filament:Generic PLA no Heated Bed @GCREATE]
+inherits = *PLA*
+filament_vendor = Generic
+# set bed to zero
+first_layer_temperature = 205
+temperature = 205
+first_layer_bed_temperature = 0
+bed_temperature = 0
+
+[filament:Generic PETG @GCREATE]
+inherits = *PET*
+filament_vendor = Generic
+temperature = 230
+bed_temperature = 70
+first_layer_temperature = 235
+first_layer_bed_temperature = 70
+
+[filament:Atomic PLA @GCREATE]
+inherits = *PLA*
+filament_vendor = Atomic Filament
+temperature = 215
+first_layer_temperature = 205
+bed_temperature = 60
+
+[filament:Push Plastic PLA @GCREATE]
+inherits = *PLA*
+filament_vendor = Push Plastic
+temperature = 200
+bed_temperature = 60
+
+[filament:HT PLA @GCREATE]
+inherits = *PLA*
+filament_vendor = ProtoPasta
+temperature = 250
+bed_temperature = 70
+
+[filament:Generic TPU 90A @GCREATE]
+inherits = *TPU90A*
+filament_vendor = Generic
+
+
+[filament:Generic CF PETG @GCREATE]
+inherits = *CFPETG*
+filament_vendor = Generic
+
+[filament:Generic CF Nylon @GCREATE]
+inherits = *CFNYLON*
+filament_vendor = Generic
+
+[filament:Generic CF PLA @GCREATE]
+inherits = *CFPLA*
+filament_vendor = Generic
+
+[filament:ColorFabb Woodfill PLA @GCREATE]
+inherits = *WOODFILLPLA*
+filament_vendor = ColorFabb
+
+
+
+[filament:Generic PVA @GCREATE - PLA and PVA Support]
+bed_temperature = 0
+bridge_fan_speed = 75
+#compatible_printers_condition = (printer_model=~/.*GMAX2DUAL2IN1.*/ or printer_model=~/.*GMAX2DUAL.*/
+end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
+extrusion_multiplier = 1
+fan_always_on = 1
+fan_below_layer_time = 15
+filament_colour = #F5F2C4
+filament_cooling_final_speed = 3.4
+filament_cooling_initial_speed = 2.2
+filament_cooling_moves = 0
+filament_loading_speed = 30
+filament_loading_speed_start = 30
+filament_max_volumetric_speed = 0
+filament_minimal_purge_on_wipe_tower = 7
+filament_ramming_parameters = "0"
+filament_settings_id = "Generic PVA Support @GCREATE"
+filament_soluble = 1
+filament_toolchange_delay = 0
+filament_type = PVA
+filament_unload_time = 0
+filament_unloading_speed = 30
+filament_unloading_speed_start = 30
+filament_vendor = Generic
+first_layer_temperature = 195
+inherits = Generic PLA @GCREATE
+max_fan_speed = 80
+min_fan_speed = 50
+min_print_speed = 15
+slowdown_below_layer_time = 10
+start_filament_gcode = "; Filament gcode\n"
+temperature = 195
+
+#################################
+# SET COMMON PRINTER SETTINGS #
+#################################
+
+# Common printer preset
+[printer:*common*]
+printer_technology = FFF
+before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n
+extruder_colour = #FFFF00
+extruder_offset = 0x0
+gcode_flavor = marlin
+silent_mode = 0
+remaining_times = 0
+machine_max_acceleration_e = 1000
+machine_max_acceleration_extruding = 2000
+machine_max_acceleration_retracting = 1500
+machine_max_acceleration_x = 800
+machine_max_acceleration_y = 800
+machine_max_acceleration_z = 15
+machine_max_feedrate_e = 120
+machine_max_feedrate_x = 500
+machine_max_feedrate_y = 500
+machine_max_feedrate_z = 10
+machine_max_jerk_e = 2.5
+machine_max_jerk_x = 3
+machine_max_jerk_y = 3
+machine_max_jerk_z = 0.4
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
+retract_before_travel = 1
+retract_before_wipe = 0%
+retract_layer_change = 1
+retract_length = 1
+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 = 70
+single_extruder_multi_material = 0
+thumbnails = 95x95
+use_firmware_retraction = 0
+use_relative_e_distances = 1
+use_volumetric_e = 0
+variable_layer_height = 1
+wipe = 1
+z_offset = 0
+
+
+###################################
+# SET PRINTER SPECIFIC PROFILES #
+###################################
+
+[printer:*gCreate gMax 2*]
+inherits = *common*
+printer_model = GMAX2
+#printer_variant = 0.5
+max_layer_height = 0.7
+min_layer_height = 0.15
+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_GCREATE\nPRINTER_MODEL_GMAX2
+bed_shape = 0x0,457x0,457x457,0x457
+max_print_height = 610
+machine_max_acceleration_e = 5000
+machine_max_acceleration_extruding = 500
+machine_max_acceleration_retracting = 1000
+machine_max_acceleration_x = 600
+machine_max_acceleration_y = 600
+machine_max_acceleration_z = 15
+machine_max_feedrate_e = 60
+machine_max_feedrate_x = 500
+machine_max_feedrate_y = 500
+machine_max_feedrate_z = 8
+machine_max_jerk_e = 5
+machine_max_jerk_x = 8
+machine_max_jerk_y = 8
+machine_max_jerk_z = 0.4
+machine_min_extruding_rate = 0
+machine_min_travel_rate = 0
+#nozzle_diameter = 0.7
+retract_before_travel = 2
+retract_length = 0.75
+retract_speed = 70
+deretract_speed = 40
+retract_before_wipe = 70%
+default_print_profile = 0.20mm - Standard Layers @GCREATE
+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 all\nG92 E0.0
+end_gcode = M104 S0 T0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y170 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+min(layer_z+70, max_print_height-10)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
+
+#[printer:*abl*]
+#start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp#\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed #temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 #E0.0
+
+[printer:*gCreate gMax 2 Pro*]
+inherits = *common*
+printer_model = GMAX2PRO
+#printer_variant = 0.5
+max_layer_height = 0.7
+min_layer_height = 0.08
+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_GCREATE\nPRINTER_MODEL_GMAX2PRO
+bed_shape = 0x0,457x0,457x457,0x457
+max_print_height = 610
+
+default_print_profile = 0.20mm - Standard Layers @GCREATE
+
+[printer:*gCreate gMax 1.5XT Plus*]
+inherits = *common*
+printer_model = GMAX15P
+#printer_variant = 0.5
+max_layer_height = 0.6
+min_layer_height = 0.08
+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_GCREATE\nPRINTER_MODEL_GMAX15P
+bed_shape = 0x0,410x0,410x410,0x410
+max_print_height = 533
+
+default_print_profile = 0.20mm - Standard Layers @GCREATE
+
+[printer:*gCreate gMax 2 Dual 2in1*]
+inherits = *common*
+printer_model = GMAX2DUAL2IN1
+max_layer_height = 0.7
+min_layer_height = 0.08
+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_GCREATE\nPRINTER_MODEL_GMAX2DUAL2IN1
+start_gcode = G90 ;\n G28 ;\n G1 Z5 F5000
+bed_shape = 0x0,457x0,457x457,0x457
+max_print_height = 610
+default_print_profile = 0.20mm - Standard Layers @GCREATE
+single_extruder_multi_material = 1
+#cooling tube retraction
+cooling_tube_retraction = 30
+cooling_tube_length = 6
+parking_pos_retraction = 30
+extra_loading_move = -1
+#multi tool settings
+extruder_colour = #FF3333;#0000CC
+extruder_offset = 0x0,0x0
+retract_length_toolchange = 30;30
+
+
+[printer:*gCreate gMax 2 Dual Chimera*]
+inherits = *common*
+printer_model = GMAX2DUAL
+max_layer_height = 0.7
+min_layer_height = 0.08
+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_GCREATE\nPRINTER_MODEL_GMAX2DUAL
+start_gcode = G90\nG28\nG1 Z5 F5000\nM218 T1 X20 Y0 ; Set second extruder offset
+end_gcode = M104 S0 T0 ; turn off temperature\nM104 S0 T1 ; turn off 2nd extruder\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y170 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+min(layer_z+70, max_print_height-10)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
+bed_shape = 0x0,457x0,457x457,0x457
+max_print_height = 610
+default_print_profile = 0.20mm - Standard Layers @GCREATE
+single_extruder_multi_material = 0
+#multi tool settings
+extruder_colour = #FF3333;#0000CC
+extruder_offset = 0x0,20x0
+retract_length_toolchange = 8,8
+retract_speed = 70,70
+
+##############################################
+# SET NOZZLE DIAMETER VARIANTS PER PRINTER #
+##############################################
+
+#these are the names and printers displayed in the drop down menus when selecting profiles
+
+#####################################
+#gMax 1.5 XT+ and gMax 1.5+ profiles#
+#####################################
+
+
+[printer:gMax 1.5XT Plus - 0.3mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 1.5XT Plus*
+printer_variant = 0.3
+nozzle_diameter = 0.3
+max_layer_height = 0.25
+min_layer_height = 0.08
+
+[printer:gMax 1.5XT Plus - 0.4mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 1.5XT Plus*
+printer_variant = 0.4
+nozzle_diameter = 0.4
+max_layer_height = 0.32
+min_layer_height = 0.12
+#default_print_profile = 0.15mm - Thin Layers @GCREATE @0.4 nozzle
+
+[printer:gMax 1.5XT Plus - 0.5mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 1.5XT Plus*
+printer_variant = 0.5
+nozzle_diameter = 0.5
+max_layer_height = 0.4
+min_layer_height = 0.15
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+#default_print_profile = 0.20mm - Normal Layers @GCREATE @0.5 nozzle
+
+[printer:gMax 1.5XT Plus - 0.8mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 1.5XT Plus*
+printer_variant = 0.8
+nozzle_diameter = 0.8
+max_layer_height = 0.7
+min_layer_height = 0.25
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+[printer:gMax 1.5XT Plus - 1.0mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 1.5XT Plus*
+printer_variant = 1.0
+nozzle_diameter = 1.0
+max_layer_height = 0.8
+min_layer_height = 0.3
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+
+#################
+#gMax 2 profiles#
+#################
+
+[printer:gMax 2 - 0.3mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2*
+printer_variant = 0.3
+nozzle_diameter = 0.3
+max_layer_height = 0.25
+min_layer_height = 0.08
+
+[printer:gMax 2 - 0.4mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2*
+printer_variant = 0.4
+nozzle_diameter = 0.4
+max_layer_height = 0.32
+min_layer_height = 0.12
+#default_print_profile = 0.15mm - Thin Layers @GCREATE @0.4 nozzle
+
+[printer:gMax 2 - 0.5mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2*
+printer_variant = 0.5
+nozzle_diameter = 0.5
+max_layer_height = 0.4
+min_layer_height = 0.15
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+#default_print_profile = 0.20mm - Normal Layers @GCREATE @0.5 nozzle
+
+[printer:gMax 2 - 0.8mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2*
+printer_variant = 0.8
+nozzle_diameter = 0.8
+max_layer_height = 0.7
+min_layer_height = 0.25
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+[printer:gMax 2 - 1.0mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2*
+printer_variant = 1.0
+nozzle_diameter = 1.0
+max_layer_height = 0.8
+min_layer_height = 0.3
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+
+#####################
+#gMax 2 Pro profiles#
+#####################
+
+[printer:gMax 2 Pro - 0.3mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Pro*
+printer_variant = 0.3
+nozzle_diameter = 0.3
+max_layer_height = 0.25
+min_layer_height = 0.08
+
+[printer:gMax 2 Pro - 0.4mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Pro*
+printer_variant = 0.4
+nozzle_diameter = 0.4
+max_layer_height = 0.32
+min_layer_height = 0.12
+#default_print_profile = 0.15mm - Thin Layers @GCREATE @0.4 nozzle
+
+[printer:gMax 2 Pro - 0.5mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Pro*
+printer_variant = 0.5
+nozzle_diameter = 0.5
+max_layer_height = 0.4
+min_layer_height = 0.15
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+#default_print_profile = 0.20mm - Normal Layers @GCREATE @0.5 nozzle
+
+[printer:gMax 2 Pro - 0.8mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Pro*
+printer_variant = 0.8
+nozzle_diameter = 0.8
+max_layer_height = 0.7
+min_layer_height = 0.25
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+[printer:gMax 2 Pro - 1.0mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Pro*
+printer_variant = 1.0
+nozzle_diameter = 1.0
+max_layer_height = 0.8
+min_layer_height = 0.3
+#default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI
+#retract_length = 3.5
+
+###########################
+#gMax 2 Dual 2in1 profiles#
+###########################
+
+[printer:gMax 2 Dual 2in1 - 0.5, 0.5mm nozzle]
+#match printer name above
+inherits = *gCreate gMax 2 Dual 2in1*
+printer_variant = 0.5
+nozzle_diameter = 0.5, 0.5
+max_layer_height = 0.4
+min_layer_height = 0.15
+
+##############################
+#gMax 2 Dual Chimera profiles#
+##############################
+
+[printer:gMax 2 Dual Chimera - 0.5, 0.5mm nozzle]
+inherits = *gCreate gMax 2 Dual Chimera*
+printer_variant = 0.5
+nozzle_diameter = 0.5, 0.5
+max_layer_height = 0.4
+min_layer_height = 0.15
diff --git a/resources/profiles/gCreate/GMAX15P_thumbnail.png b/resources/profiles/gCreate/GMAX15P_thumbnail.png
new file mode 100644
index 000000000..345d87386
Binary files /dev/null and b/resources/profiles/gCreate/GMAX15P_thumbnail.png differ
diff --git a/resources/profiles/gCreate/GMAX2DUAL2IN1_thumbnail.png b/resources/profiles/gCreate/GMAX2DUAL2IN1_thumbnail.png
new file mode 100644
index 000000000..6f08ab8c9
Binary files /dev/null and b/resources/profiles/gCreate/GMAX2DUAL2IN1_thumbnail.png differ
diff --git a/resources/profiles/gCreate/GMAX2DUAL_thumbnail.png b/resources/profiles/gCreate/GMAX2DUAL_thumbnail.png
new file mode 100644
index 000000000..7d24f5b99
Binary files /dev/null and b/resources/profiles/gCreate/GMAX2DUAL_thumbnail.png differ
diff --git a/resources/profiles/gCreate/GMAX2PRO_thumbnail.png b/resources/profiles/gCreate/GMAX2PRO_thumbnail.png
new file mode 100644
index 000000000..6a7efe7bf
Binary files /dev/null and b/resources/profiles/gCreate/GMAX2PRO_thumbnail.png differ
diff --git a/resources/profiles/gCreate/GMAX2_thumbnail.png b/resources/profiles/gCreate/GMAX2_thumbnail.png
new file mode 100644
index 000000000..91d765679
Binary files /dev/null and b/resources/profiles/gCreate/GMAX2_thumbnail.png differ
diff --git a/resources/profiles/gCreate/gmax15p.svg b/resources/profiles/gCreate/gmax15p.svg
new file mode 100644
index 000000000..5ecaa0fea
--- /dev/null
+++ b/resources/profiles/gCreate/gmax15p.svg
@@ -0,0 +1 @@
+
diff --git a/resources/profiles/gCreate/gmax15p_bed.stl b/resources/profiles/gCreate/gmax15p_bed.stl
new file mode 100644
index 000000000..a9c67ddf5
Binary files /dev/null and b/resources/profiles/gCreate/gmax15p_bed.stl differ
diff --git a/resources/profiles/gCreate/gmax2.svg b/resources/profiles/gCreate/gmax2.svg
new file mode 100644
index 000000000..5ecaa0fea
--- /dev/null
+++ b/resources/profiles/gCreate/gmax2.svg
@@ -0,0 +1 @@
+
diff --git a/resources/profiles/gCreate/gmax2_bed.stl b/resources/profiles/gCreate/gmax2_bed.stl
new file mode 100644
index 000000000..622d2ec8f
Binary files /dev/null and b/resources/profiles/gCreate/gmax2_bed.stl differ
diff --git a/src/libslic3r/MutablePriorityQueue.hpp b/src/libslic3r/MutablePriorityQueue.hpp
index b20bf60ea..68cd01859 100644
--- a/src/libslic3r/MutablePriorityQueue.hpp
+++ b/src/libslic3r/MutablePriorityQueue.hpp
@@ -2,11 +2,15 @@
#define slic3r_MutablePriorityQueue_hpp_
#include
+#include
template
class MutablePriorityQueue
{
public:
+ static_assert(std::is_trivially_copyable::value, "Template argument T must be a trivially copiable type in class template MutablePriorityQueue");
+
+ // It is recommended to use make_mutable_priority_queue() for construction.
MutablePriorityQueue(IndexSetter &&index_setter, LessPredicate &&less_predicate) :
m_index_setter(std::forward(index_setter)),
m_less_predicate(std::forward(less_predicate))
@@ -24,6 +28,8 @@ public:
size_t size() const { return m_heap.size(); }
bool empty() const { return m_heap.empty(); }
+ T& operator[](std::size_t idx) noexcept { return m_heap[idx]; }
+ const T& operator[](std::size_t idx) const noexcept { return m_heap[idx]; }
using iterator = typename std::vector::iterator;
using const_iterator = typename std::vector::const_iterator;
@@ -139,10 +145,10 @@ inline void MutablePriorityQueue
+struct SkipHeapAddressing
+{
+public:
+ static const constexpr std::size_t block_size = blocking;
+ static const constexpr std::size_t block_mask = block_size - 1;
+ static_assert((block_size & block_mask) == 0U, "block size must be 2^n for some integer n");
+
+ static inline std::size_t child_of(std::size_t node_no) noexcept {
+ if (! is_block_leaf(node_no))
+ // If not a leaf, then it is sufficient to just traverse down inside a miniheap.
+ // The following line is equivalent to, but quicker than
+ // return block_base(node_no) + 2 * block_offset(node_no);
+ return node_no + block_offset(node_no);
+ // Otherwise skip to a root of a child miniheap.
+ return (block_base(node_no) + 1 + child_no(node_no) * 2) * block_size + 1;
+ }
+
+ static inline std::size_t parent_of(std::size_t node_no) noexcept {
+ auto const node_root = block_base(node_no); // 16
+ if (! is_block_root(node_no))
+ // If not a block (miniheap) root, then it is sufficient to just traverse up inside a miniheap.
+ return node_root + block_offset(node_no) / 2;
+ // Otherwise skipping from a root of one miniheap into leaf of another miniheap.
+ // Address of a parent miniheap block. One miniheap branches at (block_size / 2) leaves to (block_size) miniheaps.
+ auto const parent_base = block_base(node_root / block_size - 1); // 0
+ // Index of a leaf of a parent miniheap, which is a parent of node_no.
+ auto const child = ((node_no - block_size) / block_size - parent_base) / 2;
+ return
+ // Address of a parent miniheap
+ parent_base +
+ // Address of a leaf of a parent miniheap
+ block_size / 2 + child; // 30
+ }
+
+ // Leafs are stored inside the second half of a block.
+ static inline bool is_block_leaf(std::size_t node_no) noexcept { return (node_no & (block_size >> 1)) != 0U; }
+ // Unused space aka padding to facilitate quick addressing.
+ static inline bool is_padding (std::size_t node_no) noexcept { return block_offset(node_no) == 0U; }
+// Following methods are internal, but made public for unit tests.
+//private:
+ // Address is a root of a block (of a miniheap).
+ static inline bool is_block_root(std::size_t node_no) noexcept { return block_offset(node_no) == 1U; }
+ // Offset inside a block (inside a miniheap).
+ static inline std::size_t block_offset (std::size_t node_no) noexcept { return node_no & block_mask; }
+ // Base address of a block (a miniheap).
+ static inline std::size_t block_base (std::size_t node_no) noexcept { return node_no & ~block_mask; }
+ // Index of a leaf.
+ static inline std::size_t child_no (std::size_t node_no) noexcept { assert(is_block_leaf(node_no)); return node_no & (block_mask >> 1); }
+};
+
+// Cache friendly variant of MutablePriorityQueue, implemented as a binary heap of binary miniheaps,
+// building upon SkipHeapAddressing.
+template
+class MutableSkipHeapPriorityQueue
+{
+public:
+ static_assert(std::is_trivially_copyable::value, "Template argument T must be a trivially copiable type in class template MutableSkipHeapPriorityQueue");
+ using address = SkipHeapAddressing;
+
+ // It is recommended to use make_miniheap_mutable_priority_queue() for construction.
+ MutableSkipHeapPriorityQueue(IndexSetter &&index_setter, LessPredicate &&less_predicate) :
+ m_index_setter(std::forward(index_setter)),
+ m_less_predicate(std::forward(less_predicate))
+ {}
+ ~MutableSkipHeapPriorityQueue() { clear(); }
+
+ void clear();
+ // Reserve one unused element per miniheap.
+ void reserve(size_t cnt) { m_heap.reserve(cnt + ((cnt + (address::block_size - 1)) / (address::block_size - 1))); }
+ void push(const T &item);
+ void push(T &&item);
+ void pop();
+ T& top() { return m_heap[1]; }
+ void remove(size_t idx);
+ void update(size_t idx) { assert(! address::is_padding(idx)); T item = m_heap[idx]; remove(idx); push(item); }
+ // There is one padding element storead at each miniheap, thus lower the number of elements by the number of miniheaps.
+ size_t size() const noexcept { return m_heap.size() - (m_heap.size() + address::block_size - 1) / address::block_size; }
+ bool empty() const { return m_heap.empty(); }
+ T& operator[](std::size_t idx) noexcept { assert(! address::is_padding(idx)); return m_heap[idx]; }
+ const T& operator[](std::size_t idx) const noexcept { assert(! address::is_padding(idx)); return m_heap[idx]; }
+
+protected:
+ void update_heap_up(size_t top, size_t bottom);
+ void update_heap_down(size_t top, size_t bottom);
+ void pop_back() noexcept {
+ assert(m_heap.size() > 1);
+ assert(! address::is_padding(m_heap.size() - 1));
+ m_heap.pop_back();
+ if (address::is_padding(m_heap.size() - 1))
+ m_heap.pop_back();
+ }
+
+private:
+ std::vector m_heap;
+ IndexSetter m_index_setter;
+ LessPredicate m_less_predicate;
+};
+
+template
+MutableSkipHeapPriorityQueue
+ make_miniheap_mutable_priority_queue(IndexSetter &&index_setter, LessPredicate &&less_predicate)
+{
+ return MutableSkipHeapPriorityQueue(
+ std::forward(index_setter), std::forward(less_predicate));
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::clear()
+{
+#ifdef NDEBUG
+ // Only mark as removed from the queue in release mode, if configured so.
+ if (ResetIndexWhenRemoved)
+#endif /* NDEBUG */
+ {
+ for (size_t idx = 0; idx < m_heap.size(); ++ idx)
+ // Mark as removed from the queue.
+ if (! address::is_padding(idx))
+ m_index_setter(m_heap[idx], std::numeric_limits::max());
+ }
+ m_heap.clear();
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::push(const T &item)
+{
+ if (address::is_padding(m_heap.size()))
+ m_heap.emplace_back(T());
+ size_t idx = m_heap.size();
+ m_heap.emplace_back(item);
+ m_index_setter(m_heap.back(), idx);
+ update_heap_up(1, idx);
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::push(T &&item)
+{
+ if (address::is_padding(m_heap.size()))
+ m_heap.emplace_back(T());
+ size_t idx = m_heap.size();
+ m_heap.emplace_back(std::move(item));
+ m_index_setter(m_heap.back(), idx);
+ update_heap_up(1, idx);
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::pop()
+{
+ assert(! m_heap.empty());
+#ifdef NDEBUG
+ // Only mark as removed from the queue in release mode, if configured so.
+ if (ResetIndexWhenRemoved)
+#endif /* NDEBUG */
+ {
+ // Mark as removed from the queue.
+ m_index_setter(m_heap.front(), std::numeric_limits::max());
+ }
+ // Zero'th element is padding, thus non-empty queue must have at least two elements.
+ if (m_heap.size() > 2) {
+ m_heap[1] = m_heap.back();
+ this->pop_back();
+ m_index_setter(m_heap[1], 1);
+ update_heap_down(1, m_heap.size() - 1);
+ } else
+ m_heap.clear();
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::remove(size_t idx)
+{
+ assert(idx < m_heap.size());
+ assert(! address::is_padding(idx));
+#ifdef NDEBUG
+ // Only mark as removed from the queue in release mode, if configured so.
+ if (ResetIndexWhenRemoved)
+#endif /* NDEBUG */
+ {
+ // Mark as removed from the queue.
+ m_index_setter(m_heap[idx], std::numeric_limits::max());
+ }
+ if (idx + 1 == m_heap.size()) {
+ this->pop_back();
+ return;
+ }
+ m_heap[idx] = m_heap.back();
+ m_index_setter(m_heap[idx], idx);
+ this->pop_back();
+ update_heap_down(idx, m_heap.size() - 1);
+ update_heap_up(1, idx);
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::update_heap_up(size_t top, size_t bottom)
+{
+ assert(! address::is_padding(top));
+ assert(! address::is_padding(bottom));
+ size_t childIdx = bottom;
+ T *child = &m_heap[childIdx];
+ for (;;) {
+ size_t parentIdx = address::parent_of(childIdx);
+ if (childIdx == 1 || parentIdx < top)
+ break;
+ T *parent = &m_heap[parentIdx];
+ // switch nodes
+ if (! m_less_predicate(*parent, *child)) {
+ T tmp = *parent;
+ m_index_setter(tmp, childIdx);
+ m_index_setter(*child, parentIdx);
+ m_heap[parentIdx] = *child;
+ m_heap[childIdx] = tmp;
+ }
+ // shift up
+ childIdx = parentIdx;
+ child = parent;
+ }
+}
+
+template
+inline void MutableSkipHeapPriorityQueue::update_heap_down(size_t top, size_t bottom)
+{
+ assert(! address::is_padding(top));
+ assert(! address::is_padding(bottom));
+ size_t parentIdx = top;
+ T *parent = &m_heap[parentIdx];
+ for (;;) {
+ size_t childIdx = address::child_of(parentIdx);
+ if (childIdx > bottom)
+ break;
+ T *child = &m_heap[childIdx];
+ size_t child2Idx = childIdx + (address::is_block_leaf(parentIdx) ? address::block_size : 1);
+ if (child2Idx <= bottom) {
+ T *child2 = &m_heap[child2Idx];
+ if (! m_less_predicate(*child, *child2)) {
+ child = child2;
+ childIdx = child2Idx;
+ }
+ }
+ if (m_less_predicate(*parent, *child))
+ return;
+ // switch nodes
+ T tmp = *parent;
+ m_index_setter(tmp, childIdx);
+ m_index_setter(*child, parentIdx);
+ m_heap[parentIdx] = *child;
+ m_heap[childIdx] = tmp;
+ // shift down
+ parentIdx = childIdx;
+ parent = child;
+ }
+}
+
#endif /* slic3r_MutablePriorityQueue_hpp_ */
diff --git a/tests/libslic3r/CMakeLists.txt b/tests/libslic3r/CMakeLists.txt
index 5a4203ea0..575878cf2 100644
--- a/tests/libslic3r/CMakeLists.txt
+++ b/tests/libslic3r/CMakeLists.txt
@@ -12,6 +12,7 @@ add_executable(${_TEST_NAME}_tests
test_placeholder_parser.cpp
test_polygon.cpp
test_mutable_polygon.cpp
+ test_mutable_priority_queue.cpp
test_stl.cpp
test_meshsimplify.cpp
test_meshboolean.cpp
diff --git a/tests/libslic3r/test_mutable_priority_queue.cpp b/tests/libslic3r/test_mutable_priority_queue.cpp
new file mode 100644
index 000000000..83ac28793
--- /dev/null
+++ b/tests/libslic3r/test_mutable_priority_queue.cpp
@@ -0,0 +1,330 @@
+#include
+
+#include
+
+#include "libslic3r/MutablePriorityQueue.hpp"
+
+// based on https://raw.githubusercontent.com/rollbear/prio_queue/master/self_test.cpp
+// original source Copyright Björn Fahller 2015, Boost Software License, Version 1.0, http://www.boost.org/LICENSE_1_0.txt
+
+TEST_CASE("Skip addressing", "[MutableSkipHeapPriorityQueue]") {
+ using skip_addressing = SkipHeapAddressing<8>;
+ SECTION("block root") {
+ REQUIRE(skip_addressing::is_block_root(1));
+ REQUIRE(skip_addressing::is_block_root(9));
+ REQUIRE(skip_addressing::is_block_root(17));
+ REQUIRE(skip_addressing::is_block_root(73));
+ REQUIRE(! skip_addressing::is_block_root(2));
+ REQUIRE(! skip_addressing::is_block_root(3));
+ REQUIRE(! skip_addressing::is_block_root(4));
+ REQUIRE(! skip_addressing::is_block_root(7));
+ REQUIRE(! skip_addressing::is_block_root(31));
+ }
+ SECTION("block leaf") {
+ REQUIRE(! skip_addressing::is_block_leaf(1));
+ REQUIRE(! skip_addressing::is_block_leaf(2));
+ REQUIRE(! skip_addressing::is_block_leaf(3));
+ REQUIRE(skip_addressing::is_block_leaf(4));
+ REQUIRE(skip_addressing::is_block_leaf(5));
+ REQUIRE(skip_addressing::is_block_leaf(6));
+ REQUIRE(skip_addressing::is_block_leaf(7));
+ REQUIRE(skip_addressing::is_block_leaf(28));
+ REQUIRE(skip_addressing::is_block_leaf(29));
+ REQUIRE(skip_addressing::is_block_leaf(30));
+ REQUIRE(! skip_addressing::is_block_leaf(257));
+ REQUIRE(skip_addressing::is_block_leaf(255));
+ }
+ SECTION("Obtaining child") {
+ REQUIRE(skip_addressing::child_of(1) == 2);
+ REQUIRE(skip_addressing::child_of(2) == 4);
+ REQUIRE(skip_addressing::child_of(3) == 6);
+ REQUIRE(skip_addressing::child_of(4) == 9);
+ REQUIRE(skip_addressing::child_of(31) == 249);
+ }
+ SECTION("Obtaining parent") {
+ REQUIRE(skip_addressing::parent_of(2) == 1);
+ REQUIRE(skip_addressing::parent_of(3) == 1);
+ REQUIRE(skip_addressing::parent_of(6) == 3);
+ REQUIRE(skip_addressing::parent_of(7) == 3);
+ REQUIRE(skip_addressing::parent_of(9) == 4);
+ REQUIRE(skip_addressing::parent_of(17) == 4);
+ REQUIRE(skip_addressing::parent_of(33) == 5);
+ REQUIRE(skip_addressing::parent_of(29) == 26);
+ REQUIRE(skip_addressing::parent_of(1097) == 140);
+ }
+}
+
+template
+static auto make_test_priority_queue()
+{
+ return make_miniheap_mutable_priority_queue, block_size, false>(
+ [](std::pair &v, size_t idx){ v.second = idx; },
+ [](std::pair &l, std::pair &r){ return l.first < r.first; });
+}
+
+TEST_CASE("Mutable priority queue - basic tests", "[MutableSkipHeapPriorityQueue]") {
+ SECTION("a default constructed queue is empty") {
+ auto q = make_test_priority_queue();
+ REQUIRE(q.empty());
+ REQUIRE(q.size() == 0);
+ }
+ SECTION("an empty queue is not empty when one element is inserted") {
+ auto q = make_test_priority_queue();
+ q.push(std::make_pair(1, 0U));
+ REQUIRE(!q.empty());
+ REQUIRE(q.size() == 1);
+ }
+ SECTION("a queue with one element has it on top") {
+ auto q = make_test_priority_queue();
+ q.push(std::make_pair(8, 0U));
+ REQUIRE(q.top().first == 8);
+ }
+ SECTION("a queue with one element becomes empty when popped") {
+ auto q = make_test_priority_queue();
+ q.push(std::make_pair(9, 0U));
+ q.pop();
+ REQUIRE(q.empty());
+ REQUIRE(q.size() == 0);
+ }
+ SECTION("insert sorted stays sorted") {
+ auto q = make_test_priority_queue();
+ for (auto i : { 1, 2, 3, 4, 5, 6, 7, 8 })
+ q.push(std::make_pair(i, 0U));
+ REQUIRE(q.top().first == 1);
+ q.pop();
+ REQUIRE(q.top().first == 2);
+ q.pop();
+ REQUIRE(q.top().first == 3);
+ q.pop();
+ REQUIRE(q.top().first == 4);
+ q.pop();
+ REQUIRE(q.top().first == 5);
+ q.pop();
+ REQUIRE(q.top().first == 6);
+ q.pop();
+ REQUIRE(q.top().first == 7);
+ q.pop();
+ REQUIRE(q.top().first == 8);
+ q.pop();
+ REQUIRE(q.empty());
+ }
+ SECTION("randomly inserted elements are popped sorted") {
+ auto q = make_test_priority_queue();
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_int_distribution<> dist(1, 100000);
+ int n[36000];
+ for (auto& i : n) {
+ i = dist(gen);
+ q.push(std::make_pair(i, 0U));
+ }
+
+ REQUIRE(!q.empty());
+ REQUIRE(q.size() == 36000);
+ std::sort(std::begin(n), std::end(n));
+ for (auto i : n) {
+ REQUIRE(q.top().first == i);
+ q.pop();
+ }
+ REQUIRE(q.empty());
+ }
+}
+
+TEST_CASE("Mutable priority queue - reshedule first", "[MutableSkipHeapPriorityQueue]") {
+ SECTION("reschedule top with highest prio leaves order unchanged") {
+ auto q = make_miniheap_mutable_priority_queue, size_t>, 4, false>(
+ [](std::pair, size_t>& v, size_t idx) { v.second = idx; },
+ [](std::pair, size_t>& l, std::pair, size_t>& r) { return l.first.first < r.first.first; });
+
+ // 0 1 2 3 4 5 6 7 8
+ int nums[] = { 32, 1, 88, 16, 9, 11, 3, 22, 23 };
+ for (auto &i : nums)
+ q.push(std::make_pair(std::make_pair(i, &i), 0U));
+ REQUIRE(q.top().first.first == 1);
+ REQUIRE(q.top().first.second == &nums[1]);
+ REQUIRE(*q.top().first.second == 1);
+
+ // Update the top element.
+ q.top().first.first = 2;
+ q.update(1);
+
+ REQUIRE(q.top().first.first == 2);
+ REQUIRE(q.top().first.second == &nums[1]);
+ q.pop();
+ REQUIRE(q.top().first.first == 3);
+ REQUIRE(q.top().first.second == &nums[6]);
+ q.pop();
+ REQUIRE(q.top().first.first == 9);
+ REQUIRE(q.top().first.second == &nums[4]);
+ q.pop();
+ REQUIRE(q.top().first.first == 11);
+ REQUIRE(q.top().first.second == &nums[5]);
+ q.pop();
+ REQUIRE(q.top().first.first == 16);
+ REQUIRE(q.top().first.second == &nums[3]);
+ q.pop();
+ REQUIRE(q.top().first.first == 22);
+ REQUIRE(q.top().first.second == &nums[7]);
+ q.pop();
+ REQUIRE(q.top().first.first == 23);
+ REQUIRE(q.top().first.second == &nums[8]);
+ q.pop();
+ REQUIRE(q.top().first.first == 32);
+ REQUIRE(q.top().first.second == &nums[0]);
+ q.pop();
+ REQUIRE(q.top().first.first == 88);
+ REQUIRE(q.top().first.second == &nums[2]);
+ q.pop();
+ REQUIRE(q.empty());
+ }
+ SECTION("reschedule to mid range moves element to correct place") {
+ auto q = make_miniheap_mutable_priority_queue, size_t>, 4, false>(
+ [](std::pair, size_t>& v, size_t idx) { v.second = idx; },
+ [](std::pair, size_t>& l, std::pair, size_t>& r) { return l.first.first < r.first.first; });
+
+ // 0 1 2 3 4 5 6 7 8
+ int nums[] = { 32, 1, 88, 16, 9, 11, 3, 22, 23 };
+ for (auto& i : nums)
+ q.push(std::make_pair(std::make_pair(i, &i), 0U));
+ REQUIRE(q.top().first.first == 1);
+ REQUIRE(q.top().first.second == &nums[1]);
+ REQUIRE(*q.top().first.second == 1);
+
+ // Update the top element.
+ q.top().first.first = 12;
+ q.update(1);
+
+ REQUIRE(q.top().first.first == 3);
+ REQUIRE(q.top().first.second == &nums[6]);
+ q.pop();
+ REQUIRE(q.top().first.first == 9);
+ REQUIRE(q.top().first.second == &nums[4]);
+ q.pop();
+ REQUIRE(q.top().first.first == 11);
+ REQUIRE(q.top().first.second == &nums[5]);
+ q.pop();
+ REQUIRE(q.top().first.first == 12);
+ REQUIRE(q.top().first.second == &nums[1]);
+ q.pop();
+ REQUIRE(q.top().first.first == 16);
+ REQUIRE(q.top().first.second == &nums[3]);
+ q.pop();
+ REQUIRE(q.top().first.first == 22);
+ REQUIRE(q.top().first.second == &nums[7]);
+ q.pop();
+ REQUIRE(q.top().first.first == 23);
+ REQUIRE(q.top().first.second == &nums[8]);
+ q.pop();
+ REQUIRE(q.top().first.first == 32);
+ REQUIRE(q.top().first.second == &nums[0]);
+ q.pop();
+ REQUIRE(q.top().first.first == 88);
+ REQUIRE(q.top().first.second == &nums[2]);
+ q.pop();
+ REQUIRE(q.empty());
+ }
+ SECTION("reschedule to last moves element to correct place", "heap")
+ {
+ auto q = make_miniheap_mutable_priority_queue, size_t>, 4, false>(
+ [](std::pair, size_t>& v, size_t idx) { v.second = idx; },
+ [](std::pair, size_t>& l, std::pair, size_t>& r) { return l.first.first < r.first.first; });
+
+ // 0 1 2 3 4 5 6 7 8
+ int nums[] = { 32, 1, 88, 16, 9, 11, 3, 22, 23 };
+ for (auto& i : nums)
+ q.push(std::make_pair(std::make_pair(i, &i), 0U));
+ REQUIRE(q.top().first.first == 1);
+ REQUIRE(q.top().first.second == &nums[1]);
+ REQUIRE(*q.top().first.second == 1);
+
+ // Update the top element.
+ q.top().first.first = 89;
+ q.update(1);
+
+ REQUIRE(q.top().first.first == 3);
+ REQUIRE(q.top().first.second == &nums[6]);
+ q.pop();
+ REQUIRE(q.top().first.first == 9);
+ REQUIRE(q.top().first.second == &nums[4]);
+ q.pop();
+ REQUIRE(q.top().first.first == 11);
+ REQUIRE(q.top().first.second == &nums[5]);
+ q.pop();
+ REQUIRE(q.top().first.first == 16);
+ REQUIRE(q.top().first.second == &nums[3]);
+ q.pop();
+ REQUIRE(q.top().first.first == 22);
+ REQUIRE(q.top().first.second == &nums[7]);
+ q.pop();
+ REQUIRE(q.top().first.first == 23);
+ REQUIRE(q.top().first.second == &nums[8]);
+ q.pop();
+ REQUIRE(q.top().first.first == 32);
+ REQUIRE(q.top().first.second == &nums[0]);
+ q.pop();
+ REQUIRE(q.top().first.first == 88);
+ REQUIRE(q.top().first.second == &nums[2]);
+ q.pop();
+ REQUIRE(q.top().first.first == 89);
+ REQUIRE(q.top().first.second == &nums[1]);
+ q.pop();
+ REQUIRE(q.empty());
+ }
+ SECTION("reschedule top of 2 elements to last") {
+ auto q = make_test_priority_queue<8>();
+ q.push(std::make_pair(1, 0U));
+ q.push(std::make_pair(2, 0U));
+ REQUIRE(q.top().first == 1);
+ // Update the top element.
+ q.top().first = 3;
+ q.update(1);
+ REQUIRE(q.top().first == 2);
+ }
+ SECTION("reschedule top of 3 elements left to 2nd") {
+ auto q = make_test_priority_queue<8>();
+ q.push(std::make_pair(1, 0U));
+ q.push(std::make_pair(2, 0U));
+ q.push(std::make_pair(4, 0U));
+ REQUIRE(q.top().first == 1);
+ // Update the top element.
+ q.top().first = 3;
+ q.update(1);
+ REQUIRE(q.top().first == 2);
+ }
+ SECTION("reschedule top of 3 elements right to 2nd") {
+ auto q = make_test_priority_queue<8>();
+ q.push(std::make_pair(1, 0U));
+ q.push(std::make_pair(4, 0U));
+ q.push(std::make_pair(2, 0U));
+ REQUIRE(q.top().first == 1);
+ // Update the top element.
+ q.top().first = 3;
+ q.update(1);
+ REQUIRE(q.top().first == 2);
+ }
+ SECTION("reschedule top random gives same resultas pop/push") {
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_int_distribution dist(1, 100000);
+
+ auto pq = make_test_priority_queue<8>();
+ std::priority_queue, std::greater<>> stdq;
+
+ for (size_t outer = 0; outer < 100; ++ outer) {
+ int num = gen();
+ pq.push(std::make_pair(num, 0U));
+ stdq.push(num);
+ for (size_t inner = 0; inner < 100; ++ inner) {
+ int newval = gen();
+ // Update the top element.
+ pq.top().first = newval;
+ pq.update(1);
+ stdq.pop();
+ stdq.push(newval);
+ auto n = pq.top().first;
+ auto sn = stdq.top();
+ REQUIRE(sn == n);
+ }
+ }
+ }
+}