mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 02:45:58 +08:00
Merge branch 'master' into fs_align_supports
This commit is contained in:
commit
ff8281beb6
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@ local-lib
|
||||
build-linux/*
|
||||
deps/build-linux/*
|
||||
**/.DS_Store
|
||||
/.idea/
|
||||
|
@ -523,21 +523,28 @@ add_custom_target(gettext_make_pot
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Generate pot file from strings in the source tree"
|
||||
)
|
||||
add_custom_target(gettext_merge_po_with_pot
|
||||
|
||||
add_custom_target(gettext_merge_community_po_with_pot
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Merge localization po with new generted pot file"
|
||||
COMMENT "Merge community po with new generated pot file"
|
||||
)
|
||||
file(GLOB L10N_PO_FILES "${L10N_DIR}/*/PrusaSlicer*.po")
|
||||
# list of names of directories, which are licalized by PS internally
|
||||
list(APPEND PS_L10N_DIRS "cs" "de" "es" "fr" "it" "ja" "pl")
|
||||
foreach(po_file ${L10N_PO_FILES})
|
||||
#GET_FILENAME_COMPONENT(po_dir "${po_file}" DIRECTORY)
|
||||
#SET(po_new_file "${po_dir}/PrusaSlicer_.po")
|
||||
add_custom_command(
|
||||
TARGET gettext_merge_po_with_pot PRE_BUILD
|
||||
COMMAND msgmerge -N -o ${po_file} ${po_file} "${L10N_DIR}/PrusaSlicer.pot"
|
||||
# delete obsolete lines from resulting PO to avoid conflicts after a merging of it with wxWidgets.po
|
||||
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
GET_FILENAME_COMPONENT(po_dir "${po_file}" DIRECTORY)
|
||||
GET_FILENAME_COMPONENT(po_dir_name "${po_dir}" NAME)
|
||||
list(FIND PS_L10N_DIRS ${po_dir_name} found_dir_id)
|
||||
# found_dir_id==-1 means that po_dir_name wasn't found in PS_L10N_DIRS
|
||||
if(found_dir_id LESS 0)
|
||||
add_custom_command(
|
||||
TARGET gettext_merge_community_po_with_pot PRE_BUILD
|
||||
COMMAND msgmerge -N -o ${po_file} ${po_file} "${L10N_DIR}/PrusaSlicer.pot"
|
||||
# delete obsolete lines from resulting PO to avoid conflicts after a merging of it with wxWidgets.po
|
||||
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_target(gettext_concat_wx_po_with_po
|
||||
@ -545,7 +552,6 @@ add_custom_target(gettext_concat_wx_po_with_po
|
||||
COMMENT "Concatenate and merge wxWidgets localization po with PrusaSlicer po file"
|
||||
)
|
||||
file(GLOB L10N_PO_FILES "${L10N_DIR}/*/PrusaSlicer*.po")
|
||||
file(GLOB L10N_WX_PO_FILES "${L10N_DIR}/*/PrusaSlicer*.po")
|
||||
foreach(po_file ${L10N_PO_FILES})
|
||||
GET_FILENAME_COMPONENT(po_dir "${po_file}" DIRECTORY)
|
||||
GET_FILENAME_COMPONENT(po_dir_name "${po_dir}" NAME)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
BIN
resources/profiles/Creality/ENDER3PRO_thumbnail.png
Normal file
BIN
resources/profiles/Creality/ENDER3PRO_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.4.0-rc
|
||||
1.4.3 Added new filament profiles and SLA materials.
|
||||
1.4.2 Added SLA material profiles.
|
||||
1.4.1 Updated firmware version.
|
||||
1.4.0 Updated for the PrusaSlicer 2.4.0-rc release. Updated SLA material colors.
|
||||
|
@ -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.2
|
||||
config_version = 1.4.3
|
||||
# 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%
|
||||
@ -477,7 +477,7 @@ perimeter_acceleration = 800
|
||||
perimeter_speed = 50
|
||||
solid_infill_speed = 50
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_layers = 7
|
||||
top_solid_layers = 8
|
||||
bridge_flow_ratio = 1
|
||||
bridge_speed = 25
|
||||
|
||||
@ -1543,6 +1543,7 @@ filament_max_volumetric_speed = 13
|
||||
[filament:*ABSMINI*]
|
||||
# inherits = *ABS*
|
||||
bed_temperature = 100
|
||||
first_layer_bed_temperature = 100
|
||||
filament_retract_length = 2.7
|
||||
filament_retract_speed = nil
|
||||
filament_deretract_speed = nil
|
||||
@ -2914,6 +2915,7 @@ inherits = *PET*
|
||||
filament_vendor = BASF
|
||||
filament_cost =
|
||||
filament_density = 1.33
|
||||
filament_colour = #F7F7F7
|
||||
first_layer_temperature = 220
|
||||
first_layer_bed_temperature = 70
|
||||
temperature = 215
|
||||
@ -2925,7 +2927,7 @@ bridge_fan_speed = 100
|
||||
filament_type = PET
|
||||
disable_fan_first_layers = 1
|
||||
full_fan_speed_layer = 3
|
||||
filament_notes = "BASF Forward AM Ultrafuse PET\nMaterial profile version 1.0\n\nMaterial Description\nUltrafuse PET is made from a premium PET and prints as easy as PLA, but is much stronger. The filament has a large operating window for printing (temperature vs. speed), so it can be used on every 3D-printer. PET will give you outstanding printing results: a good layer adhesion, a high resolution and it is easy to handle. Ultrafuse PET can be 100% recycled, is watertight and has great colors and finish.\n\nPrinting Recommendations:\nUltrafuse PET can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion.\n"
|
||||
filament_notes = "Material Description\nUltrafuse PET is made from a premium PET and prints as easy as PLA, but is much stronger. The filament has a large operating window for printing (temperature vs. speed), so it can be used on every 3D-printer. PET will give you outstanding printing results: a good layer adhesion, a high resolution and it is easy to handle. Ultrafuse PET can be 100% recycled, is watertight and has great colors and finish.\n\nPrinting Recommendations:\nUltrafuse PET can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion."
|
||||
filament_retract_length = 2
|
||||
filament_retract_speed = 40
|
||||
filament_retract_before_travel = 2
|
||||
@ -2943,7 +2945,7 @@ filament_cost =
|
||||
filament_density = 1.25
|
||||
filament_spool_weight = 0
|
||||
filament_colour = #FFFFFF
|
||||
filament_notes = "BASF Forward AM Ultrafuse PLA PRO1\nMaterial profile version 1.0\n\nMaterial Description\nPLA PRO1 is an extremely versatile tough PLA filament made for professionals. It reduces your printing time by 30% – 80%, (subject to printer and object limitations) and the strength exceeds overall mechanical properties of printed ABS parts. Printer settings can be tuned to achieve blazing fast speeds or an unrivaled surface finish. The excellent quality control ensures the highest levels of consistency between colors and batches, it will perform as expected, every time.\n\nPrinting Recommendations:\nUltrafuse PLA PRO1 can be printed directly onto a clean build plate.\n"
|
||||
filament_notes = "Material Description\nPLA PRO1 is an extremely versatile tough PLA filament made for professionals. It reduces your printing time by 30% – 80%, (subject to printer and object limitations) and the strength exceeds overall mechanical properties of printed ABS parts. Printer settings can be tuned to achieve blazing fast speeds or an unrivaled surface finish. The excellent quality control ensures the highest levels of consistency between colors and batches, it will perform as expected, every time.\n\nPrinting Recommendations:\nUltrafuse PLA PRO1 can be printed directly onto a clean build plate."
|
||||
filament_retract_length = 2
|
||||
filament_retract_lift = 0
|
||||
filament_retract_speed = 40
|
||||
@ -2969,15 +2971,303 @@ max_fan_speed = 20
|
||||
bed_temperature = 100
|
||||
disable_fan_first_layers = 3
|
||||
filament_colour = #FFFFFF
|
||||
filament_notes = "BASF Forward AM Ultrafuse ABS\nMaterial profile version 1.0\n\nMaterial Description\nABS is the second most used 3D printing material. It is strong, flexible and has a high heat resistance. ABS is a preferred plastic for engineers and professional applications. ABS can be smoothened with acetone. To make a proper 3D print with ABS you will need a heated print bed. The filament is available in 9 colors.\n\nPrinting Recommendations:\n\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion.\n"
|
||||
filament_retract_length = 2
|
||||
filament_retract_speed = 40
|
||||
filament_notes = "Material Description\nABS is the second most used 3D printing material. It is strong, flexible and has a high heat resistance. ABS is a preferred plastic for engineers and professional applications. ABS can be smoothened with acetone. To make a proper 3D print with ABS you will need a heated print bed. The filament is available in 9 colors.\n\nPrinting Recommendations:\n\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion."
|
||||
filament_retract_before_travel = 2
|
||||
filament_wipe = 0
|
||||
filament_retract_layer_change = 0
|
||||
|
||||
[filament:Ultrafuse ABS @MINI]
|
||||
inherits = Ultrafuse ABS; *ABSMINI*
|
||||
filament_retract_layer_change = nil
|
||||
|
||||
[filament:Ultrafuse ABS Fusion+]
|
||||
inherits = Ultrafuse ABS
|
||||
filament_density = 1.08
|
||||
first_layer_bed_temperature = 105
|
||||
temperature = 250
|
||||
filament_colour = #FFF8D9
|
||||
filament_notes = "Material Description\nABS Fusion+ made with Polyscope XILOY™ 3D is an engineering filament which has been optimized for 3D-printing. This special grade has been developed in collaboration with Polyscope Polymers - renowned for its material solutions in the automotive industry. ABS is a thermoplastic which is used in many applications. Although ABS has been classified as a standard material in 3D-printing it is known to be quite challenging to process. ABS Fusion+ combines the properties of ABS with an improved processability. The filament is based on an ABS grade which can be directly printed on glass without any adhesives or tape and has a higher success rate of prints due to extreme low warping."
|
||||
filament_retract_before_travel = 2
|
||||
filament_wipe = nil
|
||||
filament_retract_layer_change = 0
|
||||
filament_retract_lift = 0
|
||||
|
||||
[filament:Ultrafuse ABS Fusion+ @MINI]
|
||||
inherits = Ultrafuse ABS Fusion+; *ABSMINI*
|
||||
first_layer_bed_temperature = 100
|
||||
filament_retract_layer_change = nil
|
||||
|
||||
[filament:Ultrafuse ASA]
|
||||
inherits = Ultrafuse ABS Fusion+
|
||||
filament_density = 1.07
|
||||
filament_colour = #FFF4CA
|
||||
first_layer_temperature = 275
|
||||
temperature = 275
|
||||
first_layer_bed_temperature = 110
|
||||
bed_temperature = 105
|
||||
filament_type = ASA
|
||||
min_fan_speed = 25
|
||||
max_fan_speed = 50
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 4
|
||||
filament_max_volumetric_speed = 5
|
||||
filament_notes = "Material Description\nUltrafuse ASA is a high-performance thermoplastic with similar mechanical properties as ABS. ASA offers additional benefits such as high outdoor weather resistance. The UV resistance, toughness, and rigidity make it an ideal material to 3D-print outdoor fixtures and appliances without losing its properties or color. When also taking into account the high heat resistance and high chemical resistance, this filament is a good choice for many types of applications.\n\nPrinting Recommendations:\nApply Magigoo PC, 3D lac or Dimafix to a clean build plate to improve adhesion."
|
||||
|
||||
[filament:Ultrafuse ASA @MINI]
|
||||
inherits = Ultrafuse ASA; *ABSMINI*
|
||||
filament_type = ASA
|
||||
|
||||
[filament:Ultrafuse HIPS]
|
||||
inherits = Ultrafuse ABS
|
||||
temperature = 250
|
||||
filament_density = 1.02
|
||||
filament_type = HIPS
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
filament_soluble = 1
|
||||
filament_notes = "Material Description\nUltrafuse HIPS is a high-quality engineering thermoplastic, which is well known in the 3D-printing industry as a support material for ABS. But this material has additional properties to offer like good impact resistance, good dimensional stability, and easy post-processing. HiPS is a great material to use as a support for ABS because there is a good compatibility between the two materials, and HIPS is an easy breakaway support. Now you have the opportunity to create ABS models with complex geometry. HIPS is easy to post process with glue or with sanding paper."
|
||||
|
||||
[filament:Ultrafuse HIPS @MINI]
|
||||
inherits = Ultrafuse HIPS; *ABSMINI*
|
||||
filament_type = HIPS
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
|
||||
[filament:Ultrafuse PA]
|
||||
inherits = Fillamentum Nylon FX256
|
||||
filament_vendor = BASF
|
||||
filament_density = 1.12
|
||||
filament_colour = #ECFAFF
|
||||
first_layer_temperature = 240
|
||||
temperature = 240
|
||||
first_layer_bed_temperature = 80
|
||||
bed_temperature = 70
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 0
|
||||
bridge_fan_speed = 0
|
||||
fan_below_layer_time = 30
|
||||
slowdown_below_layer_time = 20
|
||||
min_print_speed = 15
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_retract_length = 1
|
||||
filament_retract_lift = 0
|
||||
filament_retract_before_travel = 2
|
||||
filament_retract_layer_change = 0
|
||||
filament_cost = 0
|
||||
filament_spool_weight = 0
|
||||
compatible_printers_condition = printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
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.01{elsif nozzle_diameter[0]==0.6}0.02{else}0.04{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 K12{elsif nozzle_diameter[0]==0.8};{else}M900 K20{endif} ; Filament gcode LA 1.0"
|
||||
filament_notes = "Material Description\nThe key features of Ultrafuse PA are the high strength and high modulus. Furthermore, Ultrafuse PA shows a good thermal distortion stability.\n\nPrinting Recommendations:\nApply PVA glue, Kapton tape or PA adhesive to a clean buildplate to improve adhesion."
|
||||
|
||||
[filament:Ultrafuse PA6 GF30]
|
||||
inherits = Ultrafuse PA
|
||||
filament_density = 1.17
|
||||
first_layer_temperature = 270
|
||||
temperature = 270
|
||||
first_layer_bed_temperature = 100
|
||||
bed_temperature = 100
|
||||
filament_colour = #404040
|
||||
fan_always_on = 1
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 50
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 1
|
||||
full_fan_speed_layer = 3
|
||||
slowdown_below_layer_time = 15
|
||||
filament_max_volumetric_speed = 10
|
||||
filament_retract_length = 1.2
|
||||
filament_retract_speed = 40
|
||||
filament_deretract_speed = 30
|
||||
filament_retract_lift = nil
|
||||
filament_wipe = 0
|
||||
filament_notes = "Material Description\nUltrafuse® PA6 GF30 is a unique compound specifically developed for FFF printing. Due to the glass fiber content of 30%, parts tend to warp less. In addition the excellent layer adhesion and its compatibility with the water soluble support Ultrafuse® BVOH make this material the perfect solution to develop industrial applications on an FFF printer.\n\nWith its high wear and chemical resistance, high stiffness and strength, Ultrafuse® PA6 GF30 is perfect for a wide variety of applications in automotive, electronics or transportation.\n\nUltrafuse PA6 GF30 is designed for functional prototyping and demanding applications such as industrial tooling, transportation, electronics, small appliances, sports & leisure\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PA6 GF30 can be printed directly onto a clean build plate. For challenging prints, use Magigoo PA gluestick to improve adhesion."
|
||||
compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Ultrafuse PAHT-CF15]
|
||||
inherits = Ultrafuse PA6 GF30
|
||||
filament_density = 1.23
|
||||
filament_notes = "Material Description\nPAHT CF15 is a high-performance 3D printing filament that opens new application fields in FFF printing. In parallel to its advanced mechanical properties, dimensional stability, and chemical resistance, it has very good processability. It works in any FFF printer with a hardened nozzle. In addition to that, it is compatible with water-soluble support material and HiPS, which allow printing complex geometries that work in challenging environments. PAHT CF15 has high heat resistance up to 130 °C and low moisture absorption.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PAHT-CF can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion."
|
||||
|
||||
[filament:Ultrafuse PC-ABS-FR]
|
||||
inherits = Ultrafuse ABS
|
||||
filament_colour = #505050
|
||||
filament_density = 1.17
|
||||
first_layer_temperature = 275
|
||||
temperature = 275
|
||||
first_layer_bed_temperature = 110
|
||||
bed_temperature = 105
|
||||
filament_type = PC
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_wipe = nil
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 20
|
||||
bridge_fan_speed = 30
|
||||
disable_fan_first_layers = 4
|
||||
compatible_printers_condition = printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
filament_notes = "Material Description\nUltrafuse® PC/ABS FR Black is a V-0 flame retardant blend of Polycarbonate and ABS – two of the most used thermoplastics for engineering & electrical applications. The combination of these two materials results in a premium material with a mix of the excellent mechanical properties of PC and the comparably low printing temperature of ABS. Combined with a halogen free flame retardant, parts printed with Ultrafuse® PC/ABS FR Black feature great tensile and impact strength, higher thermal resistance than ABS and can fulfill the requirements of the UL94 V-0 standard.\n\nPrinting Recommendations:\nApply Magigoo PC to a clean build plate to improve adhesion."
|
||||
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.07{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 K24{elsif nozzle_diameter[0]==0.8};{else}M900 K45{endif} ; Filament gcode LA 1.0"
|
||||
|
||||
[filament:Ultrafuse PET-CF15]
|
||||
inherits = Ultrafuse PET
|
||||
filament_density = 1.36
|
||||
filament_colour = #404040
|
||||
first_layer_temperature = 270
|
||||
temperature = 270
|
||||
first_layer_bed_temperature = 75
|
||||
bed_temperature = 75
|
||||
min_fan_speed = 60
|
||||
max_fan_speed = 100
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 1
|
||||
full_fan_speed_layer = 3
|
||||
slowdown_below_layer_time = 15
|
||||
fan_below_layer_time = 30
|
||||
filament_max_volumetric_speed = 10
|
||||
filament_retract_length = 1.2
|
||||
filament_retract_speed = 40
|
||||
filament_deretract_speed = 30
|
||||
filament_retract_lift = nil
|
||||
filament_wipe = 0
|
||||
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.01{elsif nozzle_diameter[0]==0.6}0.04{else}0.05{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 K18{elsif nozzle_diameter[0]==0.8};{else}M900 K30{endif} ; Filament gcode LA 1.0"
|
||||
filament_notes = "Material Description\nPET CF15 is a Carbon Fiber reinforced PET which has precisely tuned material properties, for a wide range of technical applications. The filament is very strong and stiff and has high heat resistance. With its high dimensional stability and low abrasiveness, the filament offers an easy to print experience which allows direct printing on glass or a PEI sheet. It is compatible with HiPS for breakaway support and water soluble support and has an excellent surface finish.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nUltrafuse PET-CF15 can be printed directly onto a clean build plate. For challenging prints, use 3dLac to improve adhesion."
|
||||
compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Ultrafuse PLA]
|
||||
inherits = *PLA*
|
||||
filament_vendor = BASF
|
||||
filament_density = 1.25
|
||||
full_fan_speed_layer = 3
|
||||
filament_notes = "Material Description\nPLA is one of the most used materials for 3D printing. Ultrafuse PLA is available in a wide range of colors. The glossy feel often attracts those who print display models or items for household use. Many appreciate the plant-based origin of this material. When properly cooled, PLA has a high maximum printing speed and sharp printed corners. Combining this with low warping of the print makes it a popular plastic for home printers, hobbyists, prototyping and schools.\n\nPrinting Recommendations:\nUltrafuse PLA can be printed directly onto a clean build plate."
|
||||
|
||||
[filament:Ultrafuse PP]
|
||||
inherits = Ultrafuse ABS
|
||||
filament_density = 0.91
|
||||
filament_colour = #F0F0F0
|
||||
first_layer_temperature = 240
|
||||
temperature = 240
|
||||
first_layer_bed_temperature = 80
|
||||
bed_temperature = 70
|
||||
min_fan_speed = 100
|
||||
max_fan_speed = 100
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 1
|
||||
full_fan_speed_layer = 3
|
||||
fan_below_layer_time = 60
|
||||
slowdown_below_layer_time = 20
|
||||
min_print_speed = 10
|
||||
filament_type = PP
|
||||
filament_max_volumetric_speed = 2.5
|
||||
filament_retract_speed = 25
|
||||
filament_deretract_speed = 25
|
||||
filament_retract_layer_change = 0
|
||||
filament_wipe = nil
|
||||
filament_notes = "Material Description\nUltrafuse PP is high-performance thermoplastic with low density, high elasticity and high resistance to fatigue. The mechanical properties make it an ideal material for 3D-printing applications which have to endure high stress or strain. The filament has high chemical resistance and a high isolation value. PP is one of the most used materials in the world, due to its versatility and ability to engineer lightweight tough parts.\n\nPrinting Recommendations:\nApply PP tape or Magigoo PP adhesive to the buildplate for optimal adhesion."
|
||||
compatible_printers_condition = printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Ultrafuse PP-GF30]
|
||||
inherits = Ultrafuse PP
|
||||
filament_density = 1.07
|
||||
filament_colour = #404040
|
||||
first_layer_temperature = 260
|
||||
temperature = 250
|
||||
first_layer_bed_temperature = 90
|
||||
bed_temperature = 40
|
||||
min_fan_speed = 40
|
||||
max_fan_speed = 75
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 30
|
||||
slowdown_below_layer_time = 15
|
||||
min_print_speed = 15
|
||||
filament_retract_length = 1.2
|
||||
filament_retract_speed = 40
|
||||
filament_deretract_speed = 30
|
||||
filament_retract_lift = nil
|
||||
filament_wipe = 0
|
||||
filament_notes = "Ultrafuse PP GF30 is polypropylene, reinforced with 30% glass fiber content. The fibers in this compound are specially designed for 3D-printing filaments and are compatible with a wide range of standard FFF 3D-printers. The extreme stiffness makes this material highly suitable for demanding applications. Other key properties of PPGF30 are high heat resistance and improved UV-resistance. All these excellent properties make this filament highly suitable in an industrial environment.\n\nPrinting Recommendations:\nThis material contains fibers that have an abrasive effect on printer components. Use a hardened or Ruby nozzle with a diameter of 0.6 or larger for optimal performance and avoid damage to the nozzle.\n\nApply PP strapping tape or PPGF adhesive to a clean build plate for optimal adhesion."
|
||||
compatible_printers_condition = nozzle_diameter[0]>=0.6 and printer_model!="MINI" and printer_model!="MK2SMM" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Ultrafuse TPC-45D]
|
||||
inherits = *FLEX*
|
||||
filament_vendor = BASF
|
||||
extrusion_multiplier = 1
|
||||
filament_density = 1.15
|
||||
filament_colour = #0035EC
|
||||
first_layer_temperature = 235
|
||||
temperature = 235
|
||||
first_layer_bed_temperature = 60
|
||||
bed_temperature = 60
|
||||
min_fan_speed = 10
|
||||
max_fan_speed = 50
|
||||
bridge_fan_speed = 80
|
||||
fan_below_layer_time = 30
|
||||
slowdown_below_layer_time = 15
|
||||
min_print_speed = 15
|
||||
fan_always_on = 1
|
||||
cooling = 1
|
||||
filament_max_volumetric_speed = 1.2
|
||||
filament_retract_length = 1.2
|
||||
filament_retract_speed = 25
|
||||
filament_deretract_speed = 25
|
||||
filament_retract_lift = 0
|
||||
filament_wipe = nil
|
||||
filament_retract_before_wipe = nil
|
||||
filament_retract_before_travel = 2
|
||||
filament_retract_layer_change = 0
|
||||
filament_notes = "Material Description\nTPC 45D is a flexible, shore 45D, rubber-like Thermoplastic Copolyester Elastomer (TPE-C), which is derived from rapeseed oil and combines the best properties of elastomers (rubbers) and polyesters. The material delivers excellent adhesion in the Z-direction, meaning that the printed layers do not detach - even with extreme deformation.\n\nPrinting Recommendations:\nApply Magigoo Flex to a clean build plate to improve adhesion."
|
||||
|
||||
## [filament:Ultrafuse TPS-90A]
|
||||
## inherits = Ultrafuse TPC-45D
|
||||
## filament_density = 1.04
|
||||
## extrusion_multiplier = 1.02
|
||||
## filament_colour = #FFFFFF
|
||||
## first_layer_temperature = 270
|
||||
## temperature = 265
|
||||
## first_layer_bed_temperature = 30
|
||||
## bed_temperature = 30
|
||||
## min_fan_speed = 20
|
||||
## max_fan_speed = 75
|
||||
## filament_notes = "Material Description\nUltrafuse® TPS 90A is an elastomer based on the raw material SEBS. The combination of durable and flexible building blocks leads to a very versatile material. Compared to other flexible 3D printing materials it shows more rubber-like soft touch haptics and better non-slip properties. Furthermore, the material shows a reduced moisture uptake, which allows for printing without pre-drying. Parts printed with Ultrafuse® TPS 90A show almost no visible layers or warpage, which makes it an excellent material choice for end-use parts. Producing multi-material parts is possible by printing it together with ABS.\n\nPrinting Recommendations:\nApply Tape, adhesion spray or glue to a clean build plate to improve adhesion."
|
||||
|
||||
[filament:Ultrafuse TPU-64D]
|
||||
inherits = Ultrafuse TPC-45D
|
||||
filament_density = 1.16
|
||||
first_layer_temperature = 230
|
||||
temperature = 225
|
||||
first_layer_bed_temperature = 40
|
||||
bed_temperature = 40
|
||||
min_fan_speed = 20
|
||||
max_fan_speed = 100
|
||||
filament_notes = "Material Description\nUltrafuse® TPU 64D is the hardest elastomer in BASF Forward AM’s flexible productline. The material shows a relatively high rigidity while maintaining a certain flexibility. This filament is the perfect match for industrial applications requiring rigid parts being resistant to impact, wear and tear. Due to its property profile, the material can be used as an alternative for parts made from ABS and rubbers. Ultrafuse® TPU 64D is easy to print on direct drive and bowden style printers and is compatible with soluble BVOH support to realize the most complex geometries.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing."
|
||||
|
||||
[filament:Ultrafuse TPU-85A]
|
||||
inherits = Ultrafuse TPU-64D
|
||||
filament_density = 1.11
|
||||
first_layer_temperature = 225
|
||||
temperature = 220
|
||||
filament_notes = "Material Description\nUltrafuse® TPU 85A comes in its natural white color. Chemical properties (e.g. resistance against particular substances) and tolerance for solvents can be made available, if these factors are relevant for a specific application. Generally, these properties correspond to publicly available data on polyether based TPUs. This material is not FDA conform. Good flexibility at low temperature, good wear performance and good damping behavior are the key features of Ultrafuse® TPU 85A.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing."
|
||||
|
||||
[filament:Ultrafuse TPU-95A]
|
||||
inherits = Ultrafuse TPU-85A
|
||||
filament_density = 1.14
|
||||
first_layer_temperature = 230
|
||||
temperature = 225
|
||||
filament_notes = "Material Description\nUltrafuse® TPU 95A comes with a well-balanced profile of flexibility and durability. On top of that, it allows for easier and faster printing then softer TPU grades. Parts printed with Ultrafuse® TPU 95A show a high elongation, good impact resistance, excellent layer adhesion and a good resistance to oils and common industrially used chemicals. Due to its good printing behavior, Ultrafuse® TPU 95A is a good choice for starting printing flexible materials on both direct drive and bowden style printers.\n\nPrinting Recommendations:\nUltrafuse TPU can be printed directly onto a clean build plate. A small amount of 3Dlac can make removal easier after printing."
|
||||
|
||||
[filament:Ultrafuse rPET]
|
||||
inherits = Ultrafuse PET
|
||||
filament_density = 1.27
|
||||
filament_colour = #9DC5FF
|
||||
first_layer_temperature = 235
|
||||
temperature = 235
|
||||
first_layer_bed_temperature = 80
|
||||
bed_temperature = 75
|
||||
min_fan_speed = 50
|
||||
max_fan_speed = 100
|
||||
fan_below_layer_time = 15
|
||||
filament_notes = "Material Description\nPET is mainly known by the well-known PET bottle material. This recycled has a natural transparent blueish look. It has excellent 3D printing properties and good mechanical characteristics."
|
||||
filament_retract_length = 1.2
|
||||
filament_retract_lift = 0.6
|
||||
filament_wipe = nil
|
||||
|
||||
[filament:Ultrafuse Metal]
|
||||
inherits = *ABSC*
|
||||
@ -4629,7 +4919,7 @@ material_colour = #FF8040
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 12
|
||||
initial_exposure_time = 30
|
||||
material_type = Tough
|
||||
material_type = Casting
|
||||
material_vendor = 3DM
|
||||
material_colour = #B0B000
|
||||
|
||||
@ -5084,6 +5374,38 @@ material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:PrimaCreator Tough Clear @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:PrimaCreator Tough White @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:PrimaCreator Flex Clear @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 4.5
|
||||
initial_exposure_time = 30
|
||||
material_type = Flexible
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Siraya Tech Simple Clear @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 8
|
||||
@ -5371,7 +5693,7 @@ inherits = *common 0.05*
|
||||
exposure_time = 12
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_vendor = 3DM
|
||||
material_colour = #EC0000
|
||||
|
||||
[sla_material:Esun Bio-Photopolymer Resin White @0.05]
|
||||
@ -5550,6 +5872,38 @@ material_type = Tough
|
||||
material_vendor = Photocentric
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8.5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:PrimaCreator Tough Clear @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:PrimaCreator Tough White @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:PrimaCreator Flex Clear @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 6.5
|
||||
initial_exposure_time = 30
|
||||
material_type = Flexible
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Siraya Tech Simple Clear @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 10
|
||||
@ -6270,6 +6624,38 @@ material_type = Tough
|
||||
material_vendor = Made for Prusa
|
||||
material_colour = #FF8040
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 14
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:PrimaCreator Tough Clear @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:PrimaCreator Tough White @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:PrimaCreator Flex Clear @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 12
|
||||
initial_exposure_time = 35
|
||||
material_type = Flexible
|
||||
material_vendor = PrimaCreator
|
||||
material_colour = #F8F8F8
|
||||
|
||||
## SL1S materials ##
|
||||
|
||||
## 0.025 SL1S
|
||||
@ -6916,6 +7302,310 @@ material_type = Tough
|
||||
material_vendor = Peopoly
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:3DM-ABS @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = 3DM
|
||||
material_colour = #FF8040
|
||||
|
||||
[sla_material:3DM-DENT @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.3
|
||||
initial_exposure_time = 36
|
||||
material_type = Dental
|
||||
material_vendor = 3DM
|
||||
material_colour = #FFEEE6
|
||||
|
||||
[sla_material:3DM-HR Green @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = 3DM
|
||||
material_colour = #00B900
|
||||
|
||||
[sla_material:3DM-HR Red Wine @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 32
|
||||
material_type = Tough
|
||||
material_vendor = 3DM
|
||||
material_colour = #EC0000
|
||||
|
||||
[sla_material:3DM-Vulcan Gold @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 24
|
||||
material_type = Casting
|
||||
material_vendor = 3DM
|
||||
material_colour = #B0B000
|
||||
|
||||
[sla_material:3DM-XPRO White @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = 3DM
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:Asiga Denta Model @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 24
|
||||
material_type = Dental
|
||||
material_vendor = Asiga
|
||||
material_colour = #FFEEE6
|
||||
|
||||
[sla_material:Asiga PlasGRAY @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 9.7
|
||||
initial_exposure_time = 48
|
||||
material_type = Tough
|
||||
material_vendor = Asiga
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:BlueCast EcoGray @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = BlueCast
|
||||
material_colour = #808080
|
||||
|
||||
[sla_material:BlueCast Phrozen Wax @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5.3
|
||||
initial_exposure_time = 40
|
||||
material_type = Tough
|
||||
material_vendor = BlueCast
|
||||
material_colour = #007EFD
|
||||
|
||||
[sla_material:NextDent Model 2.0 Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 4
|
||||
initial_exposure_time = 28
|
||||
material_type = Dental
|
||||
material_vendor = NextDent
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:NextDent Cast Purple @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3
|
||||
initial_exposure_time = 16
|
||||
material_type = Casting
|
||||
material_vendor = NextDent
|
||||
material_colour = #E800E8
|
||||
|
||||
[sla_material:Siraya Tech Tenacious @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.7
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Siraya Tech Blu Clear V2 @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Siraya Tech Blu Blue @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 4
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #007EFD
|
||||
|
||||
[sla_material:Siraya Tech Fast Black @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #595959
|
||||
|
||||
[sla_material:Siraya Tech Fast Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Siraya Tech Simple Clear @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Siraya Tech Sculpt @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.7
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Siraya Tech
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Harz Labs Model Resin Cherry @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 4.3
|
||||
initial_exposure_time = 16
|
||||
material_type = Tough
|
||||
material_vendor = Harz Labs
|
||||
material_colour = #EC0000
|
||||
|
||||
[sla_material:Harz Labs Model Resin Black @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 4.3
|
||||
initial_exposure_time = 16
|
||||
material_type = Tough
|
||||
material_vendor = Harz Labs
|
||||
material_colour = #595959
|
||||
|
||||
[sla_material:Harz Labs Basic Resin Red @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 4.3
|
||||
initial_exposure_time = 16
|
||||
material_type = Tough
|
||||
material_vendor = Harz Labs
|
||||
material_colour = #EC0000
|
||||
|
||||
[sla_material:Resinworks 3D Violet @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5.7
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Resinworks 3D
|
||||
material_colour = #E800E8
|
||||
|
||||
[sla_material:FunToDo Industrial Blend Unpigmented @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 1.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = FunToDo
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:FunToDo Snow White @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = FunToDo
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:FunToDo Ash Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3
|
||||
initial_exposure_time = 32
|
||||
material_type = Tough
|
||||
material_vendor = FunToDo
|
||||
material_colour = #808080
|
||||
|
||||
[sla_material:Ameralabs AMD 3 LED @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 1.7
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #808080
|
||||
|
||||
[sla_material:Dragon Resin Metalshine Metal Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 40
|
||||
material_type = Tough
|
||||
material_vendor = Dragon Resin
|
||||
material_colour = #808080
|
||||
|
||||
[sla_material:Dragon Resin Metalshine Dark Brass @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 40
|
||||
material_type = Tough
|
||||
material_vendor = Dragon Resin
|
||||
material_colour = #B0B000
|
||||
|
||||
[sla_material:Dragon Resin Metalshine Brass @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 40
|
||||
material_type = Tough
|
||||
material_vendor = Dragon Resin
|
||||
material_colour = #B0B000
|
||||
|
||||
[sla_material:Esun Bio-Photopolymer Resin White @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.7
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Esun
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:Esun Standard Resin Black @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.3
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Esun
|
||||
material_colour = #595959
|
||||
|
||||
[sla_material:Monocure 3D Black Rapid Resin @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_colour = #595959
|
||||
|
||||
[sla_material:Monocure 3D Blue Rapid Resin @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_colour = #007EFD
|
||||
|
||||
[sla_material:Monocure 3D Clear Rapid Resin @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.7
|
||||
initial_exposure_time = 32
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_colour = #F8F8F8
|
||||
|
||||
[sla_material:Monocure 3D Grey Rapid Resin @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Monocure 3D White Rapid Resin @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 3.3
|
||||
initial_exposure_time = 28
|
||||
material_type = Tough
|
||||
material_vendor = Monocure
|
||||
material_colour = #FFFFFF
|
||||
|
||||
[sla_material:Photocentric Hard Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 24
|
||||
material_type = Tough
|
||||
material_vendor = Photocentric
|
||||
material_colour = #808080
|
||||
|
||||
## 0.1 SL1S
|
||||
|
||||
## Prusa Polymers 0.1
|
||||
|
@ -10,7 +10,10 @@
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <mutex>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <boost/thread/lock_guard.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
// #define BRIM_DEBUG_TO_SVG
|
||||
@ -200,20 +203,94 @@ static ExPolygons top_level_outer_brim_area(const Print &print
|
||||
return diff_ex(brim_area, no_brim_area);
|
||||
}
|
||||
|
||||
static ExPolygons inner_brim_area(const Print &print,
|
||||
const ConstPrintObjectPtrs &top_level_objects_with_brim,
|
||||
const std::vector<ExPolygons> &bottom_layers_expolygons,
|
||||
const float no_brim_offset)
|
||||
// Return vector of booleans indicated if polygons from bottom_layers_expolygons contain another polygon or not.
|
||||
// Every ExPolygon is counted as several Polygons (contour and holes). Contour polygon is always processed before holes.
|
||||
static std::vector<bool> has_polygons_nothing_inside(const Print &print, const std::vector<ExPolygons> &bottom_layers_expolygons)
|
||||
{
|
||||
assert(print.objects().size() == bottom_layers_expolygons.size());
|
||||
Polygons islands;
|
||||
for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) {
|
||||
const PrintObject *object = print.objects()[print_object_idx];
|
||||
const Polygons islands_object = to_polygons(bottom_layers_expolygons[print_object_idx]);
|
||||
|
||||
islands.reserve(islands.size() + object->instances().size() * islands_object.size());
|
||||
for (const PrintInstance &instance : object->instances())
|
||||
append_and_translate(islands, islands_object, instance);
|
||||
}
|
||||
|
||||
ClipperLib_Z::Paths islands_clip;
|
||||
islands_clip.reserve(islands.size());
|
||||
for (const Polygon &poly : islands) {
|
||||
size_t island_idx = &poly - &islands.front();
|
||||
ClipperLib_Z::Path island_clip;
|
||||
for (const Point &pt : poly.points)
|
||||
island_clip.emplace_back(pt.x(), pt.y(), island_idx + 1);
|
||||
islands_clip.emplace_back(island_clip);
|
||||
}
|
||||
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
// Always assign zero to detect cases when two polygons are overlapping.
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot, const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
|
||||
pt.z() = 0;
|
||||
});
|
||||
|
||||
clipper.AddPaths(islands_clip, ClipperLib_Z::ptSubject, true);
|
||||
ClipperLib_Z::PolyTree islands_polytree;
|
||||
clipper.Execute(ClipperLib_Z::ctUnion, islands_polytree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
|
||||
std::vector<bool> has_nothing_inside(islands.size());
|
||||
std::function<void(const ClipperLib_Z::PolyNode&)> check_contours = [&check_contours, &has_nothing_inside](const ClipperLib_Z::PolyNode &parent_node)->void {
|
||||
if (!parent_node.Childs.empty())
|
||||
for(const ClipperLib_Z::PolyNode *child_node : parent_node.Childs)
|
||||
check_contours(*child_node);
|
||||
|
||||
if (parent_node.Childs.empty() && !parent_node.Contour.empty() && parent_node.Contour.front().z() != 0) {
|
||||
int polygon_idx = parent_node.Contour.front().z();
|
||||
assert(polygon_idx > 0 && polygon_idx <= int(has_nothing_inside.size()));
|
||||
|
||||
// The whole contour must have the same ID. In other cases, some counters overlap.
|
||||
for (const ClipperLib_Z::IntPoint &point : parent_node.Contour)
|
||||
if (polygon_idx != point.z())
|
||||
return;
|
||||
|
||||
has_nothing_inside[polygon_idx - 1] = true;
|
||||
}
|
||||
};
|
||||
|
||||
check_contours(islands_polytree);
|
||||
return has_nothing_inside;
|
||||
}
|
||||
|
||||
// INNERMOST means that ExPolygon doesn't contain any other ExPolygons.
|
||||
// NORMAL is for other cases.
|
||||
enum class InnerBrimType {NORMAL, INNERMOST};
|
||||
|
||||
struct InnerBrimExPolygons
|
||||
{
|
||||
ExPolygons brim_area;
|
||||
InnerBrimType type = InnerBrimType::NORMAL;
|
||||
double brim_width = 0.;
|
||||
};
|
||||
|
||||
static std::vector<InnerBrimExPolygons> inner_brim_area(const Print &print,
|
||||
const ConstPrintObjectPtrs &top_level_objects_with_brim,
|
||||
const std::vector<ExPolygons> &bottom_layers_expolygons,
|
||||
const float no_brim_offset)
|
||||
{
|
||||
assert(print.objects().size() == bottom_layers_expolygons.size());
|
||||
std::vector<bool> has_nothing_inside = has_polygons_nothing_inside(print, bottom_layers_expolygons);
|
||||
std::unordered_set<size_t> top_level_objects_idx;
|
||||
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
|
||||
for (const PrintObject *object : top_level_objects_with_brim)
|
||||
top_level_objects_idx.insert(object->id().id);
|
||||
|
||||
ExPolygons brim_area;
|
||||
ExPolygons no_brim_area;
|
||||
Polygons holes;
|
||||
std::vector<ExPolygons> brim_area_innermost(print.objects().size());
|
||||
ExPolygons brim_area;
|
||||
ExPolygons no_brim_area;
|
||||
Polygons holes_reversed;
|
||||
|
||||
// polygon_idx must correspond to idx generated inside has_polygons_nothing_inside()
|
||||
size_t polygon_idx = 0;
|
||||
for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) {
|
||||
const PrintObject *object = print.objects()[print_object_idx];
|
||||
const BrimType brim_type = object->config().brim_type.value;
|
||||
@ -221,9 +298,10 @@ static ExPolygons inner_brim_area(const Print &print,
|
||||
const float brim_width = scale_(object->config().brim_width.value);
|
||||
const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
|
||||
|
||||
ExPolygons brim_area_innermost_object;
|
||||
ExPolygons brim_area_object;
|
||||
ExPolygons no_brim_area_object;
|
||||
Polygons holes_object;
|
||||
Polygons holes_reversed_object;
|
||||
for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) {
|
||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) {
|
||||
if (top_outer_brim)
|
||||
@ -235,8 +313,20 @@ static ExPolygons inner_brim_area(const Print &print,
|
||||
// After 7ff76d07684858fd937ef2f5d863f105a10f798e offset and shrink don't work with CW polygons (holes), so let's make it CCW.
|
||||
Polygons ex_poly_holes_reversed = ex_poly.holes;
|
||||
polygons_reverse(ex_poly_holes_reversed);
|
||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
|
||||
append(brim_area_object, diff_ex(shrink_ex(ex_poly_holes_reversed, brim_separation, ClipperLib::jtSquare), shrink_ex(ex_poly_holes_reversed, brim_width + brim_separation, ClipperLib::jtSquare)));
|
||||
for ([[maybe_unused]] const PrintInstance &instance : object->instances()) {
|
||||
++polygon_idx; // Increase idx because of the contour of the ExPolygon.
|
||||
|
||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
|
||||
for(const Polygon &hole : ex_poly_holes_reversed) {
|
||||
size_t hole_idx = &hole - &ex_poly_holes_reversed.front();
|
||||
if (has_nothing_inside[polygon_idx + hole_idx])
|
||||
append(brim_area_innermost_object, shrink_ex({hole}, brim_separation, ClipperLib::jtSquare));
|
||||
else
|
||||
append(brim_area_object, diff_ex(shrink_ex({hole}, brim_separation, ClipperLib::jtSquare), shrink_ex({hole}, brim_width + brim_separation, ClipperLib::jtSquare)));
|
||||
}
|
||||
|
||||
polygon_idx += ex_poly.holes.size(); // Increase idx for every hole of the ExPolygon.
|
||||
}
|
||||
|
||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim)
|
||||
append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly_holes_reversed));
|
||||
@ -244,18 +334,34 @@ static ExPolygons inner_brim_area(const Print &print,
|
||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
||||
append(no_brim_area_object, diff_ex(ExPolygon(ex_poly.contour), shrink_ex(ex_poly_holes_reversed, no_brim_offset, ClipperLib::jtSquare)));
|
||||
|
||||
append(holes_object, ex_poly_holes_reversed);
|
||||
append(holes_reversed_object, ex_poly_holes_reversed);
|
||||
}
|
||||
append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation, ClipperLib::jtSquare));
|
||||
|
||||
for (const PrintInstance &instance : object->instances()) {
|
||||
append_and_translate(brim_area_innermost[print_object_idx], brim_area_innermost_object, instance);
|
||||
append_and_translate(brim_area, brim_area_object, instance);
|
||||
append_and_translate(no_brim_area, no_brim_area_object, instance);
|
||||
append_and_translate(holes, holes_object, instance);
|
||||
append_and_translate(holes_reversed, holes_reversed_object, instance);
|
||||
}
|
||||
}
|
||||
assert(polygon_idx == has_nothing_inside.size());
|
||||
|
||||
return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area);
|
||||
ExPolygons brim_area_innermost_merged;
|
||||
// Append all innermost brim areas.
|
||||
std::vector<InnerBrimExPolygons> brim_area_out;
|
||||
for (size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx)
|
||||
if (const double brim_width = print.objects()[print_object_idx]->config().brim_width.value; !brim_area_innermost[print_object_idx].empty()) {
|
||||
append(brim_area_innermost_merged, brim_area_innermost[print_object_idx]);
|
||||
brim_area_out.push_back({std::move(brim_area_innermost[print_object_idx]), InnerBrimType::INNERMOST, brim_width});
|
||||
}
|
||||
|
||||
// Append all normal brim areas.
|
||||
brim_area_out.push_back({diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes_reversed), no_brim_area), InnerBrimType::NORMAL});
|
||||
|
||||
// Cut out a huge brim areas that overflows into the INNERMOST holes.
|
||||
brim_area_out.back().brim_area = diff_ex(brim_area_out.back().brim_area, brim_area_innermost_merged);
|
||||
return brim_area_out;
|
||||
}
|
||||
|
||||
// Flip orientation of open polylines to minimize travel distance.
|
||||
@ -359,17 +465,28 @@ static void make_inner_brim(const Print &print,
|
||||
ExtrusionEntityCollection &brim)
|
||||
{
|
||||
assert(print.objects().size() == bottom_layers_expolygons.size());
|
||||
const auto scaled_resolution = scaled<double>(print.config().gcode_resolution.value);
|
||||
Flow flow = print.brim_flow();
|
||||
ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing()));
|
||||
Polygons loops;
|
||||
islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), ClipperLib::jtSquare);
|
||||
for (size_t i = 0; !islands_ex.empty(); ++i) {
|
||||
for (ExPolygon &poly_ex : islands_ex)
|
||||
poly_ex.douglas_peucker(scaled_resolution);
|
||||
polygons_append(loops, to_polygons(islands_ex));
|
||||
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), ClipperLib::jtSquare);
|
||||
}
|
||||
const auto scaled_resolution = scaled<double>(print.config().gcode_resolution.value);
|
||||
Flow flow = print.brim_flow();
|
||||
std::vector<InnerBrimExPolygons> inner_brims_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing()));
|
||||
Polygons loops;
|
||||
std::mutex loops_mutex;
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, inner_brims_ex.size()), [&inner_brims_ex, &flow, &scaled_resolution, &loops, &loops_mutex](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t brim_idx = range.begin(); brim_idx < range.end(); ++brim_idx) {
|
||||
const InnerBrimExPolygons &inner_brim_ex = inner_brims_ex[brim_idx];
|
||||
auto num_loops = size_t(floor(inner_brim_ex.brim_width / flow.spacing()));
|
||||
ExPolygons islands_ex = offset_ex(inner_brim_ex.brim_area, -0.5f * float(flow.scaled_spacing()), ClipperLib::jtSquare);
|
||||
for (size_t i = 0; (inner_brim_ex.type == InnerBrimType::INNERMOST ? i < num_loops : !islands_ex.empty()); ++i) {
|
||||
for (ExPolygon &poly_ex : islands_ex)
|
||||
poly_ex.douglas_peucker(scaled_resolution);
|
||||
|
||||
{
|
||||
boost::lock_guard<std::mutex> lock(loops_mutex);
|
||||
polygons_append(loops, to_polygons(islands_ex));
|
||||
}
|
||||
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), ClipperLib::jtSquare);
|
||||
}
|
||||
}
|
||||
}); // end of parallel_for
|
||||
|
||||
loops = union_pt_chained_outside_in(loops);
|
||||
std::reverse(loops.begin(), loops.end());
|
||||
|
@ -1047,7 +1047,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
|
||||
if (! print.config().gcode_substitutions.values.empty()) {
|
||||
m_find_replace = make_unique<GCodeFindReplace>(print.config());
|
||||
file.set_find_replace(m_find_replace.get());
|
||||
file.set_find_replace(m_find_replace.get(), false);
|
||||
}
|
||||
|
||||
// resets analyzer's tracking data
|
||||
@ -1155,6 +1155,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
|
||||
// Starting now, the G-code find / replace post-processor will be enabled.
|
||||
file.find_replace_enable();
|
||||
|
||||
// adds tags for time estimators
|
||||
if (print.config().remaining_times.value)
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
|
||||
@ -1461,6 +1464,10 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
|
||||
|
||||
// From now to the end of G-code, the G-code find / replace post-processor will be disabled.
|
||||
// Thus the PrusaSlicer generated config will NOT be processed by the G-code post-processor, see GH issue #7952.
|
||||
file.find_replace_supress();
|
||||
|
||||
// Append full config, delimited by two 'phony' configuration keys prusaslicer_config = begin and prusaslicer_config = end.
|
||||
// The delimiters are structured as configuration key / value pairs to be parsable by older versions of PrusaSlicer G-code viewer.
|
||||
{
|
||||
@ -1518,7 +1525,7 @@ void GCode::process_layers(
|
||||
);
|
||||
|
||||
// The pipeline elements are joined using const references, thus no copying is performed.
|
||||
output_stream.set_find_replace(nullptr);
|
||||
output_stream.find_replace_supress();
|
||||
if (m_spiral_vase && m_find_replace)
|
||||
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & find_replace & output);
|
||||
else if (m_spiral_vase)
|
||||
@ -1527,7 +1534,7 @@ void GCode::process_layers(
|
||||
tbb::parallel_pipeline(12, generator & cooling & find_replace & output);
|
||||
else
|
||||
tbb::parallel_pipeline(12, generator & cooling & output);
|
||||
output_stream.set_find_replace(m_find_replace.get());
|
||||
output_stream.find_replace_enable();
|
||||
}
|
||||
|
||||
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
|
||||
@ -1571,7 +1578,7 @@ void GCode::process_layers(
|
||||
);
|
||||
|
||||
// The pipeline elements are joined using const references, thus no copying is performed.
|
||||
output_stream.set_find_replace(nullptr);
|
||||
output_stream.find_replace_supress();
|
||||
if (m_spiral_vase && m_find_replace)
|
||||
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & find_replace & output);
|
||||
else if (m_spiral_vase)
|
||||
@ -1580,7 +1587,7 @@ void GCode::process_layers(
|
||||
tbb::parallel_pipeline(12, generator & cooling & find_replace & output);
|
||||
else
|
||||
tbb::parallel_pipeline(12, generator & cooling & output);
|
||||
output_stream.set_find_replace(m_find_replace.get());
|
||||
output_stream.find_replace_enable();
|
||||
}
|
||||
|
||||
std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)
|
||||
|
@ -196,7 +196,9 @@ private:
|
||||
// Set a find-replace post-processor to modify the G-code before GCodePostProcessor.
|
||||
// It is being set to null inside process_layers(), because the find-replace process
|
||||
// is being called on a secondary thread to improve performance.
|
||||
void set_find_replace(GCodeFindReplace *find_replace) { m_find_replace = find_replace; }
|
||||
void set_find_replace(GCodeFindReplace *find_replace, bool enabled) { m_find_replace_backup = find_replace; m_find_replace = enabled ? find_replace : nullptr; }
|
||||
void find_replace_enable() { m_find_replace = m_find_replace_backup; }
|
||||
void find_replace_supress() { m_find_replace = nullptr; }
|
||||
|
||||
bool is_open() const { return f; }
|
||||
bool is_error() const;
|
||||
@ -220,6 +222,8 @@ private:
|
||||
FILE *f { nullptr };
|
||||
// Find-replace post-processor to be called before GCodePostProcessor.
|
||||
GCodeFindReplace *m_find_replace { nullptr };
|
||||
// If suppressed, the backoup holds m_find_replace.
|
||||
GCodeFindReplace *m_find_replace_backup { nullptr };
|
||||
GCodeProcessor &m_processor;
|
||||
};
|
||||
void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb);
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <unordered_set>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
//#define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
struct TravelPoint
|
||||
@ -354,8 +356,6 @@ static Polyline to_polyline(const std::vector<TravelPoint> &travel)
|
||||
return result;
|
||||
}
|
||||
|
||||
// #define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
|
||||
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
|
||||
static void export_travel_to_svg(const Polygons &boundary,
|
||||
const Line &original_travel,
|
||||
@ -521,6 +521,25 @@ static float get_perimeter_spacing_external(const Layer &layer)
|
||||
return perimeter_spacing;
|
||||
}
|
||||
|
||||
// Returns average perimeter width calculated from all LayerRegion within the layer.
|
||||
static float get_external_perimeter_width(const Layer &layer)
|
||||
{
|
||||
size_t regions_count = 0;
|
||||
float perimeter_width = 0.f;
|
||||
for (const LayerRegion *layer_region : layer.regions())
|
||||
if (layer_region != nullptr && !layer_region->slices.empty()) {
|
||||
perimeter_width += float(layer_region->flow(frExternalPerimeter).scaled_width());
|
||||
++regions_count;
|
||||
}
|
||||
|
||||
assert(perimeter_width >= 0.f);
|
||||
if (regions_count != 0)
|
||||
perimeter_width /= float(regions_count);
|
||||
else
|
||||
perimeter_width = get_default_perimeter_spacing(*layer.object());
|
||||
return perimeter_width;
|
||||
}
|
||||
|
||||
// Called by avoid_perimeters() and by simplify_travel_heuristics().
|
||||
static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary,
|
||||
const Point &start,
|
||||
@ -659,22 +678,22 @@ static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary
|
||||
// Check if anyone of ExPolygons contains whole travel.
|
||||
// called by need_wipe() and AvoidCrossingPerimeters::travel_to()
|
||||
// FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains()
|
||||
static bool any_expolygon_contains(const ExPolygons &ex_polygons,
|
||||
const std::vector<BoundingBox> &ex_polygons_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslice,
|
||||
static bool any_expolygon_contains(const ExPolygons &lslices_offset,
|
||||
const std::vector<BoundingBox> &lslices_offset_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslices_offset,
|
||||
const Line &travel)
|
||||
{
|
||||
assert(ex_polygons.size() == ex_polygons_bboxes.size());
|
||||
if(!grid_lslice.bbox().contains(travel.a) || !grid_lslice.bbox().contains(travel.b))
|
||||
assert(lslices_offset.size() == lslices_offset_bboxes.size());
|
||||
if(!grid_lslices_offset.bbox().contains(travel.a) || !grid_lslices_offset.bbox().contains(travel.b))
|
||||
return false;
|
||||
|
||||
FirstIntersectionVisitor visitor(grid_lslice);
|
||||
FirstIntersectionVisitor visitor(grid_lslices_offset);
|
||||
visitor.pt_current = &travel.a;
|
||||
visitor.pt_next = &travel.b;
|
||||
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
|
||||
grid_lslices_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
|
||||
if (!visitor.intersect) {
|
||||
for (const ExPolygon &ex_polygon : ex_polygons) {
|
||||
const BoundingBox &bbox = ex_polygons_bboxes[&ex_polygon - &ex_polygons.front()];
|
||||
for (const ExPolygon &ex_polygon : lslices_offset) {
|
||||
const BoundingBox &bbox = lslices_offset_bboxes[&ex_polygon - &lslices_offset.front()];
|
||||
if (bbox.contains(travel.a) && bbox.contains(travel.b) && ex_polygon.contains(travel.a))
|
||||
return true;
|
||||
}
|
||||
@ -684,18 +703,18 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons,
|
||||
|
||||
// Check if anyone of ExPolygons contains whole travel.
|
||||
// called by need_wipe()
|
||||
static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice, const Polyline &travel)
|
||||
static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice_offset, const Polyline &travel)
|
||||
{
|
||||
assert(ex_polygons.size() == ex_polygons_bboxes.size());
|
||||
if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice](const Point &point) { return !grid_lslice.bbox().contains(point); }))
|
||||
if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice_offset](const Point &point) { return !grid_lslice_offset.bbox().contains(point); }))
|
||||
return false;
|
||||
|
||||
FirstIntersectionVisitor visitor(grid_lslice);
|
||||
FirstIntersectionVisitor visitor(grid_lslice_offset);
|
||||
bool any_intersection = false;
|
||||
for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) {
|
||||
visitor.pt_current = &travel.points[line_idx - 1];
|
||||
visitor.pt_next = &travel.points[line_idx];
|
||||
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
|
||||
grid_lslice_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
|
||||
any_intersection = visitor.intersect;
|
||||
if (any_intersection) break;
|
||||
}
|
||||
@ -711,14 +730,14 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vec
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool need_wipe(const GCode &gcodegen,
|
||||
const EdgeGrid::Grid &grid_lslice,
|
||||
const Line &original_travel,
|
||||
const Polyline &result_travel,
|
||||
const size_t intersection_count)
|
||||
static bool need_wipe(const GCode &gcodegen,
|
||||
const ExPolygons &lslices_offset,
|
||||
const std::vector<BoundingBox> &lslices_offset_bboxes,
|
||||
const EdgeGrid::Grid &grid_lslices_offset,
|
||||
const Line &original_travel,
|
||||
const Polyline &result_travel,
|
||||
const size_t intersection_count)
|
||||
{
|
||||
const ExPolygons &lslices = gcodegen.layer()->lslices;
|
||||
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
|
||||
bool z_lift_enabled = gcodegen.config().retract_lift.get_at(gcodegen.writer().extruder()->id()) > 0.;
|
||||
bool wipe_needed = false;
|
||||
|
||||
@ -728,16 +747,16 @@ static bool need_wipe(const GCode &gcodegen,
|
||||
// The original layer is intersected with defined boundaries. Then it is necessary to make a detailed test.
|
||||
// If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes.
|
||||
if (z_lift_enabled) {
|
||||
if (any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, original_travel)) {
|
||||
if (any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, original_travel)) {
|
||||
// Check if original_travel and result_travel are not same.
|
||||
// If both are the same, then it is possible to skip testing of result_travel
|
||||
wipe_needed = !(result_travel.size() > 2 && result_travel.first_point() == original_travel.a && result_travel.last_point() == original_travel.b) &&
|
||||
!any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel);
|
||||
!any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
|
||||
} else {
|
||||
wipe_needed = true;
|
||||
}
|
||||
} else {
|
||||
wipe_needed = !any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel);
|
||||
wipe_needed = !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1163,10 +1182,8 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
||||
Vec2d startf = start.cast<double>();
|
||||
Vec2d endf = end .cast<double>();
|
||||
|
||||
const ExPolygons &lslices = gcodegen.layer()->lslices;
|
||||
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
|
||||
bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
|
||||
if (!use_external && (is_support_layer || (!lslices.empty() && !any_expolygon_contains(lslices, lslices_bboxes, m_grid_lslice, travel)))) {
|
||||
bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
|
||||
if (!use_external && (is_support_layer || (!m_lslices_offset.empty() && !any_expolygon_contains(m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel)))) {
|
||||
// Initialize m_internal only when it is necessary.
|
||||
if (m_internal.boundaries.empty())
|
||||
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
|
||||
@ -1216,7 +1233,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
|
||||
} else if (max_detour_length_exceeded) {
|
||||
*could_be_wipe_disabled = false;
|
||||
} else
|
||||
*could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count);
|
||||
*could_be_wipe_disabled = !need_wipe(gcodegen, m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel, result_pl, travel_intersection_count);
|
||||
|
||||
return result_pl;
|
||||
}
|
||||
@ -1227,13 +1244,21 @@ void AvoidCrossingPerimeters::init_layer(const Layer &layer)
|
||||
{
|
||||
m_internal.clear();
|
||||
m_external.clear();
|
||||
m_lslices_offset.clear();
|
||||
m_lslices_offset_bboxes.clear();
|
||||
|
||||
float perimeter_offset = -get_external_perimeter_width(layer) / float(2.);
|
||||
m_lslices_offset = offset_ex(layer.lslices, perimeter_offset);
|
||||
|
||||
m_lslices_offset_bboxes.reserve(m_lslices_offset.size());
|
||||
for (const ExPolygon &ex_poly : m_lslices_offset)
|
||||
m_lslices_offset_bboxes.emplace_back(get_extents(ex_poly));
|
||||
|
||||
BoundingBox bbox_slice(get_extents(layer.lslices));
|
||||
bbox_slice.offset(SCALED_EPSILON);
|
||||
|
||||
m_grid_lslice.set_bbox(bbox_slice);
|
||||
//FIXME 1mm grid?
|
||||
m_grid_lslice.create(layer.lslices, coord_t(scale_(1.)));
|
||||
m_grid_lslices_offset.set_bbox(bbox_slice);
|
||||
m_grid_lslices_offset.create(m_lslices_offset, coord_t(scale_(1.)));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -58,8 +58,11 @@ private:
|
||||
// we enable it by default for the first travel move in print
|
||||
bool m_disabled_once { true };
|
||||
|
||||
// Lslices offseted by half an external perimeter width. Used for detection if line or polyline is inside of any polygon.
|
||||
ExPolygons m_lslices_offset;
|
||||
std::vector<BoundingBox> m_lslices_offset_bboxes;
|
||||
// Used for detection of line or polyline is inside of any polygon.
|
||||
EdgeGrid::Grid m_grid_lslice;
|
||||
EdgeGrid::Grid m_grid_lslices_offset;
|
||||
// Store all needed data for travels inside object
|
||||
Boundary m_internal;
|
||||
// Store all needed data for travels outside object
|
||||
|
@ -605,7 +605,7 @@ struct MMU_Graph
|
||||
if (arcs[arc_idx].to_idx == to_idx)
|
||||
return;
|
||||
for (const size_t &arc_idx : this->nodes[to_idx].arc_idxs)
|
||||
if (arcs[arc_idx].to_idx == to_idx)
|
||||
if (arcs[arc_idx].to_idx == from_idx)
|
||||
return;
|
||||
|
||||
this->nodes[from_idx].arc_idxs.push_back(this->arcs.size());
|
||||
@ -1201,7 +1201,7 @@ static inline double compute_edge_length(const MMU_Graph &graph, const size_t st
|
||||
used_arcs[start_arc_idx] = true;
|
||||
const MMU_Graph::Arc *arc = &graph.arcs[start_arc_idx];
|
||||
size_t idx = start_idx;
|
||||
double line_total_length = (graph.nodes[arc->to_idx].point - graph.nodes[idx].point).norm();;
|
||||
double line_total_length = (graph.nodes[arc->to_idx].point - graph.nodes[idx].point).norm();
|
||||
while (graph.nodes[arc->to_idx].arc_idxs.size() == 2) {
|
||||
bool found = false;
|
||||
for (const size_t &arc_idx : graph.nodes[arc->to_idx].arc_idxs) {
|
||||
@ -1711,7 +1711,7 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
|
||||
// Such close points sometimes caused that the Voronoi diagram has self-intersecting edges around these vertices.
|
||||
// This consequently leads to issues with the extraction of colored segments by function extract_colored_segments.
|
||||
// Calling expolygons_simplify fixed these issues.
|
||||
input_expolygons[layer_idx] = smooth_outward(expolygons_simplify(offset_ex(ex_polygons, -10.f * float(SCALED_EPSILON)), 5 * SCALED_EPSILON), 10 * coord_t(SCALED_EPSILON));
|
||||
input_expolygons[layer_idx] = remove_duplicates(expolygons_simplify(offset_ex(ex_polygons, -10.f * float(SCALED_EPSILON)), 5 * SCALED_EPSILON), scaled<coord_t>(0.01), PI/6);
|
||||
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_INPUT
|
||||
{
|
||||
|
@ -37,6 +37,36 @@ void remove_duplicates(MutablePolygon &polygon, double eps)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove nearly duplicate points. If a distance between two points is less than scaled_eps
|
||||
// and if the angle between its surrounding lines is less than max_angle, the point will be removed.
|
||||
// May reduce the polygon down to empty polygon.
|
||||
void remove_duplicates(MutablePolygon &polygon, coord_t scaled_eps, const double max_angle)
|
||||
{
|
||||
if (polygon.size() >= 3) {
|
||||
auto cos_max_angle_2 = Slic3r::sqr<double>(cos(max_angle));
|
||||
auto scaled_eps_sqr = Slic3r::sqr<int64_t>(scaled_eps);
|
||||
auto begin = polygon.begin();
|
||||
auto it = begin;
|
||||
for (++it; it != begin;) {
|
||||
auto prev = it.prev();
|
||||
auto next = it.next();
|
||||
Vec2i64 v1 = (*it - *prev).cast<int64_t>();
|
||||
int64_t v1_sqr_norm = v1.squaredNorm();
|
||||
if (v1_sqr_norm < scaled_eps_sqr) {
|
||||
if (Vec2i64 v2 = (*next - *prev).cast<int64_t>();
|
||||
Slic3r::sqr<double>(double(v1.dot(v2))) > cos_max_angle_2 * double(v1_sqr_norm) * double(v2.squaredNorm())) {
|
||||
it = it.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
it = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (polygon.size() < 3)
|
||||
polygon.clear();
|
||||
}
|
||||
|
||||
// Adapted from Cura ConstPolygonRef::smooth_corner_complex() by Tim Kuipers.
|
||||
// A concave corner at it1 with position p1 has been removed by the caller between it0 and it2, where |p2 - p0| < shortcut_length.
|
||||
// Now try to close a concave crack by walking left from it0 and right from it2 as long as the new clipping edge is smaller than shortcut_length
|
||||
|
@ -309,6 +309,28 @@ inline bool operator!=(const MutablePolygon &p1, const MutablePolygon &p2) { ret
|
||||
void remove_duplicates(MutablePolygon &polygon);
|
||||
void remove_duplicates(MutablePolygon &polygon, double eps);
|
||||
|
||||
// Remove nearly duplicate points. If a distance between two points is less than scaled_eps
|
||||
// and if the angle between its surrounding lines is less than max_angle, the point will be removed.
|
||||
// May reduce the polygon down to empty polygon.
|
||||
void remove_duplicates(MutablePolygon &polygon, coord_t scaled_eps, const double max_angle);
|
||||
inline ExPolygons remove_duplicates(ExPolygons expolygons, coord_t scaled_eps, double max_angle)
|
||||
{
|
||||
MutablePolygon mp;
|
||||
for (ExPolygon &expolygon : expolygons) {
|
||||
mp.assign(expolygon.contour, expolygon.contour.size() * 2);
|
||||
remove_duplicates(mp, scaled_eps, max_angle);
|
||||
mp.polygon(expolygon.contour);
|
||||
for (Polygon &hole : expolygon.holes) {
|
||||
mp.assign(hole, hole.size() * 2);
|
||||
remove_duplicates(mp, scaled_eps, max_angle);
|
||||
mp.polygon(hole);
|
||||
}
|
||||
expolygon.holes.erase(std::remove_if(expolygon.holes.begin(), expolygon.holes.end(), [](const auto &p) { return p.empty(); }), expolygon.holes.end());
|
||||
}
|
||||
expolygons.erase(std::remove_if(expolygons.begin(), expolygons.end(), [](const auto &p) { return p.empty(); }), expolygons.end());
|
||||
return expolygons;
|
||||
}
|
||||
|
||||
void smooth_outward(MutablePolygon &polygon, coord_t clip_dist_scaled);
|
||||
|
||||
inline Polygon smooth_outward(Polygon polygon, coord_t clip_dist_scaled)
|
||||
|
@ -412,6 +412,8 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
||||
for (auto it = this->renamed_from.begin(); ! is_visible && it != this->renamed_from.end(); ++ it)
|
||||
is_visible = has(*it);
|
||||
}
|
||||
else
|
||||
is_visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,7 +793,8 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
|
||||
// The source config may contain keys from many possible preset types. Just copy those that relate to this preset.
|
||||
this->get_edited_preset().config.apply_only(combined_config, keys, true);
|
||||
this->update_dirty();
|
||||
update_saved_preset_from_current_preset();
|
||||
// Don't save the newly loaded project as a "saved into project" state.
|
||||
//update_saved_preset_from_current_preset();
|
||||
assert(this->get_edited_preset().is_dirty);
|
||||
return std::make_pair(&(*it), this->get_edited_preset().is_dirty);
|
||||
}
|
||||
@ -1226,7 +1229,6 @@ Preset& PresetCollection::select_preset(size_t idx)
|
||||
idx = first_visible_idx();
|
||||
m_idx_selected = idx;
|
||||
m_edited_preset = m_presets[idx];
|
||||
update_saved_preset_from_current_preset();
|
||||
bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets;
|
||||
for (size_t i = 0; i < m_num_default_presets; ++i)
|
||||
m_presets[i].is_visible = default_visible;
|
||||
|
@ -397,6 +397,7 @@ public:
|
||||
void discard_current_changes() {
|
||||
m_presets[m_idx_selected].reset_dirty();
|
||||
m_edited_preset = m_presets[m_idx_selected];
|
||||
// Don't save the resetted preset state as a "saved into project" state.
|
||||
// update_saved_preset_from_current_preset();
|
||||
}
|
||||
|
||||
|
@ -660,7 +660,8 @@ std::string Print::validate(std::string* warning) const
|
||||
bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_gcode.value, regex_g92e0);
|
||||
if (m_config.use_relative_e_distances) {
|
||||
// See GH issues #6336 #5073
|
||||
if (! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder)
|
||||
if ((m_config.gcode_flavor == gcfMarlinLegacy || m_config.gcode_flavor == gcfMarlinFirmware) &&
|
||||
! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder)
|
||||
return L("Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode.");
|
||||
} else if (before_layer_gcode_resets_extruder)
|
||||
return L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing.");
|
||||
|
@ -193,7 +193,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Mouse3DController.hpp
|
||||
GUI/DoubleSlider.cpp
|
||||
GUI/DoubleSlider.hpp
|
||||
GUI/DoubleSlider_Utils.hpp
|
||||
GUI/Notebook.cpp
|
||||
GUI/Notebook.hpp
|
||||
GUI/ObjectDataViewModel.cpp
|
||||
|
@ -593,10 +593,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
|
||||
if (bottom)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
unsigned int stride = m_triangles.get_vertex_data_size();
|
||||
|
||||
GLint position_id = shader->get_attrib_location("v_position");
|
||||
GLint tex_coords_id = shader->get_attrib_location("v_tex_coords");
|
||||
const unsigned int stride = m_triangles.get_vertex_data_size();
|
||||
|
||||
// show the temporary texture while no compressed data is available
|
||||
GLuint tex_id = (GLuint)m_temp_texture.get_id();
|
||||
@ -606,22 +603,16 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
||||
|
||||
if (position_id != -1) {
|
||||
glsafe(::glEnableVertexAttribArray(position_id));
|
||||
glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_position_offset()));
|
||||
}
|
||||
if (tex_coords_id != -1) {
|
||||
glsafe(::glEnableVertexAttribArray(tex_coords_id));
|
||||
glsafe(::glVertexAttribPointer(tex_coords_id, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_tex_coords_offset()));
|
||||
}
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, stride, (const void*)(intptr_t)m_triangles.get_position_offset()));
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glTexCoordPointer(2, GL_FLOAT, stride, (const void*)(intptr_t)m_triangles.get_tex_coords_offset()));
|
||||
glsafe(::glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)m_triangles.get_vertices_count()));
|
||||
|
||||
if (tex_coords_id != -1)
|
||||
glsafe(::glDisableVertexAttribArray(tex_coords_id));
|
||||
|
||||
if (position_id != -1)
|
||||
glsafe(::glDisableVertexAttribArray(position_id));
|
||||
glsafe(::glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
@ -122,6 +122,10 @@ Control::Control( wxWindow *parent,
|
||||
this->Bind(wxEVT_KEY_UP, &Control::OnKeyUp, this);
|
||||
this->Bind(wxEVT_RIGHT_DOWN, &Control::OnRightDown,this);
|
||||
this->Bind(wxEVT_RIGHT_UP, &Control::OnRightUp, this);
|
||||
this->Bind(wxEVT_SIZE, [this](wxSizeEvent& event) {
|
||||
m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
// control's view variables
|
||||
SLIDER_MARGIN = 4 + GUI::wxGetApp().em_unit();
|
||||
@ -137,8 +141,14 @@ Control::Control( wxWindow *parent,
|
||||
m_line_pens = { &DARK_GREY_PEN, &GREY_PEN, &LIGHT_GREY_PEN };
|
||||
m_segm_pens = { &DARK_ORANGE_PEN, &ORANGE_PEN, &LIGHT_ORANGE_PEN };
|
||||
|
||||
FOCUS_RECT_PEN = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT);
|
||||
FOCUS_RECT_BRUSH = wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT);
|
||||
|
||||
m_font = GetFont();
|
||||
this->SetMinSize(get_min_size());
|
||||
|
||||
if (style == wxSL_VERTICAL)
|
||||
m_ruler.set_parent(this->GetParent());
|
||||
}
|
||||
|
||||
void Control::msw_rescale()
|
||||
@ -170,6 +180,9 @@ void Control::msw_rescale()
|
||||
|
||||
SetMinSize(get_min_size());
|
||||
GetParent()->Layout();
|
||||
|
||||
m_ruler.update_dpi();
|
||||
m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
}
|
||||
|
||||
void Control::sys_color_changed()
|
||||
@ -266,7 +279,11 @@ void Control::SetMaxValue(const int max_value)
|
||||
void Control::SetSliderValues(const std::vector<double>& values)
|
||||
{
|
||||
m_values = values;
|
||||
m_ruler.init(m_values);
|
||||
m_ruler.init(m_values, get_scroll_step());
|
||||
|
||||
// When "No sparce layer" is enabled, use m_layers_values for ruler update.
|
||||
// Because of m_values has duplicate values in this case.
|
||||
// m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
}
|
||||
|
||||
void Control::draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos)
|
||||
@ -426,9 +443,12 @@ void Control::SetLayersTimes(const std::vector<float>& layers_times, float total
|
||||
if (m_layers_values.size() != m_layers_times.size())
|
||||
for (size_t i = m_layers_times.size(); i < m_layers_values.size(); i++)
|
||||
m_layers_times.push_back(total_time);
|
||||
m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
Refresh();
|
||||
Update();
|
||||
}
|
||||
else
|
||||
m_ruler.update(m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
}
|
||||
|
||||
void Control::SetLayersTimes(const std::vector<double>& layers_times)
|
||||
@ -494,15 +514,17 @@ void Control::get_lower_and_higher_position(int& lower_pos, int& higher_pos)
|
||||
}
|
||||
}
|
||||
|
||||
void Control::draw_focus_rect()
|
||||
void Control::draw_focus_rect(wxDC& dc)
|
||||
{
|
||||
if (!m_is_focused)
|
||||
return;
|
||||
const wxSize sz = GetSize();
|
||||
wxPaintDC dc(this);
|
||||
const wxPen pen = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT);
|
||||
dc.SetPen(pen);
|
||||
dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT));
|
||||
// wxPaintDC dc(this);
|
||||
//const wxPen pen = wxPen(wxColour(128, 128, 10), 1, wxPENSTYLE_DOT);
|
||||
//dc.SetPen(pen);
|
||||
//dc.SetBrush(wxBrush(wxColour(0, 0, 0), wxBRUSHSTYLE_TRANSPARENT));
|
||||
dc.SetPen(FOCUS_RECT_PEN);
|
||||
dc.SetBrush(FOCUS_RECT_BRUSH);
|
||||
dc.DrawRectangle(1, 1, sz.x - 2, sz.y - 2);
|
||||
}
|
||||
|
||||
@ -513,11 +535,12 @@ void Control::render()
|
||||
#else
|
||||
SetBackgroundColour(GetParent()->GetBackgroundColour());
|
||||
#endif // _WIN32
|
||||
draw_focus_rect();
|
||||
|
||||
wxPaintDC dc(this);
|
||||
dc.SetFont(m_font);
|
||||
|
||||
draw_focus_rect(dc);
|
||||
|
||||
const wxCoord lower_pos = get_position_from_value(m_lower_value);
|
||||
const wxCoord higher_pos = get_position_from_value(m_higher_value);
|
||||
|
||||
@ -807,7 +830,7 @@ void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, LabelType l
|
||||
}
|
||||
|
||||
wxColour old_clr = dc.GetTextForeground();
|
||||
const wxPen& pen = is_wipe_tower_layer(tick) && (tick == m_lower_value || tick == m_higher_value) ? DARK_ORANGE_PEN : wxPen(old_clr);
|
||||
const wxPen& pen = is_wipe_tower_layer(tick) && (tick == m_lower_value || tick == m_higher_value) ? DARK_ORANGE_PEN : /*wxPen(old_clr)*/GREY_PEN;
|
||||
dc.SetPen(pen);
|
||||
dc.SetTextForeground(pen.GetColour());
|
||||
|
||||
@ -1028,8 +1051,10 @@ void Control::draw_colored_band(wxDC& dc)
|
||||
}
|
||||
}
|
||||
|
||||
void Control::Ruler::init(const std::vector<double>& values)
|
||||
void Control::Ruler::init(const std::vector<double>& values, double scroll_step)
|
||||
{
|
||||
if (!m_parent)
|
||||
return;
|
||||
max_values.clear();
|
||||
max_values.reserve(std::count(values.begin(), values.end(), values.front()));
|
||||
|
||||
@ -1039,14 +1064,35 @@ void Control::Ruler::init(const std::vector<double>& values)
|
||||
it = std::find(it + 1, values.end(), values.front());
|
||||
}
|
||||
max_values.push_back(*(it - 1));
|
||||
|
||||
update(values, scroll_step);
|
||||
}
|
||||
|
||||
void Control::Ruler::update(wxWindow* win, const std::vector<double>& values, double scroll_step)
|
||||
void Control::Ruler::set_parent(wxWindow* parent)
|
||||
{
|
||||
if (values.empty())
|
||||
m_parent = parent;
|
||||
update_dpi();
|
||||
}
|
||||
|
||||
void Control::Ruler::update_dpi()
|
||||
{
|
||||
if (m_parent)
|
||||
m_DPI = GUI::get_dpi_for_window(m_parent);
|
||||
}
|
||||
|
||||
void Control::Ruler::update(const std::vector<double>& values, double scroll_step)
|
||||
{
|
||||
if (!m_parent || values.empty() ||
|
||||
// check if need to update ruler in respect to input values
|
||||
values.front() == m_min_val && values.back() == m_max_val && m_scroll_step == scroll_step && max_values.size() == m_max_values_cnt)
|
||||
return;
|
||||
int DPI = GUI::get_dpi_for_window(win);
|
||||
int pixels_per_sm = lround((double)(DPI) * 5.0/25.4);
|
||||
|
||||
m_min_val = values.front();
|
||||
m_max_val = values.back();
|
||||
m_scroll_step = scroll_step;
|
||||
m_max_values_cnt = max_values.size();
|
||||
|
||||
int pixels_per_sm = lround((double)(m_DPI) * 5.0/25.4);
|
||||
|
||||
if (lround(scroll_step) > pixels_per_sm) {
|
||||
long_step = -1.0;
|
||||
@ -1091,11 +1137,11 @@ void Control::Ruler::update(wxWindow* win, const std::vector<double>& values, do
|
||||
|
||||
void Control::draw_ruler(wxDC& dc)
|
||||
{
|
||||
if (m_values.empty())
|
||||
if (m_values.empty() || !m_ruler.can_draw())
|
||||
return;
|
||||
// When "No sparce layer" is enabled, use m_layers_values for ruler update.
|
||||
// Because of m_values has duplicate values in this case.
|
||||
m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
// m_ruler.update(this->GetParent(), m_layers_values.empty() ? m_values : m_layers_values, get_scroll_step());
|
||||
|
||||
int height, width;
|
||||
get_size(&width, &height);
|
||||
|
@ -303,7 +303,7 @@ public:
|
||||
protected:
|
||||
|
||||
void render();
|
||||
void draw_focus_rect();
|
||||
void draw_focus_rect(wxDC& dc);
|
||||
void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end);
|
||||
void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos);
|
||||
void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection);
|
||||
@ -438,19 +438,36 @@ private:
|
||||
wxPen GREY_PEN;
|
||||
wxPen LIGHT_GREY_PEN;
|
||||
|
||||
wxPen FOCUS_RECT_PEN;
|
||||
wxBrush FOCUS_RECT_BRUSH;
|
||||
|
||||
std::vector<wxPen*> m_line_pens;
|
||||
std::vector<wxPen*> m_segm_pens;
|
||||
|
||||
struct Ruler {
|
||||
class Ruler {
|
||||
wxWindow* m_parent{nullptr}; // m_parent is nullptr for Unused ruler
|
||||
// in this case we will not init/update/render it
|
||||
// values to check if ruler has to be updated
|
||||
double m_min_val;
|
||||
double m_max_val;
|
||||
double m_scroll_step;
|
||||
size_t m_max_values_cnt;
|
||||
int m_DPI;
|
||||
|
||||
public:
|
||||
|
||||
double long_step;
|
||||
double short_step;
|
||||
std::vector<double> max_values;// max value for each object/instance in sequence print
|
||||
// > 1 for sequential print
|
||||
|
||||
void init(const std::vector<double>& values);
|
||||
void update(wxWindow* win, const std::vector<double>& values, double scroll_step);
|
||||
void set_parent(wxWindow* parent);
|
||||
void update_dpi();
|
||||
void init(const std::vector<double>& values, double scroll_step);
|
||||
void update(const std::vector<double>& values, double scroll_step);
|
||||
bool is_ok() { return long_step > 0 && short_step > 0; }
|
||||
size_t count() { return max_values.size(); }
|
||||
bool can_draw() { return m_parent != nullptr; }
|
||||
} m_ruler;
|
||||
};
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
#ifndef slic3r_GUI_DoubleSlider_Utils_hpp_
|
||||
#define slic3r_GUI_DoubleSlider_Utils_hpp_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <random>
|
||||
|
||||
|
||||
#endif // slic3r_GUI_DoubleSlider_Utils_hpp_
|
@ -2774,7 +2774,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
m_dirty = true;
|
||||
},
|
||||
[this](const Vec3d& direction, bool slow, bool camera_space) {
|
||||
m_selection.start_dragging();
|
||||
m_selection.setup_cache();
|
||||
double multiplier = slow ? 1.0 : 10.0;
|
||||
|
||||
Vec3d displacement;
|
||||
@ -2787,7 +2787,6 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
displacement = multiplier * direction;
|
||||
|
||||
m_selection.translate(displacement);
|
||||
m_selection.stop_dragging();
|
||||
m_dirty = true;
|
||||
}
|
||||
);
|
||||
@ -2884,9 +2883,8 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
m_dirty = true;
|
||||
else if (m_gizmos.is_enabled() && !m_selection.is_empty()) {
|
||||
auto do_rotate = [this](double angle_z_rad) {
|
||||
m_selection.start_dragging();
|
||||
m_selection.setup_cache();
|
||||
m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint));
|
||||
m_selection.stop_dragging();
|
||||
m_dirty = true;
|
||||
// wxGetApp().obj_manipul()->set_dirty();
|
||||
};
|
||||
@ -3352,7 +3350,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None;
|
||||
// The dragging operation is initiated.
|
||||
m_mouse.drag.move_volume_idx = volume_idx;
|
||||
m_selection.start_dragging();
|
||||
m_selection.setup_cache();
|
||||
m_mouse.drag.start_position_3D = m_mouse.scene_position;
|
||||
m_sequential_print_clearance_first_displacement = true;
|
||||
m_moving = true;
|
||||
@ -3464,9 +3462,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
}
|
||||
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) {
|
||||
if (evt.LeftUp())
|
||||
m_selection.stop_dragging();
|
||||
|
||||
if (m_layers_editing.state != LayersEditing::Unknown) {
|
||||
m_layers_editing.state = LayersEditing::Unknown;
|
||||
_stop_timer();
|
||||
|
@ -998,7 +998,7 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
|
||||
shader->set_uniform("uniform_color", data.color);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
|
||||
glsafe(::glDrawElements(mode, range.second - range.first + 1, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format))));
|
||||
glsafe(::glDrawElements(mode, range.second - range.first, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format))));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
|
||||
if (tex_coord)
|
||||
|
@ -1285,8 +1285,13 @@ bool GUI_App::on_init_inner()
|
||||
else
|
||||
load_current_presets();
|
||||
|
||||
// Save the active profiles as a "saved into project".
|
||||
update_saved_preset_from_current_preset();
|
||||
|
||||
if (plater_ != nullptr) {
|
||||
// Save the names of active presets and project specific config into ProjectDirtyStateManager.
|
||||
plater_->reset_project_dirty_initial_presets();
|
||||
// Update Project dirty state, update application title bar.
|
||||
plater_->update_project_dirty_from_presets();
|
||||
}
|
||||
|
||||
@ -2447,16 +2452,13 @@ void GUI_App::update_saved_preset_from_current_preset()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<unsigned int, std::string>> GUI_App::get_selected_presets() const
|
||||
std::vector<const PresetCollection*> GUI_App::get_active_preset_collections() const
|
||||
{
|
||||
std::vector<std::pair<unsigned int, std::string>> ret;
|
||||
std::vector<const PresetCollection*> ret;
|
||||
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
for (Tab* tab : tabs_list) {
|
||||
if (tab->supports_printer_technology(printer_technology)) {
|
||||
const PresetCollection* presets = tab->get_presets();
|
||||
ret.push_back({ static_cast<unsigned int>(presets->type()), presets->get_selected_preset_name() });
|
||||
}
|
||||
}
|
||||
for (const Tab* tab : tabs_list)
|
||||
if (tab->supports_printer_technology(printer_technology))
|
||||
ret.push_back(tab->get_presets());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ public:
|
||||
bool has_unsaved_preset_changes() const;
|
||||
bool has_current_preset_changes() const;
|
||||
void update_saved_preset_from_current_preset();
|
||||
std::vector<std::pair<unsigned int, std::string>> get_selected_presets() const;
|
||||
std::vector<const PresetCollection*> get_active_preset_collections() const;
|
||||
bool check_and_save_current_preset_changes(const wxString& caption, const wxString& header, bool remember_choice = true, bool use_dont_save_insted_of_discard = false);
|
||||
void apply_keeped_preset_modifications();
|
||||
bool check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes = nullptr);
|
||||
|
@ -657,9 +657,9 @@ void ObjectManipulation::update_if_dirty()
|
||||
else
|
||||
m_og->disable();
|
||||
|
||||
if (!selection.is_dragging()) {
|
||||
if (!wxGetApp().plater()->canvas3D()->is_dragging()) {
|
||||
update_reset_buttons_visibility();
|
||||
update_mirror_buttons_visibility();
|
||||
update_mirror_buttons_visibility();
|
||||
}
|
||||
|
||||
m_dirty = false;
|
||||
@ -814,9 +814,8 @@ void ObjectManipulation::change_position_value(int axis, double value)
|
||||
|
||||
auto canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
selection.start_dragging();
|
||||
selection.setup_cache();
|
||||
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
||||
selection.stop_dragging();
|
||||
canvas->do_move(L("Set Position"));
|
||||
|
||||
m_cache.position = position;
|
||||
@ -844,11 +843,10 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
|
||||
transformation_type.set_local();
|
||||
}
|
||||
|
||||
selection.start_dragging();
|
||||
selection.setup_cache();
|
||||
selection.rotate(
|
||||
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
|
||||
transformation_type);
|
||||
selection.stop_dragging();
|
||||
canvas->do_rotate(L("Set Orientation"));
|
||||
|
||||
m_cache.rotation = rotation;
|
||||
@ -925,9 +923,8 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
||||
if (m_uniform_scale || selection.requires_uniform_scale())
|
||||
scaling_factor = scale(axis) * Vec3d::Ones();
|
||||
|
||||
selection.start_dragging();
|
||||
selection.setup_cache();
|
||||
selection.scale(scaling_factor, transformation_type);
|
||||
selection.stop_dragging();
|
||||
wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,8 @@ bool ObjectSettings::update_settings_list()
|
||||
{
|
||||
Option option = optgroup->get_option(opt);
|
||||
option.opt.width = 12;
|
||||
if (!option.opt.full_label.empty())
|
||||
option.opt.label = option.opt.full_label;
|
||||
if (is_extruders_cat)
|
||||
option.opt.max = wxGetApp().extruders_edited_cnt();
|
||||
optgroup->append_single_option_line(option);
|
||||
|
@ -162,8 +162,7 @@ bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
|
||||
Selection &selection = m_parent.get_selection();
|
||||
if (!selection.is_empty() && m_hover_id != -1 &&
|
||||
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) {
|
||||
// TODO: investigate if it is neccessary -> there was no stop dragging
|
||||
selection.start_dragging();
|
||||
selection.setup_cache();
|
||||
|
||||
m_dragging = true;
|
||||
for (auto &grabber : m_grabbers) grabber.dragging = false;
|
||||
|
@ -378,6 +378,8 @@ void GLGizmoCut::update_contours()
|
||||
|
||||
MeshSlicingParams slicing_params;
|
||||
slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix();
|
||||
slicing_params.trafo.pretranslate(Vec3d(0., 0., first_glvolume->get_sla_shift_z()));
|
||||
|
||||
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, m_cut_z, slicing_params);
|
||||
if (!polys.empty()) {
|
||||
m_cut_contours.contours.init_from(polys, static_cast<float>(m_cut_z));
|
||||
|
@ -170,11 +170,9 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
Eigen::AngleAxisd aa(q);
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z()));
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
m_cylinder.render();
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
|
@ -192,7 +192,7 @@ void GLGizmoPainterBase::render_cursor_circle()
|
||||
GLModel::Geometry init_data;
|
||||
static const unsigned int StepsCount = 32;
|
||||
static const float StepSize = 2.0f * float(PI) / float(StepsCount);
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f };
|
||||
init_data.reserve_vertices(StepsCount);
|
||||
init_data.reserve_indices(StepsCount);
|
||||
@ -200,7 +200,7 @@ void GLGizmoPainterBase::render_cursor_circle()
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i < StepsCount; ++i) {
|
||||
const float angle = float(i * StepSize);
|
||||
init_data.add_vertex(Vec3f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius, 0.0f));
|
||||
init_data.add_vertex(Vec2f(center.x() + ::cos(angle) * m_cursor_radius, center.y() + ::sin(angle) * m_cursor_radius));
|
||||
init_data.add_ushort_index(i);
|
||||
}
|
||||
|
||||
@ -1195,11 +1195,11 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
|
||||
m_varrays[i].init_from(std::move(varrays_data[i]));
|
||||
}
|
||||
#else
|
||||
for (auto* iva : { &m_iva_enforcers, &m_iva_blockers })
|
||||
iva->finalize_geometry(true);
|
||||
|
||||
for (auto& iva : m_iva_seed_fills)
|
||||
iva.finalize_geometry(true);
|
||||
// for (auto* iva : { &m_iva_enforcers, &m_iva_blockers })
|
||||
// iva->finalize_geometry(true);
|
||||
//
|
||||
// for (auto& iva : m_iva_seed_fills)
|
||||
// iva.finalize_geometry(true);
|
||||
#endif // ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
||||
#if ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL
|
||||
|
@ -461,22 +461,26 @@ void GLGizmoRotate::render_angle() const
|
||||
const float ex_radius = m_radius * (1.0f + GrabberOffset);
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
if (!m_angle_arc.is_initialized() || radius_changed) {
|
||||
const bool angle_changed = std::abs(m_old_angle - m_angle) > EPSILON;
|
||||
m_old_angle = m_angle;
|
||||
|
||||
if (!m_angle_arc.is_initialized() || radius_changed || angle_changed) {
|
||||
m_angle_arc.reset();
|
||||
if (m_angle > 0.0f) {
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.reserve_vertices(1 + AngleResolution);
|
||||
init_data.reserve_indices(1 + AngleResolution);
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT };
|
||||
init_data.reserve_vertices(1 + AngleResolution);
|
||||
init_data.reserve_indices(1 + AngleResolution);
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i <= AngleResolution; ++i) {
|
||||
const float angle = float(i) * step_angle;
|
||||
init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f));
|
||||
init_data.add_ushort_index(i);
|
||||
}
|
||||
|
||||
// vertices + indices
|
||||
for (unsigned short i = 0; i <= AngleResolution; ++i) {
|
||||
const float angle = float(i) * step_angle;
|
||||
init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f));
|
||||
init_data.add_ushort_index(i);
|
||||
m_angle_arc.init_from(std::move(init_data));
|
||||
}
|
||||
|
||||
m_angle_arc.init_from(std::move(init_data));
|
||||
}
|
||||
|
||||
m_angle_arc.set_color(color);
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
GrabberConnection m_grabber_connection;
|
||||
float m_old_radius{ 0.0f };
|
||||
float m_old_hover_radius{ 0.0f };
|
||||
float m_old_angle{ 0.0f };
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
ColorRGBA m_drag_color;
|
||||
|
@ -120,10 +120,10 @@ void GLGizmoSlaSupports::on_render_for_picking()
|
||||
|
||||
void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
{
|
||||
size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
|
||||
const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
|
||||
|
||||
bool has_points = (cache_size != 0);
|
||||
bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh()
|
||||
const bool has_points = (cache_size != 0);
|
||||
const bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh()
|
||||
&& ! m_c->selection_info()->model_object()->sla_drain_holes.empty());
|
||||
|
||||
if (! has_points && ! has_holes)
|
||||
@ -147,9 +147,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
#endif // ENABLE_GLBEGIN_GLEND_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();
|
||||
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();
|
||||
float z_shift = m_c->selection_info()->get_sla_shift();
|
||||
const float z_shift = m_c->selection_info()->get_sla_shift();
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslated(0.0, 0.0, z_shift));
|
||||
@ -158,7 +158,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
ColorRGBA render_color;
|
||||
for (size_t i = 0; i < cache_size; ++i) {
|
||||
const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i];
|
||||
const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
|
||||
const bool point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
|
||||
|
||||
if (is_mesh_point_clipped(support_point.pos.cast<double>()))
|
||||
continue;
|
||||
@ -198,7 +198,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(support_point.pos(0), support_point.pos(1), support_point.pos(2)));
|
||||
glsafe(::glTranslatef(support_point.pos.x(), support_point.pos.y(), support_point.pos.z()));
|
||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||
|
||||
if (vol->is_left_handed())
|
||||
@ -213,27 +213,21 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
Eigen::AngleAxisd aa(q);
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
||||
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z()));
|
||||
const double cone_radius = 0.25; // mm
|
||||
const double cone_height = 0.75;
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(0.f, 0.f, cone_height + support_point.head_front_radius * RenderPointScale));
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glRotated(180., 1., 0., 0.));
|
||||
glsafe(::glScaled(cone_radius, cone_radius, cone_height));
|
||||
m_cone.render();
|
||||
glsafe(::glPopMatrix());
|
||||
glsafe(::glTranslatef(0.f, 0.f, cone_height));
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
double radius = (double)support_point.head_front_radius * RenderPointScale;
|
||||
const double radius = (double)support_point.head_front_radius * RenderPointScale;
|
||||
glsafe(::glScaled(radius, radius, radius));
|
||||
m_sphere.render();
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
@ -248,7 +242,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
m_cylinder.set_color(render_color);
|
||||
#else
|
||||
m_cylinder.set_color(-1, render_color);
|
||||
if (shader != nu)
|
||||
if (shader != nullptr)
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
shader->set_uniform("emission_factor", 0.5f);
|
||||
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
|
||||
@ -257,7 +251,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2)));
|
||||
glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z()));
|
||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||
|
||||
if (vol->is_left_handed())
|
||||
@ -267,13 +261,11 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
Eigen::AngleAxisd aa(q);
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
||||
glsafe(::glPushMatrix());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z()));
|
||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
m_cylinder.render();
|
||||
glsafe(::glPopMatrix());
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glFrontFace(GL_CCW);
|
||||
|
@ -907,6 +907,10 @@ void GLGizmosManager::update_hover_state(const EType &type)
|
||||
m_tooltip = hovered_gizmo.get_name();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Activate given gizmo. Returns true if successful, false in case that current
|
||||
// gizmo vetoed its deactivation.
|
||||
bool GLGizmosManager::activate_gizmo(EType type)
|
||||
{
|
||||
assert(!m_gizmos.empty());
|
||||
|
@ -859,7 +859,10 @@ bool MainFrame::save_project_as(const wxString& filename)
|
||||
{
|
||||
bool ret = (m_plater != nullptr) ? m_plater->export_3mf(into_path(filename)) : false;
|
||||
if (ret) {
|
||||
// wxGetApp().update_saved_preset_from_current_preset();
|
||||
// Make a copy of the active presets for detecting changes in preset values.
|
||||
wxGetApp().update_saved_preset_from_current_preset();
|
||||
// Save the names of active presets and project specific config into ProjectDirtyStateManager.
|
||||
// Reset ProjectDirtyStateManager's state as saved, mark active UndoRedo step as saved with project.
|
||||
m_plater->reset_project_dirty_after_save();
|
||||
}
|
||||
return ret;
|
||||
|
@ -311,7 +311,11 @@ wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
|
||||
overwrite = true;
|
||||
if (newline)
|
||||
break;
|
||||
} else if (in[j] == '/') {
|
||||
} else if (in[j] == '/'
|
||||
#ifdef _WIN32
|
||||
|| in[j] == '\\'
|
||||
#endif // _WIN32
|
||||
) {
|
||||
// Insert after the slash.
|
||||
ibreak = ++ j;
|
||||
overwrite = false;
|
||||
|
@ -499,6 +499,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
|
||||
std::vector<float> extruders = dlg.get_extruders();
|
||||
(project_config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values = std::vector<double>(matrix.begin(), matrix.end());
|
||||
(project_config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values = std::vector<double>(extruders.begin(), extruders.end());
|
||||
// Update Project dirty state, update application title bar.
|
||||
wxGetApp().plater()->update_project_dirty_from_presets();
|
||||
wxPostEvent(parent, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, parent));
|
||||
}
|
||||
@ -2351,7 +2352,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
|
||||
const auto loading = _L("Loading") + dots;
|
||||
wxProgressDialog dlg(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE);
|
||||
wxProgressDialog progress_dlg(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE);
|
||||
wxBusyCursor busy;
|
||||
|
||||
auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model();
|
||||
@ -2360,7 +2361,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
int answer_convert_from_meters = wxOK_DEFAULT;
|
||||
int answer_convert_from_imperial_units = wxOK_DEFAULT;
|
||||
|
||||
for (size_t i = 0; i < input_files.size(); ++i) {
|
||||
size_t input_files_size = input_files.size();
|
||||
for (size_t i = 0; i < input_files_size; ++i) {
|
||||
#ifdef _WIN32
|
||||
auto path = input_files[i];
|
||||
// On Windows, we swap slashes to back slashes, see GH #6803 as read_from_file() does not understand slashes on Windows thus it assignes full path to names of loaded objects.
|
||||
@ -2370,8 +2372,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
const auto &path = input_files[i];
|
||||
#endif // _WIN32
|
||||
const auto filename = path.filename();
|
||||
dlg.Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
|
||||
dlg.Fit();
|
||||
progress_dlg.Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
|
||||
progress_dlg.Fit();
|
||||
|
||||
const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
|
||||
const bool type_zip_amf = !type_3mf && std::regex_match(path.string(), pattern_zip_amf);
|
||||
@ -2382,17 +2384,28 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
bool is_project_file = type_prusa;
|
||||
try {
|
||||
if (type_3mf || type_zip_amf) {
|
||||
#ifdef __linux__
|
||||
// On Linux Constructor of the ProgressDialog calls DisableOtherWindows() function which causes a disabling of all children of the find_toplevel_parent(q)
|
||||
// And a destructor of the ProgressDialog calls ReenableOtherWindows() function which revert previously disabled children.
|
||||
// But if printer technology will be changes during project loading,
|
||||
// then related SLA Print and Materials Settings or FFF Print and Filaments Settings will be unparent from the wxNoteBook
|
||||
// and that is why they will never be enabled after destruction of the ProgressDialog.
|
||||
// So, distroy progress_gialog if we are loading project file
|
||||
if (input_files_size == 1)
|
||||
progress_dlg.Destroy();
|
||||
#endif
|
||||
DynamicPrintConfig config;
|
||||
PrinterTechnology loaded_printer_technology {ptFFF};
|
||||
{
|
||||
DynamicPrintConfig config_loaded;
|
||||
ConfigSubstitutionContext config_substitutions{ ForwardCompatibilitySubstitutionRule::Enable };
|
||||
model = Slic3r::Model::read_from_archive(path.string(), &config_loaded, &config_substitutions, only_if(load_config, Model::LoadAttribute::CheckVersion));
|
||||
if (load_config && !config_loaded.empty()) {
|
||||
// Based on the printer technology field found in the loaded config, select the base for the config,
|
||||
PrinterTechnology printer_technology = Preset::printer_technology(config_loaded);
|
||||
loaded_printer_technology = Preset::printer_technology(config_loaded);
|
||||
|
||||
// We can't to load SLA project if there is at least one multi-part object on the bed
|
||||
if (printer_technology == ptSLA) {
|
||||
if (loaded_printer_technology == ptSLA) {
|
||||
const ModelObjectPtrs& objects = q->model().objects;
|
||||
for (auto object : objects)
|
||||
if (object->volumes.size() > 1) {
|
||||
@ -2404,7 +2417,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
}
|
||||
|
||||
config.apply(printer_technology == ptFFF ?
|
||||
config.apply(loaded_printer_technology == ptFFF ?
|
||||
static_cast<const ConfigBase&>(FullPrintConfig::defaults()) :
|
||||
static_cast<const ConfigBase&>(SLAFullPrintConfig::defaults()));
|
||||
// and place the loaded config over the base.
|
||||
@ -2435,7 +2448,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
};
|
||||
|
||||
std::vector<std::string> names;
|
||||
if (printer_technology == ptFFF) {
|
||||
if (loaded_printer_technology == ptFFF) {
|
||||
update_selected_preset_visibility(preset_bundle->prints, names);
|
||||
for (const std::string& filament : preset_bundle->filament_presets) {
|
||||
Preset* preset = preset_bundle->filaments.find_preset(filament);
|
||||
@ -2466,7 +2479,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
}
|
||||
}
|
||||
|
||||
if (printer_technology == ptFFF)
|
||||
if (loaded_printer_technology == ptFFF)
|
||||
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &preset_bundle->project_config);
|
||||
|
||||
// For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload"
|
||||
@ -5257,8 +5270,11 @@ void Plater::new_project()
|
||||
take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator);
|
||||
Plater::SuppressSnapshots suppress(this);
|
||||
reset();
|
||||
// Save the names of active presets and project specific config into ProjectDirtyStateManager.
|
||||
reset_project_dirty_initial_presets();
|
||||
// Make a copy of the active presets for detecting changes in preset values.
|
||||
wxGetApp().update_saved_preset_from_current_preset();
|
||||
// Update Project dirty state, update application title bar.
|
||||
update_project_dirty_from_presets();
|
||||
}
|
||||
|
||||
@ -5287,7 +5303,11 @@ void Plater::load_project(const wxString& filename)
|
||||
if (! load_files({ into_path(filename) }).empty()) {
|
||||
// At least one file was loaded.
|
||||
p->set_project_filename(filename);
|
||||
// Save the names of active presets and project specific config into ProjectDirtyStateManager.
|
||||
reset_project_dirty_initial_presets();
|
||||
// Make a copy of the active presets for detecting changes in preset values.
|
||||
wxGetApp().update_saved_preset_from_current_preset();
|
||||
// Update Project dirty state, update application title bar.
|
||||
update_project_dirty_from_presets();
|
||||
}
|
||||
}
|
||||
@ -5972,7 +5992,6 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
|
||||
}
|
||||
else if (0 <= instance_id && instance_id < int(mo.instances.size()))
|
||||
mesh.transform(mo.instances[instance_id]->get_matrix(), true);
|
||||
|
||||
return mesh;
|
||||
};
|
||||
|
||||
|
@ -17,9 +17,11 @@ namespace GUI {
|
||||
|
||||
void ProjectDirtyStateManager::update_from_undo_redo_stack(bool dirty)
|
||||
{
|
||||
m_plater_dirty = dirty;
|
||||
if (const Plater *plater = wxGetApp().plater(); plater && wxGetApp().initialized())
|
||||
wxGetApp().mainframe->update_title();
|
||||
if (m_plater_dirty != dirty) {
|
||||
m_plater_dirty = dirty;
|
||||
if (const Plater *plater = wxGetApp().plater(); plater && wxGetApp().initialized())
|
||||
wxGetApp().mainframe->update_title();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectDirtyStateManager::update_from_presets()
|
||||
@ -27,11 +29,11 @@ void ProjectDirtyStateManager::update_from_presets()
|
||||
m_presets_dirty = false;
|
||||
// check switching of the presets only for exist/loaded project, but not for new
|
||||
GUI_App &app = wxGetApp();
|
||||
if (!app.plater()->get_project_filename().IsEmpty()) {
|
||||
for (const auto& [type, name] : app.get_selected_presets())
|
||||
m_presets_dirty |= !m_initial_presets[type].empty() && m_initial_presets[type] != name;
|
||||
bool has_project = ! app.plater()->get_project_filename().IsEmpty();
|
||||
for (const PresetCollection *preset_collection : app.get_active_preset_collections()) {
|
||||
auto type = preset_collection->type();
|
||||
m_presets_dirty |= (has_project && !m_initial_presets[type].empty() && m_initial_presets[type] != preset_collection->get_selected_preset_name()) || preset_collection->saved_is_dirty();
|
||||
}
|
||||
m_presets_dirty |= app.has_unsaved_preset_changes();
|
||||
m_project_config_dirty = m_initial_project_config != app.preset_bundle->project_config;
|
||||
app.mainframe->update_title();
|
||||
}
|
||||
@ -49,8 +51,8 @@ void ProjectDirtyStateManager::reset_initial_presets()
|
||||
{
|
||||
m_initial_presets.fill(std::string{});
|
||||
GUI_App &app = wxGetApp();
|
||||
for (const auto& [type, name] : app.get_selected_presets())
|
||||
m_initial_presets[type] = name;
|
||||
for (const PresetCollection *preset_collection : app.get_active_preset_collections())
|
||||
m_initial_presets[preset_collection->type()] = preset_collection->get_selected_preset_name();
|
||||
m_initial_project_config = app.preset_bundle->project_config;
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,6 @@ Selection::Selection()
|
||||
, m_type(Empty)
|
||||
, m_valid(false)
|
||||
, m_scale_factor(1.0f)
|
||||
, m_dragging(false)
|
||||
{
|
||||
this->set_bounding_boxes_dirty();
|
||||
}
|
||||
@ -679,12 +678,11 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
|
||||
return *m_scaled_instance_bounding_box;
|
||||
}
|
||||
|
||||
void Selection::start_dragging()
|
||||
void Selection::setup_cache()
|
||||
{
|
||||
if (!m_valid)
|
||||
return;
|
||||
|
||||
m_dragging = true;
|
||||
set_caches();
|
||||
}
|
||||
|
||||
@ -955,12 +953,12 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
|
||||
type.set_joint();
|
||||
|
||||
// apply scale
|
||||
start_dragging();
|
||||
setup_cache();
|
||||
scale(s * Vec3d::Ones(), type);
|
||||
wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot
|
||||
|
||||
// center selection on print bed
|
||||
start_dragging();
|
||||
setup_cache();
|
||||
offset.z() = -get_bounding_box().min.z();
|
||||
translate(offset);
|
||||
wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
|
||||
|
@ -229,7 +229,6 @@ private:
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
float m_scale_factor;
|
||||
bool m_dragging;
|
||||
|
||||
public:
|
||||
Selection();
|
||||
@ -322,9 +321,7 @@ public:
|
||||
const BoundingBoxf3& get_unscaled_instance_bounding_box() const;
|
||||
const BoundingBoxf3& get_scaled_instance_bounding_box() const;
|
||||
|
||||
void start_dragging();
|
||||
void stop_dragging() { m_dragging = false; }
|
||||
bool is_dragging() const { return m_dragging; }
|
||||
void setup_cache();
|
||||
|
||||
void translate(const Vec3d& displacement, bool local = false);
|
||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||
|
@ -1247,6 +1247,7 @@ void Tab::on_presets_changed()
|
||||
// to avoid needless preset loading from update() function
|
||||
m_dependent_tabs.clear();
|
||||
|
||||
// Update Project dirty state, update application title bar.
|
||||
wxGetApp().plater()->update_project_dirty_from_presets();
|
||||
}
|
||||
|
||||
@ -4113,7 +4114,7 @@ wxSizer* TabPrint::create_manage_substitution_widget(wxWindow* parent)
|
||||
|
||||
create_btn(&m_del_all_substitutions_btn, _L("Delete all"), "cross");
|
||||
m_del_all_substitutions_btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) {
|
||||
if (MessageDialog(parent, _L("Are you sure you want to delete all substitutions?"), SLIC3R_APP_NAME, wxYES_NO | wxICON_QUESTION).
|
||||
if (MessageDialog(parent, _L("Are you sure you want to delete all substitutions?"), SLIC3R_APP_NAME, wxYES_NO | wxCANCEL | wxICON_QUESTION).
|
||||
ShowModal() != wxID_YES)
|
||||
return;
|
||||
m_subst_manager.delete_all();
|
||||
|
@ -371,6 +371,7 @@ public:
|
||||
|
||||
DynamicPrintConfig* get_config() { return m_config; }
|
||||
PresetCollection* get_presets() { return m_presets; }
|
||||
const PresetCollection* get_presets() const { return m_presets; }
|
||||
|
||||
void on_value_change(const std::string& opt_key, const boost::any& value);
|
||||
|
||||
|
@ -1,3 +1,18 @@
|
||||
#include <catch_main.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
// __has_feature() is used later for Clang, this is for compatibility with other compilers (such as GCC and MSVC)
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
// Print reports about memory leaks but exit with zero exit code when any memory leaks is found to make unit tests pass.
|
||||
// After merging the stable branch (2.4.1) with the master branch, this should be deleted.
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
extern "C" {
|
||||
const char *__lsan_default_options() {
|
||||
return "exitcode=0";
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user