mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 16:55:56 +08:00
Merge tag 'version_2.3.0'
version_2.3.0
This commit is contained in:
commit
a50b4cd544
46
cmake/modules/FindGTK3.cmake
Normal file
46
cmake/modules/FindGTK3.cmake
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# - Try to find GTK+ 3
|
||||||
|
# Once done, this will define
|
||||||
|
#
|
||||||
|
# GTK3_FOUND - system has GTK+ 3.
|
||||||
|
# GTK3_INCLUDE_DIRS - the GTK+ 3. include directories
|
||||||
|
# GTK3_LIBRARIES - link these to use GTK+ 3.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
|
||||||
|
# Copyright (C) 2013 Igalia S.L.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
|
||||||
|
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||||
|
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(GTK3 QUIET gtk+-3.0)
|
||||||
|
set(VERSION_OK TRUE)
|
||||||
|
if (GTK3_VERSION)
|
||||||
|
if (GTK3_FIND_VERSION_EXACT)
|
||||||
|
if (NOT("${GTK3_FIND_VERSION}" VERSION_EQUAL "${GTK3_VERSION}"))
|
||||||
|
set(VERSION_OK FALSE)
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
if ("${GTK3_VERSION}" VERSION_LESS "${GTK3_FIND_VERSION}")
|
||||||
|
set(VERSION_OK FALSE)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK3 DEFAULT_MSG GTK3_INCLUDE_DIRS GTK3_LIBRARIES VERSION_OK)
|
@ -5169,7 +5169,7 @@ msgid "The supplied name is empty. It can't be saved."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
||||||
|
Binary file not shown.
@ -10482,8 +10482,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "Chcete-li provést změny, musíte restartovat aplikaci %s."
|
msgstr "Chcete-li provést změny, musíte restartovat aplikaci %s."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Měli byste změnit název tiskového zařízení. Nemůže být uloženo."
|
msgstr "Měli byste změnit název tiskového zařízení."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
@ -10480,8 +10480,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "Sie müssen %s neu starten, damit die Änderungen wirksam werden."
|
msgstr "Sie müssen %s neu starten, damit die Änderungen wirksam werden."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Sie sollten den Namen Ihres Druckers ändern. Er kann nicht gespeichert werden."
|
msgstr "Sie sollten den Namen Ihres Druckers ändern."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
@ -10480,8 +10480,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "Es necesario reiniciar %s para hacer los cambios efectivos."
|
msgstr "Es necesario reiniciar %s para hacer los cambios efectivos."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Debería cambiar el nombre de su dispositivo de impresión. No se puede guardar."
|
msgstr "Debería cambiar el nombre de su dispositivo de impresión."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
@ -10480,8 +10480,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "Vous devez redémarrer %s afin que les modifications soient appliquées."
|
msgstr "Vous devez redémarrer %s afin que les modifications soient appliquées."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Vous devez changer le nom de votre imprimante. Il ne peut pas être enregistré."
|
msgstr "Vous devez changer le nom de votre imprimante."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
@ -10480,8 +10480,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "È necessario riavviare %s per rendere effettive le modifiche."
|
msgstr "È necessario riavviare %s per rendere effettive le modifiche."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Devi cambiare il nome del dispositivo di stampa. Non può essere salvato."
|
msgstr "Devi cambiare il nome del dispositivo di stampa."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
@ -5423,9 +5423,8 @@ msgid "The supplied name is empty. It can't be saved."
|
|||||||
msgstr "De ingevoerde naam is leeg. Kan niet opgeslagen worden."
|
msgstr "De ingevoerde naam is leeg. Kan niet opgeslagen worden."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr ""
|
msgstr "Je moet de naam van de printer aanpassen."
|
||||||
"Je moet de naam van de printer aanpassen. Het kan niet opgeslagen worden."
|
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
||||||
msgid "Printer with name \"%1%\" already exists."
|
msgid "Printer with name \"%1%\" already exists."
|
||||||
|
Binary file not shown.
@ -10484,8 +10484,8 @@ msgid "You need to restart %s to make the changes effective."
|
|||||||
msgstr "Wymagany jest restart %s, aby wprowadzić zmiany."
|
msgstr "Wymagany jest restart %s, aby wprowadzić zmiany."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:468
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr "Należy zmienić nazwę drukarki. Nie można jej zapisać."
|
msgstr "Należy zmienić nazwę drukarki."
|
||||||
|
|
||||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
#: src/slic3r/GUI/GUI_ObjectList.cpp:3884
|
||||||
#, possible-c-format
|
#, possible-c-format
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -5122,7 +5122,7 @@ msgid "The supplied name is empty. It can't be saved."
|
|||||||
msgstr "Имя не задано. Невозможно сохранить."
|
msgstr "Имя не задано. Невозможно сохранить."
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:547
|
||||||
msgid "You should to change a name of your printer device. It can't be saved."
|
msgid "You should change the name of your printer device."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:555
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
min_slic3r_version = 2.3.0-rc2
|
||||||
|
0.0.12 Added Ender-3V2 and filament profiles.
|
||||||
min_slic3r_version = 2.3.0-beta2
|
min_slic3r_version = 2.3.0-beta2
|
||||||
0.0.11 Updated machine limits for Ender 5 and Ender 5 Plus.
|
0.0.11 Updated machine limits for Ender 5 and Ender 5 Plus.
|
||||||
0.0.10 Parameter consistency improvements. Enabled conservative elephant foot compensation.
|
0.0.10 Parameter consistency improvements. Enabled conservative elephant foot compensation.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
name = Creality
|
name = Creality
|
||||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
# 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.
|
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||||
config_version = 0.0.11
|
config_version = 0.0.12
|
||||||
# Where to get the updates from?
|
# Where to get the updates from?
|
||||||
config_update_url =
|
config_update_url =
|
||||||
# https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
|
# https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
|
||||||
@ -28,6 +28,15 @@ bed_model = ender3_bed.stl
|
|||||||
bed_texture = ender3.svg
|
bed_texture = ender3.svg
|
||||||
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
|
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
|
||||||
|
|
||||||
|
[printer_model:ENDER3V2]
|
||||||
|
name = Creality Ender-3V2
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = ENDER
|
||||||
|
bed_model = ender3_bed.stl
|
||||||
|
bed_texture = ender3.svg
|
||||||
|
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
|
||||||
|
|
||||||
[printer_model:ENDER3BLTOUCH]
|
[printer_model:ENDER3BLTOUCH]
|
||||||
name = Creality Ender-3 BLTouch
|
name = Creality Ender-3 BLTouch
|
||||||
variants = 0.4; 0.3; 0.5; 0.6
|
variants = 0.4; 0.3; 0.5; 0.6
|
||||||
@ -584,6 +593,26 @@ filament_cost = 19.50
|
|||||||
filament_density = 1.24
|
filament_density = 1.24
|
||||||
filament_colour = #FFE200
|
filament_colour = #FFE200
|
||||||
|
|
||||||
|
[filament:Das Filament PLA @CREALITY]
|
||||||
|
inherits = *PLA*
|
||||||
|
filament_vendor = Das Filament
|
||||||
|
temperature = 215
|
||||||
|
bed_temperature = 50
|
||||||
|
first_layer_temperature = 215
|
||||||
|
first_layer_bed_temperature = 50
|
||||||
|
filament_cost = 20.56
|
||||||
|
filament_density = 1.24
|
||||||
|
|
||||||
|
[filament:Das Filament PETG @CREALITY]
|
||||||
|
inherits = *PET*
|
||||||
|
filament_vendor = Das Filament
|
||||||
|
temperature = 240
|
||||||
|
bed_temperature = 70
|
||||||
|
first_layer_temperature = 240
|
||||||
|
first_layer_bed_temperature = 70
|
||||||
|
filament_cost = 27.44
|
||||||
|
filament_density = 1.29
|
||||||
|
|
||||||
# Common printer preset
|
# Common printer preset
|
||||||
[printer:*common*]
|
[printer:*common*]
|
||||||
printer_technology = FFF
|
printer_technology = FFF
|
||||||
@ -749,6 +778,12 @@ inherits = *Creality Ender-3*; *0.5nozzle*
|
|||||||
[printer:Creality Ender-3 0.6mm]
|
[printer:Creality Ender-3 0.6mm]
|
||||||
inherits = *Creality Ender-3*; *0.6nozzle*
|
inherits = *Creality Ender-3*; *0.6nozzle*
|
||||||
|
|
||||||
|
[printer:Creality Ender-3V2]
|
||||||
|
inherits = Creality Ender-3
|
||||||
|
printer_model = ENDER3V2
|
||||||
|
printer_variant = 0.4
|
||||||
|
bed_shape = 0x0,220x0,220x220,0x220
|
||||||
|
|
||||||
[printer:*fastabl*]
|
[printer:*fastabl*]
|
||||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S{first_layer_temperature[initial_extruder]+extruder_temperature_offset[initial_extruder]} ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S{first_layer_temperature[initial_extruder]+extruder_temperature_offset[initial_extruder]} ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0\nG1 Y190 E15 F1500 ; intro line\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E15 F1200 ; intro line\nG92 E0
|
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S{first_layer_temperature[initial_extruder]+extruder_temperature_offset[initial_extruder]} ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S{first_layer_temperature[initial_extruder]+extruder_temperature_offset[initial_extruder]} ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0\nG1 Y190 E15 F1500 ; intro line\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E15 F1200 ; intro line\nG92 E0
|
||||||
|
|
||||||
|
BIN
resources/profiles/Creality/ENDER3V2_thumbnail.png
Normal file
BIN
resources/profiles/Creality/ENDER3V2_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@ -1,4 +1,5 @@
|
|||||||
min_slic3r_version = 2.3.0-rc1
|
min_slic3r_version = 2.3.0-rc1
|
||||||
|
1.2.2 Added Prusament PVB filament profile. Added 0.8mm nozzle profiles.
|
||||||
1.2.1 Updated FW version for MK2.5 family printers.
|
1.2.1 Updated FW version for MK2.5 family printers.
|
||||||
1.2.0 Added full_fan_speed_layer value for PETG. Increased support interface spacing for 0.6mm nozzle profiles. Updated firmware version.
|
1.2.0 Added full_fan_speed_layer value for PETG. Increased support interface spacing for 0.6mm nozzle profiles. Updated firmware version.
|
||||||
min_slic3r_version = 2.3.0-beta2
|
min_slic3r_version = 2.3.0-beta2
|
||||||
@ -11,6 +12,7 @@ min_slic3r_version = 2.3.0-alpha4
|
|||||||
1.2.0-alpha1 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
1.2.0-alpha1 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
||||||
1.2.0-alpha0 Added filament spool weights
|
1.2.0-alpha0 Added filament spool weights
|
||||||
min_slic3r_version = 2.2.0-alpha3
|
min_slic3r_version = 2.2.0-alpha3
|
||||||
|
1.1.12 Added Prusament PVB filament profile. Added 0.8mm nozzle profiles.
|
||||||
1.1.11 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
1.1.11 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
||||||
1.1.11 SuperSlicer version
|
1.1.11 SuperSlicer version
|
||||||
1.1.10 Updated firmware version.
|
1.1.10 Updated firmware version.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
min_slic3r_version = 2.3.0-alpha3
|
min_slic3r_version = 2.3.0-alpha3
|
||||||
|
0.0.6 Added material TPU 93A (SMARTFIL)
|
||||||
0.0.5-susi remove resolution to use default
|
0.0.5-susi remove resolution to use default
|
||||||
0.0.5 Removed obsolete host keys.0.0.4-1 remove g92
|
0.0.5 Removed obsolete host keys.
|
||||||
0.0.4 Added PLA, PETG profiles for 0.8 nozzle, update print materials
|
0.0.4 Added PLA, PETG profiles for 0.8 nozzle, update print materials
|
||||||
0.0.3 Added DeltiQ 2, DeltiQ 2 Plus printers, 0.10mm, 0.20mm FLEX print profiles, updated print materials, flexprint extension support
|
0.0.3 Added DeltiQ 2, DeltiQ 2 Plus printers, 0.10mm, 0.20mm FLEX print profiles, updated print materials, flexprint extension support
|
||||||
min_slic3r_version = 2.3.0-alpha0
|
min_slic3r_version = 2.3.0-alpha0
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
name = TriLAB
|
name = TriLAB
|
||||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
# 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.
|
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||||
config_version = 0.0.5-susi
|
config_version = 0.0.6
|
||||||
# Where to get the updates from?
|
# Where to get the updates from?
|
||||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
|
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
|
||||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||||
@ -22,7 +22,7 @@ technology = FFF
|
|||||||
family = DeltiQ 2
|
family = DeltiQ 2
|
||||||
bed_model = dq2_bed.stl
|
bed_model = dq2_bed.stl
|
||||||
bed_texture = dq2_bed_texture.svg
|
bed_texture = dq2_bed_texture.svg
|
||||||
default_materials = DeltiQ - PLA - Generic; DeltiQ - PETG - Generic; DeltiQ - ABS - Generic; DeltiQ - PLA - ExtraFill (Fillamentum); DeltiQ - PETG (Devil Design); DeltiQ - ABS - ExtraFill (Fillamentum); DeltiQ - ASA - ExtraFill (Fillamentum); DeltiQ - CPE - HG100 (Fillamentum); DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle
|
default_materials = DeltiQ - PLA - Generic; DeltiQ - PETG - Generic; DeltiQ - ABS - Generic; DeltiQ - PLA - ExtraFill (Fillamentum); DeltiQ - PETG (Devil Design); DeltiQ - ABS - ExtraFill (Fillamentum); DeltiQ - ASA - ExtraFill (Fillamentum); DeltiQ - CPE - HG100 (Fillamentum); DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 93A (SMARTFIL); DeltiQ - PLA - ExtraFill (Fillamentum) @0.8 nozzle
|
||||||
|
|
||||||
[printer_model:DQ2P]
|
[printer_model:DQ2P]
|
||||||
name = DeltiQ 2 Plus
|
name = DeltiQ 2 Plus
|
||||||
@ -40,7 +40,7 @@ technology = FFF
|
|||||||
family = DeltiQ 2
|
family = DeltiQ 2
|
||||||
bed_model = dq2_bed.stl
|
bed_model = dq2_bed.stl
|
||||||
bed_texture = dq2_bed_texture.svg
|
bed_texture = dq2_bed_texture.svg
|
||||||
default_materials = DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)
|
default_materials = DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 93A (SMARTFIL)
|
||||||
|
|
||||||
[printer_model:DQ2P+FP2]
|
[printer_model:DQ2P+FP2]
|
||||||
name = DeltiQ 2 Plus + FlexPrint 2
|
name = DeltiQ 2 Plus + FlexPrint 2
|
||||||
@ -49,7 +49,7 @@ technology = FFF
|
|||||||
family = DeltiQ 2
|
family = DeltiQ 2
|
||||||
bed_model = dq2_bed.stl
|
bed_model = dq2_bed.stl
|
||||||
bed_texture = dq2_bed_texture.svg
|
bed_texture = dq2_bed_texture.svg
|
||||||
default_materials = DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)
|
default_materials = DeltiQ FP2 - PLA - Generic; DeltiQ FP2 - PETG - Generic; DeltiQ FP2 - ABS - Generic; DeltiQ FP2 - PLA - ExtraFill (Fillamentum); DeltiQ FP2 - PETG (Devil Design); DeltiQ FP2 - ABS - ExtraFill (Fillamentum); DeltiQ FP2 - ASA - ExtraFill (Fillamentum); DeltiQ FP2 - CPE - HG100 (Fillamentum); DeltiQ FP2 - FLEX - Generic; DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum); DeltiQ FP2 - TPU 93A (SMARTFIL)
|
||||||
|
|
||||||
[printer_model:DQ2+FP]
|
[printer_model:DQ2+FP]
|
||||||
name = DeltiQ 2 + FlexPrint
|
name = DeltiQ 2 + FlexPrint
|
||||||
@ -375,7 +375,7 @@ temperature = 215
|
|||||||
|
|
||||||
[filament:DeltiQ - PETG - Generic]
|
[filament:DeltiQ - PETG - Generic]
|
||||||
inherits = *DeltiQ common*
|
inherits = *DeltiQ common*
|
||||||
bed_temperature = 90
|
bed_temperature = 80
|
||||||
bridge_fan_speed = 50
|
bridge_fan_speed = 50
|
||||||
cooling = 1
|
cooling = 1
|
||||||
fan_always_on = 1
|
fan_always_on = 1
|
||||||
@ -393,7 +393,7 @@ filament_retract_lift = 0.2
|
|||||||
filament_retract_speed = 45
|
filament_retract_speed = 45
|
||||||
filament_type = PET
|
filament_type = PET
|
||||||
filament_wipe = 1
|
filament_wipe = 1
|
||||||
first_layer_bed_temperature = 90
|
first_layer_bed_temperature = 80
|
||||||
first_layer_temperature = 240
|
first_layer_temperature = 240
|
||||||
max_fan_speed = 50
|
max_fan_speed = 50
|
||||||
min_fan_speed = 30
|
min_fan_speed = 30
|
||||||
@ -694,6 +694,37 @@ filament_retract_length = 2.5
|
|||||||
filament_retract_speed = 20
|
filament_retract_speed = 20
|
||||||
filament_type = TPU98A
|
filament_type = TPU98A
|
||||||
|
|
||||||
|
[filament:DeltiQ FP2 - TPU 93A (SMARTFIL)]
|
||||||
|
inherits = DeltiQ FP2 - FLEX - Generic
|
||||||
|
bed_temperature = 50
|
||||||
|
bridge_fan_speed = 80
|
||||||
|
cooling = 1
|
||||||
|
disable_fan_first_layers = 3
|
||||||
|
extrusion_multiplier = 1.00
|
||||||
|
fan_always_on = 1
|
||||||
|
fan_below_layer_time = 10
|
||||||
|
filament_vendor = Smartfil
|
||||||
|
filament_cost = 1209
|
||||||
|
filament_density = 1.21
|
||||||
|
filament_deretract_speed = nil
|
||||||
|
filament_max_volumetric_speed = 2.5
|
||||||
|
filament_retract_before_travel = 2
|
||||||
|
filament_retract_before_wipe = nil
|
||||||
|
filament_retract_layer_change = 0
|
||||||
|
filament_retract_length = 2.9
|
||||||
|
filament_retract_lift = 0.2
|
||||||
|
filament_retract_restart_extra = nil
|
||||||
|
filament_retract_speed = 35
|
||||||
|
filament_type = TPU93A
|
||||||
|
filament_wipe = 0
|
||||||
|
first_layer_bed_temperature = 50
|
||||||
|
first_layer_temperature = 235
|
||||||
|
max_fan_speed = 70
|
||||||
|
min_fan_speed = 30
|
||||||
|
min_print_speed = 10
|
||||||
|
slowdown_below_layer_time = 4
|
||||||
|
temperature = 235
|
||||||
|
|
||||||
|
|
||||||
# DeltiQ Printer #
|
# DeltiQ Printer #
|
||||||
|
|
||||||
|
@ -145,15 +145,11 @@ int CLI::run(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read input file(s) if any.
|
// Read input file(s) if any.
|
||||||
for (const std::string& file : m_input_files) {
|
for (const std::string& file : m_input_files)
|
||||||
std::string ext = boost::filesystem::path(file).extension().string();
|
if (is_gcode_file(file) && boost::filesystem::exists(file)) {
|
||||||
if (ext == ".gcode" || ext == ".g") {
|
start_as_gcodeviewer = true;
|
||||||
if (boost::filesystem::exists(file)) {
|
break;
|
||||||
start_as_gcodeviewer = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!start_as_gcodeviewer) {
|
if (!start_as_gcodeviewer) {
|
||||||
for (const std::string& file : m_input_files) {
|
for (const std::string& file : m_input_files) {
|
||||||
if (!boost::filesystem::exists(file)) {
|
if (!boost::filesystem::exists(file)) {
|
||||||
|
@ -716,45 +716,33 @@ static void traverse_pt_noholes(const ClipperLib::PolyNodes &nodes, Polygons *ou
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void traverse_pt_old(ClipperLib::PolyNodes &nodes, Polygons* retval)
|
static void traverse_pt_outside_in(const ClipperLib::PolyNodes &nodes, Polygons *retval)
|
||||||
{
|
{
|
||||||
/* use a nearest neighbor search to order these children
|
|
||||||
TODO: supply start_near to chained_path() too? */
|
|
||||||
|
|
||||||
// collect ordering points
|
// collect ordering points
|
||||||
Points ordering_points;
|
Points ordering_points;
|
||||||
ordering_points.reserve(nodes.size());
|
ordering_points.reserve(nodes.size());
|
||||||
for (ClipperLib::PolyNodes::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
for (const ClipperLib::PolyNode *node : nodes)
|
||||||
Point p((*it)->Contour.front().X, (*it)->Contour.front().Y);
|
ordering_points.emplace_back(node->Contour.front().X, node->Contour.front().Y);
|
||||||
ordering_points.push_back(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform the ordering
|
// Perform the ordering, push results recursively.
|
||||||
ClipperLib::PolyNodes ordered_nodes = chain_clipper_polynodes(ordering_points, nodes);
|
//FIXME pass the last point to chain_clipper_polynodes?
|
||||||
|
for (const ClipperLib::PolyNode *node : chain_clipper_polynodes(ordering_points, nodes)) {
|
||||||
// push results recursively
|
retval->emplace_back(ClipperPath_to_Slic3rPolygon(node->Contour));
|
||||||
for (ClipperLib::PolyNodes::iterator it = ordered_nodes.begin(); it != ordered_nodes.end(); ++it) {
|
if (node->IsHole())
|
||||||
|
// Orient a hole, which is clockwise oriented, to CCW.
|
||||||
|
retval->back().reverse();
|
||||||
// traverse the next depth
|
// traverse the next depth
|
||||||
traverse_pt_old((*it)->Childs, retval);
|
traverse_pt_outside_in(node->Childs, retval);
|
||||||
retval->push_back(ClipperPath_to_Slic3rPolygon((*it)->Contour));
|
|
||||||
if ((*it)->IsHole()) retval->back().reverse(); // ccw
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons union_pt_chained(const Polygons &subject, bool safety_offset_)
|
Polygons union_pt_chained_outside_in(const Polygons &subject, bool safety_offset_)
|
||||||
{
|
{
|
||||||
ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_);
|
ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_);
|
||||||
|
|
||||||
Polygons retval;
|
Polygons retval;
|
||||||
traverse_pt_old(polytree.Childs, &retval);
|
traverse_pt_outside_in(polytree.Childs, &retval);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
// TODO: This needs to be tested:
|
|
||||||
// ClipperLib::PolyTree polytree = union_pt(subject, safety_offset_);
|
|
||||||
|
|
||||||
// Polygons retval;
|
|
||||||
// traverse_pt_noholes(polytree.Childs, &retval);
|
|
||||||
// return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear)
|
Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear)
|
||||||
|
@ -228,7 +228,7 @@ ClipperLib::PolyTree union_pt(const Slic3r::ExPolygons &subject, bool safety_off
|
|||||||
ClipperLib::PolyTree union_pt(Slic3r::Polygons &&subject, bool safety_offset_ = false);
|
ClipperLib::PolyTree union_pt(Slic3r::Polygons &&subject, bool safety_offset_ = false);
|
||||||
ClipperLib::PolyTree union_pt(Slic3r::ExPolygons &&subject, bool safety_offset_ = false);
|
ClipperLib::PolyTree union_pt(Slic3r::ExPolygons &&subject, bool safety_offset_ = false);
|
||||||
|
|
||||||
Slic3r::Polygons union_pt_chained(const Slic3r::Polygons &subject, bool safety_offset_ = false);
|
Slic3r::Polygons union_pt_chained_outside_in(const Slic3r::Polygons &subject, bool safety_offset_ = false);
|
||||||
|
|
||||||
ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes);
|
ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes);
|
||||||
|
|
||||||
|
@ -680,7 +680,7 @@ void ConfigBase::setenv_() const
|
|||||||
|
|
||||||
void ConfigBase::load(const std::string &file)
|
void ConfigBase::load(const std::string &file)
|
||||||
{
|
{
|
||||||
if (boost::iends_with(file, ".gcode") || boost::iends_with(file, ".g"))
|
if (is_gcode_file(file))
|
||||||
this->load_from_gcode_file(file);
|
this->load_from_gcode_file(file);
|
||||||
else
|
else
|
||||||
this->load_from_ini(file);
|
this->load_from_ini(file);
|
||||||
|
@ -136,7 +136,7 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
|||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
printf("Filling bridge with angle %f\n", surface->bridge_angle);
|
printf("Filling bridge with angle %f\n", surface->bridge_angle);
|
||||||
#endif /* SLIC3R_DEBUG */
|
#endif /* SLIC3R_DEBUG */
|
||||||
out_angle = (float)(surface->bridge_angle);
|
out_angle = float(surface->bridge_angle);
|
||||||
} else if (this->layer_id != size_t(-1)) {
|
} else if (this->layer_id != size_t(-1)) {
|
||||||
// alternate fill direction
|
// alternate fill direction
|
||||||
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
|
out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers);
|
||||||
@ -1165,15 +1165,15 @@ struct ContourIntersectionPoint {
|
|||||||
size_t contour_idx;
|
size_t contour_idx;
|
||||||
size_t point_idx;
|
size_t point_idx;
|
||||||
// Eucleidean parameter of point_idx along its contour.
|
// Eucleidean parameter of point_idx along its contour.
|
||||||
float param;
|
double param;
|
||||||
// Other intersection points along the same contour. If there is only a single T-joint on a contour
|
// Other intersection points along the same contour. If there is only a single T-joint on a contour
|
||||||
// with an intersection line, then the prev_on_contour and next_on_contour remain nulls.
|
// with an intersection line, then the prev_on_contour and next_on_contour remain nulls.
|
||||||
ContourIntersectionPoint* prev_on_contour{ nullptr };
|
ContourIntersectionPoint* prev_on_contour{ nullptr };
|
||||||
ContourIntersectionPoint* next_on_contour{ nullptr };
|
ContourIntersectionPoint* next_on_contour{ nullptr };
|
||||||
// Length of the contour not yet allocated to some extrusion path going back (clockwise), or masked out by some overlapping infill line.
|
// Length of the contour not yet allocated to some extrusion path going back (clockwise), or masked out by some overlapping infill line.
|
||||||
float contour_not_taken_length_prev{ std::numeric_limits<float>::max() };
|
double contour_not_taken_length_prev { std::numeric_limits<double>::max() };
|
||||||
// Length of the contour not yet allocated to some extrusion path going forward (counter-clockwise), or masked out by some overlapping infill line.
|
// Length of the contour not yet allocated to some extrusion path going forward (counter-clockwise), or masked out by some overlapping infill line.
|
||||||
float contour_not_taken_length_next{ std::numeric_limits<float>::max() };
|
double contour_not_taken_length_next { std::numeric_limits<double>::max() };
|
||||||
// End point is consumed if an infill line connected to this T-joint was already connected left or right along the contour,
|
// End point is consumed if an infill line connected to this T-joint was already connected left or right along the contour,
|
||||||
// or if the infill line was processed, but it was not possible to connect it left or right along the contour.
|
// or if the infill line was processed, but it was not possible to connect it left or right along the contour.
|
||||||
bool consumed{ false };
|
bool consumed{ false };
|
||||||
@ -1184,13 +1184,13 @@ struct ContourIntersectionPoint {
|
|||||||
void consume_prev() { this->contour_not_taken_length_prev = 0.; this->prev_trimmed = true; this->consumed = true; }
|
void consume_prev() { this->contour_not_taken_length_prev = 0.; this->prev_trimmed = true; this->consumed = true; }
|
||||||
void consume_next() { this->contour_not_taken_length_next = 0.; this->next_trimmed = true; this->consumed = true; }
|
void consume_next() { this->contour_not_taken_length_next = 0.; this->next_trimmed = true; this->consumed = true; }
|
||||||
|
|
||||||
void trim_prev(const float new_len) {
|
void trim_prev(const double new_len) {
|
||||||
if (new_len < this->contour_not_taken_length_prev) {
|
if (new_len < this->contour_not_taken_length_prev) {
|
||||||
this->contour_not_taken_length_prev = new_len;
|
this->contour_not_taken_length_prev = new_len;
|
||||||
this->prev_trimmed = true;
|
this->prev_trimmed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void trim_next(const float new_len) {
|
void trim_next(const double new_len) {
|
||||||
if (new_len < this->contour_not_taken_length_next) {
|
if (new_len < this->contour_not_taken_length_next) {
|
||||||
this->contour_not_taken_length_next = new_len;
|
this->contour_not_taken_length_next = new_len;
|
||||||
this->next_trimmed = true;
|
this->next_trimmed = true;
|
||||||
@ -1211,24 +1211,24 @@ struct ContourIntersectionPoint {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Distance from param1 to param2 when going counter-clockwise.
|
// Distance from param1 to param2 when going counter-clockwise.
|
||||||
static inline float closed_contour_distance_ccw(float param1, float param2, float contour_length)
|
static inline double closed_contour_distance_ccw(double param1, double param2, double contour_length)
|
||||||
{
|
{
|
||||||
assert(param1 >= 0.f && param1 <= contour_length);
|
assert(param1 >= 0. && param1 <= contour_length);
|
||||||
assert(param2 >= 0.f && param2 <= contour_length);
|
assert(param2 >= 0. && param2 <= contour_length);
|
||||||
float d = param2 - param1;
|
double d = param2 - param1;
|
||||||
if (d < 0.f)
|
if (d < 0.)
|
||||||
d += contour_length;
|
d += contour_length;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distance from param1 to param2 when going clockwise.
|
// Distance from param1 to param2 when going clockwise.
|
||||||
static inline float closed_contour_distance_cw(float param1, float param2, float contour_length)
|
static inline double closed_contour_distance_cw(double param1, double param2, double contour_length)
|
||||||
{
|
{
|
||||||
return closed_contour_distance_ccw(param2, param1, contour_length);
|
return closed_contour_distance_ccw(param2, param1, contour_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length along the contour from cp1 to cp2 going counter-clockwise.
|
// Length along the contour from cp1 to cp2 going counter-clockwise.
|
||||||
float path_length_along_contour_ccw(const ContourIntersectionPoint* cp1, const ContourIntersectionPoint* cp2, float contour_length)
|
double path_length_along_contour_ccw(const ContourIntersectionPoint *cp1, const ContourIntersectionPoint *cp2, double contour_length)
|
||||||
{
|
{
|
||||||
assert(cp1 != nullptr);
|
assert(cp1 != nullptr);
|
||||||
assert(cp2 != nullptr);
|
assert(cp2 != nullptr);
|
||||||
@ -1238,13 +1238,13 @@ float path_length_along_contour_ccw(const ContourIntersectionPoint* cp1, const C
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lengths along the contour from cp1 to cp2 going CCW and going CW.
|
// Lengths along the contour from cp1 to cp2 going CCW and going CW.
|
||||||
std::pair<float, float> path_lengths_along_contour(const ContourIntersectionPoint* cp1, const ContourIntersectionPoint* cp2, float contour_length)
|
std::pair<double, double> path_lengths_along_contour(const ContourIntersectionPoint *cp1, const ContourIntersectionPoint *cp2, double contour_length)
|
||||||
{
|
{
|
||||||
// Zero'th param is the length of the contour.
|
// Zero'th param is the length of the contour.
|
||||||
float param_lo = cp1->param;
|
double param_lo = cp1->param;
|
||||||
float param_hi = cp2->param;
|
double param_hi = cp2->param;
|
||||||
assert(param_lo >= 0.f && param_lo <= contour_length);
|
assert(param_lo >= 0. && param_lo <= contour_length);
|
||||||
assert(param_hi >= 0.f && param_hi <= contour_length);
|
assert(param_hi >= 0. && param_hi <= contour_length);
|
||||||
bool reversed = false;
|
bool reversed = false;
|
||||||
if (param_lo > param_hi) {
|
if (param_lo > param_hi) {
|
||||||
std::swap(param_lo, param_hi);
|
std::swap(param_lo, param_hi);
|
||||||
@ -1271,25 +1271,25 @@ static inline void take_cw_full(Polyline& pl, const Points& contour, size_t idx_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add contour points from interval (idx_start, idx_end> to polyline, limited by the Eucleidean length taken.
|
// Add contour points from interval (idx_start, idx_end> to polyline, limited by the Eucleidean length taken.
|
||||||
static inline float take_cw_limited(Polyline& pl, const Points& contour, const std::vector<float>& params, size_t idx_start, size_t idx_end, float length_to_take)
|
static inline double take_cw_limited(Polyline &pl, const Points &contour, const std::vector<double> ¶ms, size_t idx_start, size_t idx_end, double length_to_take)
|
||||||
{
|
{
|
||||||
// If appending to an infill line, then the start point of a perimeter line shall match the end point of an infill line.
|
// If appending to an infill line, then the start point of a perimeter line shall match the end point of an infill line.
|
||||||
assert(pl.empty() || pl.points.back() == contour[idx_start]);
|
assert(pl.empty() || pl.points.back() == contour[idx_start]);
|
||||||
assert(contour.size() + 1 == params.size());
|
assert(contour.size() + 1 == params.size());
|
||||||
assert(length_to_take > SCALED_EPSILON);
|
assert(length_to_take > SCALED_EPSILON);
|
||||||
// Length of the contour.
|
// Length of the contour.
|
||||||
float length = params.back();
|
double length = params.back();
|
||||||
// Parameter (length from contour.front()) for the first point.
|
// Parameter (length from contour.front()) for the first point.
|
||||||
float p0 = params[idx_start];
|
double p0 = params[idx_start];
|
||||||
// Current (2nd) point of the contour.
|
// Current (2nd) point of the contour.
|
||||||
size_t i = (idx_start == 0) ? contour.size() - 1 : idx_start - 1;
|
size_t i = (idx_start == 0) ? contour.size() - 1 : idx_start - 1;
|
||||||
// Previous point of the contour.
|
// Previous point of the contour.
|
||||||
size_t iprev = idx_start;
|
size_t iprev = idx_start;
|
||||||
// Length of the contour curve taken for iprev.
|
// Length of the contour curve taken for iprev.
|
||||||
float lprev = 0.f;
|
double lprev = 0.;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
float l = closed_contour_distance_cw(p0, params[i], length);
|
double l = closed_contour_distance_cw(p0, params[i], length);
|
||||||
if (l >= length_to_take) {
|
if (l >= length_to_take) {
|
||||||
// Trim the last segment.
|
// Trim the last segment.
|
||||||
double t = double(length_to_take - lprev) / (l - lprev);
|
double t = double(length_to_take - lprev) / (l - lprev);
|
||||||
@ -1327,16 +1327,16 @@ static inline void take_ccw_full(Polyline& pl, const Points& contour, size_t idx
|
|||||||
|
|
||||||
// Add contour points from interval (idx_start, idx_end> to polyline, limited by the Eucleidean length taken.
|
// Add contour points from interval (idx_start, idx_end> to polyline, limited by the Eucleidean length taken.
|
||||||
// Returns length of the contour taken.
|
// Returns length of the contour taken.
|
||||||
static inline float take_ccw_limited(Polyline& pl, const Points& contour, const std::vector<float>& params, size_t idx_start, size_t idx_end, float length_to_take)
|
static inline double take_ccw_limited(Polyline &pl, const Points &contour, const std::vector<double> ¶ms, size_t idx_start, size_t idx_end, double length_to_take)
|
||||||
{
|
{
|
||||||
// If appending to an infill line, then the start point of a perimeter line shall match the end point of an infill line.
|
// If appending to an infill line, then the start point of a perimeter line shall match the end point of an infill line.
|
||||||
assert(pl.empty() || pl.points.back() == contour[idx_start]);
|
assert(pl.empty() || pl.points.back() == contour[idx_start]);
|
||||||
assert(contour.size() + 1 == params.size());
|
assert(contour.size() + 1 == params.size());
|
||||||
assert(length_to_take > SCALED_EPSILON);
|
assert(length_to_take > SCALED_EPSILON);
|
||||||
// Length of the contour.
|
// Length of the contour.
|
||||||
float length = params.back();
|
double length = params.back();
|
||||||
// Parameter (length from contour.front()) for the first point.
|
// Parameter (length from contour.front()) for the first point.
|
||||||
float p0 = params[idx_start];
|
double p0 = params[idx_start];
|
||||||
// Current (2nd) point of the contour.
|
// Current (2nd) point of the contour.
|
||||||
size_t i = idx_start;
|
size_t i = idx_start;
|
||||||
if (++i == contour.size())
|
if (++i == contour.size())
|
||||||
@ -1344,9 +1344,9 @@ static inline float take_ccw_limited(Polyline& pl, const Points& contour, const
|
|||||||
// Previous point of the contour.
|
// Previous point of the contour.
|
||||||
size_t iprev = idx_start;
|
size_t iprev = idx_start;
|
||||||
// Length of the contour curve taken at iprev.
|
// Length of the contour curve taken at iprev.
|
||||||
float lprev = 0.f;
|
double lprev = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
float l = closed_contour_distance_ccw(p0, params[i], length);
|
double l = closed_contour_distance_ccw(p0, params[i], length);
|
||||||
if (l >= length_to_take) {
|
if (l >= length_to_take) {
|
||||||
// Trim the last segment.
|
// Trim the last segment.
|
||||||
double t = double(length_to_take - lprev) / (l - lprev);
|
double t = double(length_to_take - lprev) / (l - lprev);
|
||||||
@ -1415,8 +1415,8 @@ static void take(Polyline& pl1, const Polyline& pl2, const Points& contour, Cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void take_limited(
|
static void take_limited(
|
||||||
Polyline& pl1, const Points& contour, const std::vector<float>& params,
|
Polyline &pl1, const Points &contour, const std::vector<double> ¶ms,
|
||||||
ContourIntersectionPoint* cp_start, ContourIntersectionPoint* cp_end, bool clockwise, float take_max_length, float line_half_width)
|
ContourIntersectionPoint *cp_start, ContourIntersectionPoint *cp_end, bool clockwise, double take_max_length, double line_half_width)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// This is a valid case, where a single infill line connect to two different contours (outer contour + hole or two holes).
|
// This is a valid case, where a single infill line connect to two different contours (outer contour + hole or two holes).
|
||||||
@ -1449,11 +1449,11 @@ static void take_limited(
|
|||||||
pl1.points.reserve(pl1.points.size() + pl_tmp.size() + size_t(new_points));
|
pl1.points.reserve(pl1.points.size() + pl_tmp.size() + size_t(new_points));
|
||||||
}
|
}
|
||||||
|
|
||||||
float length = params.back();
|
double length = params.back();
|
||||||
float length_to_go = take_max_length;
|
double length_to_go = take_max_length;
|
||||||
cp_start->consumed = true;
|
cp_start->consumed = true;
|
||||||
if (cp_start == cp_end) {
|
if (cp_start == cp_end) {
|
||||||
length_to_go = std::max(0.f, std::min(length_to_go, length - line_half_width));
|
length_to_go = std::max(0., std::min(length_to_go, length - line_half_width));
|
||||||
length_to_go = std::min(length_to_go, clockwise ? cp_start->contour_not_taken_length_prev : cp_start->contour_not_taken_length_next);
|
length_to_go = std::min(length_to_go, clockwise ? cp_start->contour_not_taken_length_prev : cp_start->contour_not_taken_length_next);
|
||||||
cp_start->consume_prev();
|
cp_start->consume_prev();
|
||||||
cp_start->consume_next();
|
cp_start->consume_next();
|
||||||
@ -1466,11 +1466,11 @@ static void take_limited(
|
|||||||
assert(cp_start != cp_end);
|
assert(cp_start != cp_end);
|
||||||
for (ContourIntersectionPoint* cp = cp_start; cp != cp_end; cp = cp->prev_on_contour) {
|
for (ContourIntersectionPoint* cp = cp_start; cp != cp_end; cp = cp->prev_on_contour) {
|
||||||
// Length of the segment from cp to cp->prev_on_contour.
|
// Length of the segment from cp to cp->prev_on_contour.
|
||||||
float l = closed_contour_distance_cw(cp->param, cp->prev_on_contour->param, length);
|
double l = closed_contour_distance_cw(cp->param, cp->prev_on_contour->param, length);
|
||||||
length_to_go = std::min(length_to_go, cp->contour_not_taken_length_prev);
|
length_to_go = std::min(length_to_go, cp->contour_not_taken_length_prev);
|
||||||
//if (cp->prev_on_contour->consumed)
|
//if (cp->prev_on_contour->consumed)
|
||||||
// Don't overlap with an already extruded infill line.
|
// Don't overlap with an already extruded infill line.
|
||||||
length_to_go = std::max(0.f, std::min(length_to_go, l - line_half_width));
|
length_to_go = std::max(0., std::min(length_to_go, l - line_half_width));
|
||||||
cp->consume_prev();
|
cp->consume_prev();
|
||||||
if (l >= length_to_go) {
|
if (l >= length_to_go) {
|
||||||
if (length_to_go > SCALED_EPSILON) {
|
if (length_to_go > SCALED_EPSILON) {
|
||||||
@ -1479,7 +1479,7 @@ static void take_limited(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
cp->prev_on_contour->trim_next(0.f);
|
cp->prev_on_contour->trim_next(0.);
|
||||||
take_cw_full(pl1, contour, cp->point_idx, cp->prev_on_contour->point_idx);
|
take_cw_full(pl1, contour, cp->point_idx, cp->prev_on_contour->point_idx);
|
||||||
length_to_go -= l;
|
length_to_go -= l;
|
||||||
}
|
}
|
||||||
@ -1487,11 +1487,11 @@ static void take_limited(
|
|||||||
} else {
|
} else {
|
||||||
assert(cp_start != cp_end);
|
assert(cp_start != cp_end);
|
||||||
for (ContourIntersectionPoint* cp = cp_start; cp != cp_end; cp = cp->next_on_contour) {
|
for (ContourIntersectionPoint* cp = cp_start; cp != cp_end; cp = cp->next_on_contour) {
|
||||||
float l = closed_contour_distance_ccw(cp->param, cp->next_on_contour->param, length);
|
double l = closed_contour_distance_ccw(cp->param, cp->next_on_contour->param, length);
|
||||||
length_to_go = std::min(length_to_go, cp->contour_not_taken_length_next);
|
length_to_go = std::min(length_to_go, cp->contour_not_taken_length_next);
|
||||||
//if (cp->next_on_contour->consumed)
|
//if (cp->next_on_contour->consumed)
|
||||||
// Don't overlap with an already extruded infill line.
|
// Don't overlap with an already extruded infill line.
|
||||||
length_to_go = std::max(0.f, std::min(length_to_go, l - line_half_width));
|
length_to_go = std::max(0., std::min(length_to_go, l - line_half_width));
|
||||||
cp->consume_next();
|
cp->consume_next();
|
||||||
if (l >= length_to_go) {
|
if (l >= length_to_go) {
|
||||||
if (length_to_go > SCALED_EPSILON) {
|
if (length_to_go > SCALED_EPSILON) {
|
||||||
@ -1500,7 +1500,7 @@ static void take_limited(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
cp->next_on_contour->trim_prev(0.f);
|
cp->next_on_contour->trim_prev(0.);
|
||||||
take_ccw_full(pl1, contour, cp->point_idx, cp->next_on_contour->point_idx);
|
take_ccw_full(pl1, contour, cp->point_idx, cp->next_on_contour->point_idx);
|
||||||
length_to_go -= l;
|
length_to_go -= l;
|
||||||
}
|
}
|
||||||
@ -1681,19 +1681,19 @@ static inline bool line_rounded_thick_segment_collision(
|
|||||||
return intersects;
|
return intersects;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool inside_interval(float low, float high, float p)
|
static inline bool inside_interval(double low, double high, double p)
|
||||||
{
|
{
|
||||||
return p >= low && p <= high;
|
return p >= low && p <= high;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool interval_inside_interval(float outer_low, float outer_high, float inner_low, float inner_high, float epsilon)
|
static inline bool interval_inside_interval(double outer_low, double outer_high, double inner_low, double inner_high, double epsilon)
|
||||||
{
|
{
|
||||||
outer_low -= epsilon;
|
outer_low -= epsilon;
|
||||||
outer_high += epsilon;
|
outer_high += epsilon;
|
||||||
return inside_interval(outer_low, outer_high, inner_low) && inside_interval(outer_low, outer_high, inner_high);
|
return inside_interval(outer_low, outer_high, inner_low) && inside_interval(outer_low, outer_high, inner_high);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool cyclic_interval_inside_interval(float outer_low, float outer_high, float inner_low, float inner_high, float length)
|
static inline bool cyclic_interval_inside_interval(double outer_low, double outer_high, double inner_low, double inner_high, double length)
|
||||||
{
|
{
|
||||||
if (outer_low > outer_high)
|
if (outer_low > outer_high)
|
||||||
outer_high += length;
|
outer_high += length;
|
||||||
@ -1703,7 +1703,7 @@ static inline bool cyclic_interval_inside_interval(float outer_low, float outer_
|
|||||||
inner_low += length;
|
inner_low += length;
|
||||||
inner_high += length;
|
inner_high += length;
|
||||||
}
|
}
|
||||||
return interval_inside_interval(outer_low, outer_high, inner_low, inner_high, float(SCALED_EPSILON));
|
return interval_inside_interval(outer_low, outer_high, inner_low, inner_high, double(SCALED_EPSILON));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #define INFILL_DEBUG_OUTPUT
|
// #define INFILL_DEBUG_OUTPUT
|
||||||
@ -1713,7 +1713,7 @@ static void export_infill_to_svg(
|
|||||||
// Boundary contour, along which the perimeter extrusions will be drawn.
|
// Boundary contour, along which the perimeter extrusions will be drawn.
|
||||||
const std::vector<Points>& boundary,
|
const std::vector<Points>& boundary,
|
||||||
// Parametrization of boundary with Euclidian length.
|
// Parametrization of boundary with Euclidian length.
|
||||||
const std::vector<std::vector<float>>& boundary_parameters,
|
const std::vector<std::vector<double>> &boundary_parameters,
|
||||||
// Intersections (T-joints) of the infill lines with the boundary.
|
// Intersections (T-joints) of the infill lines with the boundary.
|
||||||
std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections,
|
std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections,
|
||||||
// Infill lines, either completely inside the boundary, or touching the boundary.
|
// Infill lines, either completely inside the boundary, or touching the boundary.
|
||||||
@ -1739,11 +1739,11 @@ static void export_infill_to_svg(
|
|||||||
const std::string color_boundary_not_trimmed = "yellow";
|
const std::string color_boundary_not_trimmed = "yellow";
|
||||||
const coordf_t boundary_line_width = scaled_spacing;
|
const coordf_t boundary_line_width = scaled_spacing;
|
||||||
svg.draw_outline(polygons, "red", boundary_line_width);
|
svg.draw_outline(polygons, "red", boundary_line_width);
|
||||||
for (const std::vector<ContourIntersectionPoint*>& intersections : boundary_intersections) {
|
for (const std::vector<ContourIntersectionPoint*> &intersections : boundary_intersections) {
|
||||||
const size_t boundary_idx = &intersections - boundary_intersections.data();
|
const size_t boundary_idx = &intersections - boundary_intersections.data();
|
||||||
const Points& contour = boundary[boundary_idx];
|
const Points &contour = boundary[boundary_idx];
|
||||||
const std::vector<float>& contour_param = boundary_parameters[boundary_idx];
|
const std::vector<double> &contour_param = boundary_parameters[boundary_idx];
|
||||||
for (const ContourIntersectionPoint* ip : intersections) {
|
for (const ContourIntersectionPoint *ip : intersections) {
|
||||||
assert(ip->next_trimmed == ip->next_on_contour->prev_trimmed);
|
assert(ip->next_trimmed == ip->next_on_contour->prev_trimmed);
|
||||||
assert(ip->prev_trimmed == ip->prev_on_contour->next_trimmed);
|
assert(ip->prev_trimmed == ip->prev_on_contour->next_trimmed);
|
||||||
{
|
{
|
||||||
@ -1837,7 +1837,7 @@ void mark_boundary_segments_touching_infill(
|
|||||||
// Boundary contour, along which the perimeter extrusions will be drawn.
|
// Boundary contour, along which the perimeter extrusions will be drawn.
|
||||||
const std::vector<Points>& boundary,
|
const std::vector<Points>& boundary,
|
||||||
// Parametrization of boundary with Euclidian length.
|
// Parametrization of boundary with Euclidian length.
|
||||||
const std::vector<std::vector<float>>& boundary_parameters,
|
const std::vector<std::vector<double>> &boundary_parameters,
|
||||||
// Intersections (T-joints) of the infill lines with the boundary.
|
// Intersections (T-joints) of the infill lines with the boundary.
|
||||||
std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections,
|
std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections,
|
||||||
// Bounding box around the boundary.
|
// Bounding box around the boundary.
|
||||||
@ -1868,13 +1868,13 @@ void mark_boundary_segments_touching_infill(
|
|||||||
// Make sure that the the grid is big enough for queries against the thick segment.
|
// Make sure that the the grid is big enough for queries against the thick segment.
|
||||||
grid.set_bbox(boundary_bbox.inflated(distance_colliding * 1.43));
|
grid.set_bbox(boundary_bbox.inflated(distance_colliding * 1.43));
|
||||||
// Inflate the bounding box by a thick line width.
|
// Inflate the bounding box by a thick line width.
|
||||||
grid.create(boundary, std::max(clip_distance, distance_colliding) + scale_(10.));
|
grid.create(boundary, coord_t(std::max(clip_distance, distance_colliding) + scale_(10.)));
|
||||||
|
|
||||||
// Visitor for the EdgeGrid to trim boundary_intersections with existing infill lines.
|
// Visitor for the EdgeGrid to trim boundary_intersections with existing infill lines.
|
||||||
struct Visitor {
|
struct Visitor {
|
||||||
Visitor(const EdgeGrid::Grid& grid,
|
Visitor(const EdgeGrid::Grid &grid,
|
||||||
const std::vector<Points>& boundary, const std::vector<std::vector<float>>& boundary_parameters, std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections,
|
const std::vector<Points> &boundary, const std::vector<std::vector<double>> &boundary_parameters, std::vector<std::vector<ContourIntersectionPoint*>> &boundary_intersections,
|
||||||
const double radius) :
|
const double radius) :
|
||||||
grid(grid), boundary(boundary), boundary_parameters(boundary_parameters), boundary_intersections(boundary_intersections), radius(radius), trim_l_threshold(0.5 * radius) {}
|
grid(grid), boundary(boundary), boundary_parameters(boundary_parameters), boundary_intersections(boundary_intersections), radius(radius), trim_l_threshold(0.5 * radius) {}
|
||||||
|
|
||||||
// Init with a segment of an infill line.
|
// Init with a segment of an infill line.
|
||||||
@ -1910,10 +1910,10 @@ void mark_boundary_segments_touching_infill(
|
|||||||
// The boundary segment intersects with the infill segment thickened by radius.
|
// The boundary segment intersects with the infill segment thickened by radius.
|
||||||
// Interval is specified in Euclidian length from seg_pt1 to seg_pt2.
|
// Interval is specified in Euclidian length from seg_pt1 to seg_pt2.
|
||||||
// 1) Find the Euclidian parameters of seg_pt1 and seg_pt2 on its boundary contour.
|
// 1) Find the Euclidian parameters of seg_pt1 and seg_pt2 on its boundary contour.
|
||||||
const std::vector<float>& contour_parameters = boundary_parameters[it_contour_and_segment->first];
|
const std::vector<double> &contour_parameters = boundary_parameters[it_contour_and_segment->first];
|
||||||
const float contour_length = contour_parameters.back();
|
const double contour_length = contour_parameters.back();
|
||||||
const float param_seg_pt1 = contour_parameters[it_contour_and_segment->second];
|
const double param_seg_pt1 = contour_parameters[it_contour_and_segment->second];
|
||||||
const float param_seg_pt2 = contour_parameters[it_contour_and_segment->second + 1];
|
const double param_seg_pt2 = contour_parameters[it_contour_and_segment->second + 1];
|
||||||
#ifdef INFILL_DEBUG_OUTPUT
|
#ifdef INFILL_DEBUG_OUTPUT
|
||||||
this->perimeter_overlaps.push_back({ Point((seg_pt1 + (seg_pt2 - seg_pt1).normalized() * interval.first).cast<coord_t>()),
|
this->perimeter_overlaps.push_back({ Point((seg_pt1 + (seg_pt2 - seg_pt1).normalized() * interval.first).cast<coord_t>()),
|
||||||
Point((seg_pt1 + (seg_pt2 - seg_pt1).normalized() * interval.second).cast<coord_t>()) });
|
Point((seg_pt1 + (seg_pt2 - seg_pt1).normalized() * interval.second).cast<coord_t>()) });
|
||||||
@ -1921,8 +1921,8 @@ void mark_boundary_segments_touching_infill(
|
|||||||
assert(interval.first >= 0.);
|
assert(interval.first >= 0.);
|
||||||
assert(interval.second >= 0.);
|
assert(interval.second >= 0.);
|
||||||
assert(interval.first <= interval.second);
|
assert(interval.first <= interval.second);
|
||||||
const auto param_overlap1 = std::min(param_seg_pt2, float(param_seg_pt1 + interval.first));
|
const auto param_overlap1 = std::min(param_seg_pt2, param_seg_pt1 + interval.first);
|
||||||
const auto param_overlap2 = std::min(param_seg_pt2, float(param_seg_pt1 + interval.second));
|
const auto param_overlap2 = std::min(param_seg_pt2, param_seg_pt1 + interval.second);
|
||||||
// 2) Find the ContourIntersectionPoints before param_overlap1 and after param_overlap2.
|
// 2) Find the ContourIntersectionPoints before param_overlap1 and after param_overlap2.
|
||||||
// Find the span of ContourIntersectionPoints, that is trimmed by the interval (param_overlap1, param_overlap2).
|
// Find the span of ContourIntersectionPoints, that is trimmed by the interval (param_overlap1, param_overlap2).
|
||||||
ContourIntersectionPoint* ip_low, * ip_high;
|
ContourIntersectionPoint* ip_low, * ip_high;
|
||||||
@ -1949,7 +1949,7 @@ void mark_boundary_segments_touching_infill(
|
|||||||
ip->consume_next();
|
ip->consume_next();
|
||||||
}
|
}
|
||||||
// Subtract the interval from the first and last segments.
|
// Subtract the interval from the first and last segments.
|
||||||
float trim_l = closed_contour_distance_ccw(ip_low->param, param_overlap1, contour_length);
|
double trim_l = closed_contour_distance_ccw(ip_low->param, param_overlap1, contour_length);
|
||||||
//if (trim_l > trim_l_threshold)
|
//if (trim_l > trim_l_threshold)
|
||||||
ip_low->trim_next(trim_l);
|
ip_low->trim_next(trim_l);
|
||||||
trim_l = closed_contour_distance_ccw(param_overlap2, ip_high->param, contour_length);
|
trim_l = closed_contour_distance_ccw(param_overlap2, ip_high->param, contour_length);
|
||||||
@ -1979,14 +1979,14 @@ void mark_boundary_segments_touching_infill(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeGrid::Grid& grid;
|
const EdgeGrid::Grid &grid;
|
||||||
const std::vector<Points>& boundary;
|
const std::vector<Points> &boundary;
|
||||||
const std::vector<std::vector<float>>& boundary_parameters;
|
const std::vector<std::vector<double>> &boundary_parameters;
|
||||||
std::vector<std::vector<ContourIntersectionPoint*>>& boundary_intersections;
|
std::vector<std::vector<ContourIntersectionPoint*>> &boundary_intersections;
|
||||||
// Maximum distance between the boundary and the infill line allowed to consider the boundary not touching the infill line.
|
// Maximum distance between the boundary and the infill line allowed to consider the boundary not touching the infill line.
|
||||||
const double radius;
|
const double radius;
|
||||||
// Region around the contour / infill line intersection point, where the intersections are ignored.
|
// Region around the contour / infill line intersection point, where the intersections are ignored.
|
||||||
const float trim_l_threshold;
|
const double trim_l_threshold;
|
||||||
|
|
||||||
const Vec2d* infill_pt1;
|
const Vec2d* infill_pt1;
|
||||||
const Vec2d* infill_pt2;
|
const Vec2d* infill_pt2;
|
||||||
@ -2106,11 +2106,11 @@ void connect_infill(Polylines&& infill_ordered, const Polygons& boundary_src, co
|
|||||||
void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*>& boundary_src, const BoundingBox& bbox, Polylines& polylines_out, const double spacing, const FillParams& params)
|
void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*>& boundary_src, const BoundingBox& bbox, Polylines& polylines_out, const double spacing, const FillParams& params)
|
||||||
{
|
{
|
||||||
assert(!infill_ordered.empty());
|
assert(!infill_ordered.empty());
|
||||||
assert(params.anchor_length >= 0.f);
|
assert(params.anchor_length >= 0.);
|
||||||
assert(params.anchor_length_max >= 0.01f);
|
assert(params.anchor_length_max >= 0.01f);
|
||||||
assert(params.anchor_length_max >= params.anchor_length);
|
assert(params.anchor_length_max >= params.anchor_length);
|
||||||
const auto anchor_length = float(scale_(params.anchor_length));
|
const double anchor_length = scale_(params.anchor_length);
|
||||||
const auto anchor_length_max = float(scale_(params.anchor_length_max));
|
const double anchor_length_max = scale_(params.anchor_length_max);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
append(polylines_out, infill_ordered);
|
append(polylines_out, infill_ordered);
|
||||||
@ -2118,10 +2118,10 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 1) Add the end points of infill_ordered to boundary_src.
|
// 1) Add the end points of infill_ordered to boundary_src.
|
||||||
std::vector<Points> boundary;
|
std::vector<Points> boundary;
|
||||||
std::vector<std::vector<float>> boundary_params;
|
std::vector<std::vector<double>> boundary_params;
|
||||||
boundary.assign(boundary_src.size(), Points());
|
boundary.assign(boundary_src.size(), Points());
|
||||||
boundary_params.assign(boundary_src.size(), std::vector<float>());
|
boundary_params.assign(boundary_src.size(), std::vector<double>());
|
||||||
// Mapping the infill_ordered end point to a (contour, point) of boundary.
|
// Mapping the infill_ordered end point to a (contour, point) of boundary.
|
||||||
static constexpr auto boundary_idx_unconnected = std::numeric_limits<size_t>::max();
|
static constexpr auto boundary_idx_unconnected = std::numeric_limits<size_t>::max();
|
||||||
std::vector<ContourIntersectionPoint> map_infill_end_point_to_boundary(infill_ordered.size() * 2, ContourIntersectionPoint{ boundary_idx_unconnected, boundary_idx_unconnected });
|
std::vector<ContourIntersectionPoint> map_infill_end_point_to_boundary(infill_ordered.size() * 2, ContourIntersectionPoint{ boundary_idx_unconnected, boundary_idx_unconnected });
|
||||||
@ -2131,10 +2131,10 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
{
|
{
|
||||||
EdgeGrid::Grid grid;
|
EdgeGrid::Grid grid;
|
||||||
grid.set_bbox(bbox.inflated(SCALED_EPSILON));
|
grid.set_bbox(bbox.inflated(SCALED_EPSILON));
|
||||||
grid.create(boundary_src, scale_(10.));
|
grid.create(boundary_src, coord_t(scale_(10.)));
|
||||||
intersection_points.reserve(infill_ordered.size() * 2);
|
intersection_points.reserve(infill_ordered.size() * 2);
|
||||||
for (const Polyline& pl : infill_ordered)
|
for (const Polyline &pl : infill_ordered)
|
||||||
for (const Point* pt : { &pl.points.front(), &pl.points.back() }) {
|
for (const Point *pt : { &pl.points.front(), &pl.points.back() }) {
|
||||||
EdgeGrid::Grid::ClosestPointResult cp = grid.closest_point(*pt, SCALED_EPSILON);
|
EdgeGrid::Grid::ClosestPointResult cp = grid.closest_point(*pt, SCALED_EPSILON);
|
||||||
if (cp.valid()) {
|
if (cp.valid()) {
|
||||||
// The infill end point shall lie on the contour.
|
// The infill end point shall lie on the contour.
|
||||||
@ -2168,23 +2168,31 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
++n_intersection_points;
|
++n_intersection_points;
|
||||||
contour_intersection_points.reserve(n_intersection_points);
|
contour_intersection_points.reserve(n_intersection_points);
|
||||||
}
|
}
|
||||||
for (size_t idx_point = 0; idx_point < contour_src.points.size(); ++idx_point) {
|
for (size_t idx_point = 0; idx_point < contour_src.points.size(); ++ idx_point) {
|
||||||
contour_dst.emplace_back(contour_src.points[idx_point]);
|
const Point &ipt = contour_src.points[idx_point];
|
||||||
for (; it != it_end && it->first.contour_idx == idx_contour && it->first.start_point_idx == idx_point; ++it) {
|
if (contour_dst.empty() || contour_dst.back() != ipt)
|
||||||
|
contour_dst.emplace_back(ipt);
|
||||||
|
for (; it != it_end && it->first.contour_idx == idx_contour && it->first.start_point_idx == idx_point; ++ it) {
|
||||||
// Add these points to the destination contour.
|
// Add these points to the destination contour.
|
||||||
const Polyline& infill_line = infill_ordered[it->second / 2];
|
const Polyline &infill_line = infill_ordered[it->second / 2];
|
||||||
const Point& pt = (it->second & 1) ? infill_line.points.back() : infill_line.points.front();
|
const Point &pt = (it->second & 1) ? infill_line.points.back() : infill_line.points.front();
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
{
|
{
|
||||||
const Vec2d pt1 = contour_src[idx_point].cast<double>();
|
const Vec2d pt1 = ipt.cast<double>();
|
||||||
const Vec2d pt2 = (idx_point + 1 == contour_src.size() ? contour_src.points.front() : contour_src.points[idx_point + 1]).cast<double>();
|
const Vec2d pt2 = (idx_point + 1 == contour_src.size() ? contour_src.points.front() : contour_src.points[idx_point + 1]).cast<double>();
|
||||||
const Vec2d ptx = lerp(pt1, pt2, it->first.t);
|
const Vec2d ptx = lerp(pt1, pt2, it->first.t);
|
||||||
assert(std::abs(pt.x() - pt.x()) < SCALED_EPSILON);
|
assert(std::abs(pt.x() - pt.x()) < SCALED_EPSILON);
|
||||||
assert(std::abs(pt.y() - pt.y()) < SCALED_EPSILON);
|
assert(std::abs(pt.y() - pt.y()) < SCALED_EPSILON);
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
map_infill_end_point_to_boundary[it->second] = ContourIntersectionPoint{ idx_contour, contour_dst.size() };
|
size_t idx_tjoint_pt = 0;
|
||||||
ContourIntersectionPoint* pthis = &map_infill_end_point_to_boundary[it->second];
|
if (idx_point + 1 < contour_src.size() || pt != contour_dst.front()) {
|
||||||
|
if (pt != contour_dst.back())
|
||||||
|
contour_dst.emplace_back(pt);
|
||||||
|
idx_tjoint_pt = contour_dst.size() - 1;
|
||||||
|
}
|
||||||
|
map_infill_end_point_to_boundary[it->second] = ContourIntersectionPoint{ idx_contour, idx_tjoint_pt };
|
||||||
|
ContourIntersectionPoint *pthis = &map_infill_end_point_to_boundary[it->second];
|
||||||
if (pprev) {
|
if (pprev) {
|
||||||
pprev->next_on_contour = pthis;
|
pprev->next_on_contour = pthis;
|
||||||
pthis->prev_on_contour = pprev;
|
pthis->prev_on_contour = pprev;
|
||||||
@ -2192,25 +2200,26 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
pfirst = pthis;
|
pfirst = pthis;
|
||||||
contour_intersection_points.emplace_back(pthis);
|
contour_intersection_points.emplace_back(pthis);
|
||||||
pprev = pthis;
|
pprev = pthis;
|
||||||
//add new point here
|
}
|
||||||
contour_dst.emplace_back(pt);
|
|
||||||
}
|
|
||||||
if (pfirst) {
|
if (pfirst) {
|
||||||
pprev->next_on_contour = pfirst;
|
pprev->next_on_contour = pfirst;
|
||||||
pfirst->prev_on_contour = pprev;
|
pfirst->prev_on_contour = pprev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parametrize the new boundary with the intersection points inserted.
|
// Parametrize the new boundary with the intersection points inserted.
|
||||||
std::vector<float>& contour_params = boundary_params[idx_contour];
|
std::vector<double> &contour_params = boundary_params[idx_contour];
|
||||||
contour_params.assign(contour_dst.size() + 1, 0.f);
|
contour_params.assign(contour_dst.size() + 1, 0.);
|
||||||
for (size_t i = 1; i < contour_dst.size(); ++i)
|
for (size_t i = 1; i < contour_dst.size(); ++i) {
|
||||||
contour_params[i] = contour_params[i - 1] + (contour_dst[i].cast<float>() - contour_dst[i - 1].cast<float>()).norm();
|
contour_params[i] = contour_params[i - 1] + (contour_dst[i].cast<double>() - contour_dst[i - 1].cast<double>()).norm();
|
||||||
contour_params.back() = contour_params[contour_params.size() - 2] + (contour_dst.back().cast<float>() - contour_dst.front().cast<float>()).norm();
|
assert(contour_params[i] > contour_params[i - 1]);
|
||||||
|
}
|
||||||
|
contour_params.back() = contour_params[contour_params.size() - 2] + (contour_dst.back().cast<double>() - contour_dst.front().cast<double>()).norm();
|
||||||
|
assert(contour_params.back() > contour_params[contour_params.size() - 2]);
|
||||||
// Map parameters from contour_params to boundary_intersection_points.
|
// Map parameters from contour_params to boundary_intersection_points.
|
||||||
for (ContourIntersectionPoint* ip : contour_intersection_points)
|
for (ContourIntersectionPoint* ip : contour_intersection_points)
|
||||||
ip->param = contour_params[ip->point_idx];
|
ip->param = contour_params[ip->point_idx];
|
||||||
// and measure distance to the previous and next intersection point.
|
// and measure distance to the previous and next intersection point.
|
||||||
const float contour_length = contour_params.back();
|
const double contour_length = contour_params.back();
|
||||||
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
||||||
if (ip->next_on_contour == ip) {
|
if (ip->next_on_contour == ip) {
|
||||||
assert(ip->prev_on_contour == ip);
|
assert(ip->prev_on_contour == ip);
|
||||||
@ -2244,9 +2253,9 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connection from end of one infill line to the start of another infill line.
|
// Connection from end of one infill line to the start of another infill line.
|
||||||
//const float length_max = scale_(spacing);
|
//const double length_max = scale_(spacing);
|
||||||
// const auto length_max = float(scale_((2. / params.density) * spacing));
|
// const auto length_max = double(scale_((2. / params.density) * spacing));
|
||||||
const auto length_max = float(scale_((1000. / params.density) * spacing));
|
const auto length_max = double(scale_((1000. / params.density) * spacing));
|
||||||
std::vector<size_t> merged_with(infill_ordered.size());
|
std::vector<size_t> merged_with(infill_ordered.size());
|
||||||
std::iota(merged_with.begin(), merged_with.end(), 0);
|
std::iota(merged_with.begin(), merged_with.end(), 0);
|
||||||
struct ConnectionCost {
|
struct ConnectionCost {
|
||||||
@ -2264,7 +2273,7 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
const ContourIntersectionPoint* cp2 = &map_infill_end_point_to_boundary[idx_chain * 2];
|
const ContourIntersectionPoint* cp2 = &map_infill_end_point_to_boundary[idx_chain * 2];
|
||||||
if (cp1->contour_idx != boundary_idx_unconnected && cp1->contour_idx == cp2->contour_idx) {
|
if (cp1->contour_idx != boundary_idx_unconnected && cp1->contour_idx == cp2->contour_idx) {
|
||||||
// End points on the same contour. Try to connect them.
|
// End points on the same contour. Try to connect them.
|
||||||
std::pair<float, float> len = path_lengths_along_contour(cp1, cp2, boundary_params[cp1->contour_idx].back());
|
std::pair<double, double> len = path_lengths_along_contour(cp1, cp2, boundary_params[cp1->contour_idx].back());
|
||||||
if (len.first < length_max)
|
if (len.first < length_max)
|
||||||
connections_sorted.emplace_back(idx_chain - 1, len.first, false);
|
connections_sorted.emplace_back(idx_chain - 1, len.first, false);
|
||||||
if (len.second < length_max)
|
if (len.second < length_max)
|
||||||
@ -2301,7 +2310,7 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
return std::numeric_limits<size_t>::max();
|
return std::numeric_limits<size_t>::max();
|
||||||
};
|
};
|
||||||
|
|
||||||
const float line_half_width = 0.5f * scale_(spacing);
|
const double line_half_width = 0.5 * scale_(spacing);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (ConnectionCost& connection_cost : connections_sorted) {
|
for (ConnectionCost& connection_cost : connections_sorted) {
|
||||||
@ -2311,7 +2320,7 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
assert(cp1->contour_idx == cp2->contour_idx && cp1->contour_idx != boundary_idx_unconnected);
|
assert(cp1->contour_idx == cp2->contour_idx && cp1->contour_idx != boundary_idx_unconnected);
|
||||||
if (cp1->consumed || cp2->consumed)
|
if (cp1->consumed || cp2->consumed)
|
||||||
continue;
|
continue;
|
||||||
const float length = connection_cost.cost;
|
const double length = connection_cost.cost;
|
||||||
bool could_connect;
|
bool could_connect;
|
||||||
{
|
{
|
||||||
// cp1, cp2 sorted CCW.
|
// cp1, cp2 sorted CCW.
|
||||||
@ -2354,7 +2363,7 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
|
|
||||||
struct Arc {
|
struct Arc {
|
||||||
ContourIntersectionPoint* intersection;
|
ContourIntersectionPoint* intersection;
|
||||||
float arc_length;
|
double arc_length;
|
||||||
};
|
};
|
||||||
std::vector<Arc> arches;
|
std::vector<Arc> arches;
|
||||||
arches.reserve(map_infill_end_point_to_boundary.size());
|
arches.reserve(map_infill_end_point_to_boundary.size());
|
||||||
@ -2367,12 +2376,12 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
for (Arc& arc : arches)
|
for (Arc& arc : arches)
|
||||||
if (!arc.intersection->consumed && !arc.intersection->next_on_contour->consumed) {
|
if (!arc.intersection->consumed && !arc.intersection->next_on_contour->consumed) {
|
||||||
// Indices of the polylines to be connected by a perimeter segment.
|
// Indices of the polylines to be connected by a perimeter segment.
|
||||||
ContourIntersectionPoint* cp1 = arc.intersection;
|
ContourIntersectionPoint *cp1 = arc.intersection;
|
||||||
ContourIntersectionPoint* cp2 = arc.intersection->next_on_contour;
|
ContourIntersectionPoint *cp2 = arc.intersection->next_on_contour;
|
||||||
size_t polyline_idx1 = get_and_update_merged_with(((cp1 - map_infill_end_point_to_boundary.data()) / 2));
|
size_t polyline_idx1 = get_and_update_merged_with(((cp1 - map_infill_end_point_to_boundary.data()) / 2));
|
||||||
size_t polyline_idx2 = get_and_update_merged_with(((cp2 - map_infill_end_point_to_boundary.data()) / 2));
|
size_t polyline_idx2 = get_and_update_merged_with(((cp2 - map_infill_end_point_to_boundary.data()) / 2));
|
||||||
const Points& contour = boundary[cp1->contour_idx];
|
const Points &contour = boundary[cp1->contour_idx];
|
||||||
const std::vector<float>& contour_params = boundary_params[cp1->contour_idx];
|
const std::vector<double> &contour_params = boundary_params[cp1->contour_idx];
|
||||||
if (polyline_idx1 != polyline_idx2) {
|
if (polyline_idx1 != polyline_idx2) {
|
||||||
Polyline& polyline1 = infill_ordered[polyline_idx1];
|
Polyline& polyline1 = infill_ordered[polyline_idx1];
|
||||||
Polyline& polyline2 = infill_ordered[polyline_idx2];
|
Polyline& polyline2 = infill_ordered[polyline_idx2];
|
||||||
@ -2403,25 +2412,25 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect the remaining open infill lines to the perimeter lines if possible.
|
// Connect the remaining open infill lines to the perimeter lines if possible.
|
||||||
for (ContourIntersectionPoint& contour_point : map_infill_end_point_to_boundary)
|
for (ContourIntersectionPoint &contour_point : map_infill_end_point_to_boundary)
|
||||||
if (!contour_point.consumed && contour_point.contour_idx != boundary_idx_unconnected) {
|
if (! contour_point.consumed && contour_point.contour_idx != boundary_idx_unconnected) {
|
||||||
const Points& contour = boundary[contour_point.contour_idx];
|
const Points &contour = boundary[contour_point.contour_idx];
|
||||||
const std::vector<float>& contour_params = boundary_params[contour_point.contour_idx];
|
const std::vector<double> &contour_params = boundary_params[contour_point.contour_idx];
|
||||||
const size_t contour_pt_idx = contour_point.point_idx;
|
const size_t contour_pt_idx = contour_point.point_idx;
|
||||||
|
|
||||||
float lprev = contour_point.could_connect_prev() ?
|
double lprev = contour_point.could_connect_prev() ?
|
||||||
path_length_along_contour_ccw(contour_point.prev_on_contour, &contour_point, contour_params.back()) :
|
path_length_along_contour_ccw(contour_point.prev_on_contour, &contour_point, contour_params.back()) :
|
||||||
std::numeric_limits<float>::max();
|
std::numeric_limits<double>::max();
|
||||||
float lnext = contour_point.could_connect_next() ?
|
double lnext = contour_point.could_connect_next() ?
|
||||||
path_length_along_contour_ccw(&contour_point, contour_point.next_on_contour, contour_params.back()) :
|
path_length_along_contour_ccw(&contour_point, contour_point.next_on_contour, contour_params.back()) :
|
||||||
std::numeric_limits<float>::max();
|
std::numeric_limits<double>::max();
|
||||||
size_t polyline_idx = get_and_update_merged_with(((&contour_point - map_infill_end_point_to_boundary.data()) / 2));
|
size_t polyline_idx = get_and_update_merged_with(((&contour_point - map_infill_end_point_to_boundary.data()) / 2));
|
||||||
Polyline& polyline = infill_ordered[polyline_idx];
|
Polyline& polyline = infill_ordered[polyline_idx];
|
||||||
assert(!polyline.empty());
|
assert(!polyline.empty());
|
||||||
assert(contour[contour_point.point_idx] == polyline.points.front() || contour[contour_point.point_idx] == polyline.points.back());
|
assert(contour[contour_point.point_idx] == polyline.points.front() || contour[contour_point.point_idx] == polyline.points.back());
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
for (float l : { std::min(lprev, lnext), std::max(lprev, lnext) }) {
|
for (double l : { std::min(lprev, lnext), std::max(lprev, lnext) }) {
|
||||||
if (l == std::numeric_limits<float>::max() || l > anchor_length_max)
|
if (l == std::numeric_limits<double>::max() || l > anchor_length_max)
|
||||||
break;
|
break;
|
||||||
// Take the complete contour.
|
// Take the complete contour.
|
||||||
bool reversed = l == lprev;
|
bool reversed = l == lprev;
|
||||||
@ -2459,7 +2468,7 @@ void connect_infill(Polylines&& infill_ordered, const std::vector<const Polygon*
|
|||||||
// 2) Hook length
|
// 2) Hook length
|
||||||
// ...
|
// ...
|
||||||
// Let's take the longer now, as this improves the chance of another hook to be placed on the other side of this contour point.
|
// Let's take the longer now, as this improves the chance of another hook to be placed on the other side of this contour point.
|
||||||
float l = std::max(contour_point.contour_not_taken_length_prev, contour_point.contour_not_taken_length_next);
|
double l = std::max(contour_point.contour_not_taken_length_prev, contour_point.contour_not_taken_length_next);
|
||||||
if (l > SCALED_EPSILON) {
|
if (l > SCALED_EPSILON) {
|
||||||
if (contour_point.contour_not_taken_length_prev > contour_point.contour_not_taken_length_next)
|
if (contour_point.contour_not_taken_length_prev > contour_point.contour_not_taken_length_next)
|
||||||
take_limited(polyline, contour, contour_params, &contour_point, contour_point.prev_on_contour, true, anchor_length, line_half_width);
|
take_limited(polyline, contour, contour_params, &contour_point, contour_point.prev_on_contour, true, anchor_length, line_half_width);
|
||||||
|
@ -35,22 +35,22 @@ FillConcentric::_fill_surface_single(
|
|||||||
distance = scale_(this->get_spacing());
|
distance = scale_(this->get_spacing());
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons loops = (Polygons)expolygon;
|
Polygons loops = to_polygons(std::move(expolygon));
|
||||||
Polygons last = loops;
|
Polygons last = loops;
|
||||||
while (! last.empty()) {
|
while (! last.empty()) {
|
||||||
last = offset2(last, -double(distance + scale_(this->get_spacing()) /2), +double(scale_(this->get_spacing()) /2));
|
last = offset2(last, -double(distance + scale_(this->get_spacing()) /2), +double(scale_(this->get_spacing()) /2));
|
||||||
loops.insert(loops.end(), last.begin(), last.end());
|
append(loops, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate paths from the outermost to the innermost, to avoid
|
// generate paths from the outermost to the innermost, to avoid
|
||||||
// adhesion problems of the first central tiny loops
|
// adhesion problems of the first central tiny loops
|
||||||
loops = union_pt_chained(loops, false);
|
loops = union_pt_chained_outside_in(loops, false);
|
||||||
|
|
||||||
// split paths using a nearest neighbor search
|
// split paths using a nearest neighbor search
|
||||||
size_t iPathFirst = polylines_out.size();
|
size_t iPathFirst = polylines_out.size();
|
||||||
Point last_pos(0, 0);
|
Point last_pos(0, 0);
|
||||||
for (const Polygon &loop : loops) {
|
for (const Polygon &loop : loops) {
|
||||||
polylines_out.push_back(loop.split_at_index(last_pos.nearest_point_index(loop.points)));
|
polylines_out.emplace_back(loop.split_at_index(last_pos.nearest_point_index(loop.points)));
|
||||||
last_pos = polylines_out.back().last_point();
|
last_pos = polylines_out.back().last_point();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ namespace Slic3r {
|
|||||||
class FillConcentric : public Fill
|
class FillConcentric : public Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~FillConcentric() override {}
|
~FillConcentric() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill* clone() const override { return new FillConcentric(*this); };
|
Fill* clone() const override { return new FillConcentric(*this); };
|
||||||
|
@ -38,7 +38,7 @@ protected:
|
|||||||
|
|
||||||
bool _can_connect(coord_t dist_X, coord_t dist_Y) const
|
bool _can_connect(coord_t dist_X, coord_t dist_Y) const
|
||||||
{
|
{
|
||||||
coord_t TOLERANCE = 10 * SCALED_EPSILON;
|
const auto TOLERANCE = coord_t(10 * SCALED_EPSILON);
|
||||||
return (dist_X >= (this->_line_spacing - this->_line_oscillation) - TOLERANCE)
|
return (dist_X >= (this->_line_spacing - this->_line_oscillation) - TOLERANCE)
|
||||||
&& (dist_X <= (this->_line_spacing + this->_line_oscillation) + TOLERANCE)
|
&& (dist_X <= (this->_line_spacing + this->_line_oscillation) + TOLERANCE)
|
||||||
&& (dist_Y <= this->_diagonal_distance);
|
&& (dist_Y <= this->_diagonal_distance);
|
||||||
|
@ -58,59 +58,59 @@ const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_poin
|
|||||||
const std::string SLA_DRAIN_HOLES_FILE = "Metadata/Slic3r_PE_sla_drain_holes.txt";
|
const std::string SLA_DRAIN_HOLES_FILE = "Metadata/Slic3r_PE_sla_drain_holes.txt";
|
||||||
const std::string CUSTOM_GCODE_PER_PRINT_Z_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml";
|
const std::string CUSTOM_GCODE_PER_PRINT_Z_FILE = "Metadata/Prusa_Slicer_custom_gcode_per_print_z.xml";
|
||||||
|
|
||||||
static constexpr char* MODEL_TAG = "model";
|
static constexpr const char* MODEL_TAG = "model";
|
||||||
static constexpr char* RESOURCES_TAG = "resources";
|
static constexpr const char* RESOURCES_TAG = "resources";
|
||||||
static constexpr char* OBJECT_TAG = "object";
|
static constexpr const char* OBJECT_TAG = "object";
|
||||||
static constexpr char* MESH_TAG = "mesh";
|
static constexpr const char* MESH_TAG = "mesh";
|
||||||
static constexpr char* VERTICES_TAG = "vertices";
|
static constexpr const char* VERTICES_TAG = "vertices";
|
||||||
static constexpr char* VERTEX_TAG = "vertex";
|
static constexpr const char* VERTEX_TAG = "vertex";
|
||||||
static constexpr char* TRIANGLES_TAG = "triangles";
|
static constexpr const char* TRIANGLES_TAG = "triangles";
|
||||||
static constexpr char* TRIANGLE_TAG = "triangle";
|
static constexpr const char* TRIANGLE_TAG = "triangle";
|
||||||
static constexpr char* COMPONENTS_TAG = "components";
|
static constexpr const char* COMPONENTS_TAG = "components";
|
||||||
static constexpr char* COMPONENT_TAG = "component";
|
static constexpr const char* COMPONENT_TAG = "component";
|
||||||
static constexpr char* BUILD_TAG = "build";
|
static constexpr const char* BUILD_TAG = "build";
|
||||||
static constexpr char* ITEM_TAG = "item";
|
static constexpr const char* ITEM_TAG = "item";
|
||||||
static constexpr char* METADATA_TAG = "metadata";
|
static constexpr const char* METADATA_TAG = "metadata";
|
||||||
|
|
||||||
static constexpr char* CONFIG_TAG = "config";
|
static constexpr const char* CONFIG_TAG = "config";
|
||||||
static constexpr char* VOLUME_TAG = "volume";
|
static constexpr const char* VOLUME_TAG = "volume";
|
||||||
|
|
||||||
static constexpr char* UNIT_ATTR = "unit";
|
static constexpr const char* UNIT_ATTR = "unit";
|
||||||
static constexpr char* NAME_ATTR = "name";
|
static constexpr const char* NAME_ATTR = "name";
|
||||||
static constexpr char* TYPE_ATTR = "type";
|
static constexpr const char* TYPE_ATTR = "type";
|
||||||
static constexpr char* ID_ATTR = "id";
|
static constexpr const char* ID_ATTR = "id";
|
||||||
static constexpr char* X_ATTR = "x";
|
static constexpr const char* X_ATTR = "x";
|
||||||
static constexpr char* Y_ATTR = "y";
|
static constexpr const char* Y_ATTR = "y";
|
||||||
static constexpr char* Z_ATTR = "z";
|
static constexpr const char* Z_ATTR = "z";
|
||||||
static constexpr char* V1_ATTR = "v1";
|
static constexpr const char* V1_ATTR = "v1";
|
||||||
static constexpr char* V2_ATTR = "v2";
|
static constexpr const char* V2_ATTR = "v2";
|
||||||
static constexpr char* V3_ATTR = "v3";
|
static constexpr const char* V3_ATTR = "v3";
|
||||||
static constexpr char* OBJECTID_ATTR = "objectid";
|
static constexpr const char* OBJECTID_ATTR = "objectid";
|
||||||
static constexpr char* TRANSFORM_ATTR = "transform";
|
static constexpr const char* TRANSFORM_ATTR = "transform";
|
||||||
static constexpr char* PRINTABLE_ATTR = "printable";
|
static constexpr const char* PRINTABLE_ATTR = "printable";
|
||||||
static constexpr char* INSTANCESCOUNT_ATTR = "instances_count";
|
static constexpr const char* INSTANCESCOUNT_ATTR = "instances_count";
|
||||||
static constexpr char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";
|
static constexpr const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";
|
||||||
static constexpr char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam";
|
static constexpr const char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam";
|
||||||
|
|
||||||
static constexpr char* KEY_ATTR = "key";
|
static constexpr const char* KEY_ATTR = "key";
|
||||||
static constexpr char* VALUE_ATTR = "value";
|
static constexpr const char* VALUE_ATTR = "value";
|
||||||
static constexpr char* FIRST_TRIANGLE_ID_ATTR = "firstid";
|
static constexpr const char* FIRST_TRIANGLE_ID_ATTR = "firstid";
|
||||||
static constexpr char* LAST_TRIANGLE_ID_ATTR = "lastid";
|
static constexpr const char* LAST_TRIANGLE_ID_ATTR = "lastid";
|
||||||
|
|
||||||
static constexpr char* OBJECT_TYPE = "object";
|
static constexpr const char* OBJECT_TYPE = "object";
|
||||||
static constexpr char* VOLUME_TYPE = "volume";
|
static constexpr const char* VOLUME_TYPE = "volume";
|
||||||
|
|
||||||
static constexpr char* NAME_KEY = "name";
|
static constexpr const char* NAME_KEY = "name";
|
||||||
static constexpr char* MODIFIER_KEY = "modifier";
|
static constexpr const char* MODIFIER_KEY = "modifier";
|
||||||
static constexpr char* VOLUME_TYPE_KEY = "volume_type";
|
static constexpr const char* VOLUME_TYPE_KEY = "volume_type";
|
||||||
static constexpr char* MATRIX_KEY = "matrix";
|
static constexpr const char* MATRIX_KEY = "matrix";
|
||||||
static constexpr char* SOURCE_FILE_KEY = "source_file";
|
static constexpr const char* SOURCE_FILE_KEY = "source_file";
|
||||||
static constexpr char* SOURCE_OBJECT_ID_KEY = "source_object_id";
|
static constexpr const char* SOURCE_OBJECT_ID_KEY = "source_object_id";
|
||||||
static constexpr char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
|
static constexpr const char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
|
||||||
static constexpr char* SOURCE_OFFSET_X_KEY = "source_offset_x";
|
static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
|
||||||
static constexpr char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
|
static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
|
||||||
static constexpr char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
||||||
static constexpr char* SOURCE_IN_INCHES = "source_in_inches";
|
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
|
||||||
|
|
||||||
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
|
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
|
||||||
const char* VALID_OBJECT_TYPES[] =
|
const char* VALID_OBJECT_TYPES[] =
|
||||||
|
@ -2478,6 +2478,8 @@ void GCode::process_layer(
|
|||||||
instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, instance_to_print.object_by_extruder.support_extrusion_role));
|
instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, instance_to_print.object_by_extruder.support_extrusion_role));
|
||||||
m_layer = layers[instance_to_print.layer_id].layer();
|
m_layer = layers[instance_to_print.layer_id].layer();
|
||||||
}
|
}
|
||||||
|
//FIXME order islands?
|
||||||
|
// Sequential tool path ordering of multiple parts within the same object, aka. perimeter tracking (#5511)
|
||||||
for (ObjectByExtruder::Island &island : instance_to_print.object_by_extruder.islands) {
|
for (ObjectByExtruder::Island &island : instance_to_print.object_by_extruder.islands) {
|
||||||
const std::vector<ObjectByExtruder::Island::Region>& by_region_specific =
|
const std::vector<ObjectByExtruder::Island::Region>& by_region_specific =
|
||||||
is_anything_overridden ?
|
is_anything_overridden ?
|
||||||
|
@ -134,7 +134,7 @@ GCodeSender::set_baud_rate(unsigned int baud_rate)
|
|||||||
speed_t newSpeed = baud_rate;
|
speed_t newSpeed = baud_rate;
|
||||||
ioctl(handle, IOSSIOSPEED, &newSpeed);
|
ioctl(handle, IOSSIOSPEED, &newSpeed);
|
||||||
::tcsetattr(handle, TCSANOW, &ios);
|
::tcsetattr(handle, TCSANOW, &ios);
|
||||||
#elif __linux
|
#elif __linux__
|
||||||
termios2 ios;
|
termios2 ios;
|
||||||
if (ioctl(handle, TCGETS2, &ios))
|
if (ioctl(handle, TCGETS2, &ios))
|
||||||
printf("Error in TCGETS2: %s\n", strerror(errno));
|
printf("Error in TCGETS2: %s\n", strerror(errno));
|
||||||
|
@ -668,7 +668,7 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
|
|||||||
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
|
// If the file is loaded successfully, its print / filament / printer profiles will be activated.
|
||||||
void PresetBundle::load_config_file(const std::string &path)
|
void PresetBundle::load_config_file(const std::string &path)
|
||||||
{
|
{
|
||||||
if (boost::iends_with(path, ".gcode") || boost::iends_with(path, ".g")) {
|
if (is_gcode_file(path)) {
|
||||||
DynamicPrintConfig config;
|
DynamicPrintConfig config;
|
||||||
config.apply(FullPrintConfig::defaults());
|
config.apply(FullPrintConfig::defaults());
|
||||||
config.load_from_gcode_file(path);
|
config.load_from_gcode_file(path);
|
||||||
|
@ -2379,7 +2379,7 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//order path with least travel possible
|
//order path with least travel possible
|
||||||
loops = union_pt_chained(loops, false);
|
loops = union_pt_chained_outside_in(loops, false);
|
||||||
|
|
||||||
//create ear pattern
|
//create ear pattern
|
||||||
coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing());
|
coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing());
|
||||||
@ -2518,6 +2518,7 @@ void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects
|
|||||||
for (Polygon& poly : offset(islands_to_loops, 0.5f * double(flow.scaled_spacing())))
|
for (Polygon& poly : offset(islands_to_loops, 0.5f * double(flow.scaled_spacing())))
|
||||||
loops[i].emplace_back(poly);
|
loops[i].emplace_back(poly);
|
||||||
}
|
}
|
||||||
|
//loops = union_pt_chained_outside_in(loops, false);
|
||||||
std::reverse(loops.begin(), loops.end());
|
std::reverse(loops.begin(), loops.end());
|
||||||
|
|
||||||
//intersection
|
//intersection
|
||||||
|
@ -2610,7 +2610,7 @@ namespace Slic3r {
|
|||||||
layer->make_slices();
|
layer->make_slices();
|
||||||
//FIXME: can't make it work in multi-region object, it seems useful to avoid bridge on top of first layer compensation
|
//FIXME: can't make it work in multi-region object, it seems useful to avoid bridge on top of first layer compensation
|
||||||
//so it's disable, if you want an offset, use the offset field.
|
//so it's disable, if you want an offset, use the offset field.
|
||||||
//if (layer->regions().size() == 1 && layer_id == 0 && first_layer_compensation < 0 && m_config.raft_layers == 0) {
|
//if (layer->regions().size() == 1 && ! m_layers.empty() && layer_id == 0 && first_layer_compensation < 0 && m_config.raft_layers == 0) {
|
||||||
// // The Elephant foot has been compensated, therefore the 1st layer's lslices are shrank with the Elephant foot compensation value.
|
// // The Elephant foot has been compensated, therefore the 1st layer's lslices are shrank with the Elephant foot compensation value.
|
||||||
// // Store the uncompensated value there.
|
// // Store the uncompensated value there.
|
||||||
// assert(! m_layers.empty());
|
// assert(! m_layers.empty());
|
||||||
|
@ -45,9 +45,11 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
|||||||
m_cursor = Cursor(hit, source, radius, cursor_type, trafo);
|
m_cursor = Cursor(hit, source, radius, cursor_type, trafo);
|
||||||
|
|
||||||
// In case user changed cursor size since last time, update triangle edge limit.
|
// In case user changed cursor size since last time, update triangle edge limit.
|
||||||
if (m_old_cursor_radius != radius) {
|
// It is necessary to compare the internal radius in m_cursor! radius is in
|
||||||
set_edge_limit(radius / 5.f);
|
// world coords and does not change after scaling.
|
||||||
m_old_cursor_radius = radius;
|
if (m_old_cursor_radius_sqr != m_cursor.radius_sqr) {
|
||||||
|
set_edge_limit(std::sqrt(m_cursor.radius_sqr) / 5.f);
|
||||||
|
m_old_cursor_radius_sqr = m_cursor.radius_sqr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now start with the facet the pointer points to and check all adjacent facets.
|
// Now start with the facet the pointer points to and check all adjacent facets.
|
||||||
|
@ -146,7 +146,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Cursor m_cursor;
|
Cursor m_cursor;
|
||||||
float m_old_cursor_radius;
|
float m_old_cursor_radius_sqr;
|
||||||
|
|
||||||
// Private functions:
|
// Private functions:
|
||||||
bool select_triangle(int facet_idx, EnforcerBlockerType type,
|
bool select_triangle(int facet_idx, EnforcerBlockerType type,
|
||||||
|
@ -90,6 +90,7 @@ extern CopyFileResult check_copy(const std::string& origin, const std::string& c
|
|||||||
extern bool is_plain_file(const boost::filesystem::directory_entry &path);
|
extern bool is_plain_file(const boost::filesystem::directory_entry &path);
|
||||||
extern bool is_ini_file(const boost::filesystem::directory_entry &path);
|
extern bool is_ini_file(const boost::filesystem::directory_entry &path);
|
||||||
extern bool is_idx_file(const boost::filesystem::directory_entry &path);
|
extern bool is_idx_file(const boost::filesystem::directory_entry &path);
|
||||||
|
extern bool is_gcode_file(const std::string &path);
|
||||||
|
|
||||||
// File path / name / extension splitting utilities, working with UTF-8,
|
// File path / name / extension splitting utilities, working with UTF-8,
|
||||||
// to be published to Perl.
|
// to be published to Perl.
|
||||||
@ -358,8 +359,12 @@ inline std::string get_time_dhm(float time_in_secs)
|
|||||||
|
|
||||||
#if WIN32
|
#if WIN32
|
||||||
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
|
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
|
||||||
|
//FIXME this is an inprecise hack. Add the hash table size and possibly some estimate of the linked list at each of the used bin.
|
||||||
|
#define SLIC3R_STDUNORDEREDSET_MEMSIZE(NAME, TYPE) NAME.size() * ((sizeof(TYPE) + __alignof(TYPE) - 1) / __alignof(TYPE)) * __alignof(TYPE)
|
||||||
#else
|
#else
|
||||||
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
|
#define SLIC3R_STDVEC_MEMSIZE(NAME, TYPE) NAME.capacity() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
|
||||||
|
//FIXME this is an inprecise hack. Add the hash table size and possibly some estimate of the linked list at each of the used bin.
|
||||||
|
#define SLIC3R_STDUNORDEREDSET_MEMSIZE(NAME, TYPE) NAME.size() * ((sizeof(TYPE) + alignof(TYPE) - 1) / alignof(TYPE)) * alignof(TYPE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // slic3r_Utils_hpp_
|
#endif // slic3r_Utils_hpp_
|
||||||
|
@ -39,9 +39,9 @@
|
|||||||
|
|
||||||
#include <tbb/task_scheduler_init.h>
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
#if defined(__linux) || defined(__GNUC__ )
|
#if defined(__linux__) || defined(__GNUC__ )
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#endif /* __linux */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
@ -522,6 +522,12 @@ bool is_idx_file(const boost::filesystem::directory_entry &dir_entry)
|
|||||||
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".idx") == 0;
|
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".idx") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_gcode_file(const std::string &path)
|
||||||
|
{
|
||||||
|
return boost::iends_with(path, ".gcode") || boost::iends_with(path, ".gco") ||
|
||||||
|
boost::iends_with(path, ".g") || boost::iends_with(path, ".ngc");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -273,3 +273,12 @@ endif ()
|
|||||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||||
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# We need to implement some hacks for wxWidgets and touch the underlying GTK
|
||||||
|
# layer and sub-libraries. This forces us to use the include locations and
|
||||||
|
# link these libraries.
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
find_package(GTK${SLIC3R_GTK} REQUIRED)
|
||||||
|
target_include_directories(libslic3r_gui PRIVATE ${GTK${SLIC3R_GTK}_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(libslic3r_gui ${GTK${SLIC3R_GTK}_LIBRARIES})
|
||||||
|
endif ()
|
||||||
|
@ -612,7 +612,7 @@ struct _3DScene
|
|||||||
static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume);
|
static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume);
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr float BedEpsilon = float(EPSILON);
|
static constexpr float BedEpsilon = 3.f * float(EPSILON);
|
||||||
|
|
||||||
class ExtrusionToVert : public ExtrusionVisitorConst {
|
class ExtrusionToVert : public ExtrusionVisitorConst {
|
||||||
float print_z;
|
float print_z;
|
||||||
|
@ -151,9 +151,9 @@ void GCodeViewer::TBuffer::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// release cpu memory
|
// release cpu memory
|
||||||
indices = std::vector<IBuffer>();
|
indices.clear();
|
||||||
paths = std::vector<Path>();
|
paths.clear();
|
||||||
render_paths = std::vector<RenderPath>();
|
render_paths.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id)
|
void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id)
|
||||||
@ -798,9 +798,9 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
|||||||
unsigned int start_vertex_offset = buffer.start_segment_vertex_offset();
|
unsigned int start_vertex_offset = buffer.start_segment_vertex_offset();
|
||||||
unsigned int end_vertex_offset = buffer.end_segment_vertex_offset();
|
unsigned int end_vertex_offset = buffer.end_segment_vertex_offset();
|
||||||
|
|
||||||
for (size_t i = 0; i < buffer.render_paths.size(); ++i) {
|
size_t i = 0;
|
||||||
|
for (const RenderPath& render_path : buffer.render_paths) {
|
||||||
// get paths segments from buffer paths
|
// get paths segments from buffer paths
|
||||||
const RenderPath& render_path = buffer.render_paths[i];
|
|
||||||
const IndexBuffer& ibuffer = indices[render_path.index_buffer_id];
|
const IndexBuffer& ibuffer = indices[render_path.index_buffer_id];
|
||||||
const Path& path = buffer.paths[render_path.path_id];
|
const Path& path = buffer.paths[render_path.path_id];
|
||||||
float half_width = 0.5f * path.width;
|
float half_width = 0.5f * path.width;
|
||||||
@ -965,6 +965,8 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
|||||||
for (const Triangle& t : out_triangles) {
|
for (const Triangle& t : out_triangles) {
|
||||||
fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", t[0], t[0], t[1], t[1], t[2], t[2]);
|
fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", t[0], t[0], t[1], t[1], t[2], t[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++ i;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -1978,6 +1980,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// second pass: filter paths by sequential data and collect them by color
|
// second pass: filter paths by sequential data and collect them by color
|
||||||
|
RenderPath *render_path = nullptr;
|
||||||
for (const auto& [buffer, index_buffer_id, path_id] : paths) {
|
for (const auto& [buffer, index_buffer_id, path_id] : paths) {
|
||||||
const Path& path = buffer->paths[path_id];
|
const Path& path = buffer->paths[path_id];
|
||||||
if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first)
|
if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first)
|
||||||
@ -2008,16 +2011,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
|
|||||||
default: { color = { 0.0f, 0.0f, 0.0f }; break; }
|
default: { color = { 0.0f, 0.0f, 0.0f }; break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ibuffer_id = index_buffer_id;
|
RenderPath key{ color, static_cast<unsigned int>(index_buffer_id), path_id };
|
||||||
auto it = std::find_if(buffer->render_paths.begin(), buffer->render_paths.end(),
|
if (render_path == nullptr || ! RenderPathPropertyEqual()(*render_path, key))
|
||||||
[color, ibuffer_id](const RenderPath& path) { return path.index_buffer_id == ibuffer_id && path.color == color; });
|
render_path = const_cast<RenderPath*>(&(*buffer->render_paths.emplace(key).first));
|
||||||
if (it == buffer->render_paths.end()) {
|
|
||||||
it = buffer->render_paths.insert(buffer->render_paths.end(), RenderPath());
|
|
||||||
it->color = color;
|
|
||||||
it->path_id = path_id;
|
|
||||||
it->index_buffer_id = index_buffer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int segments_count = std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1;
|
unsigned int segments_count = std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1;
|
||||||
unsigned int size_in_indices = 0;
|
unsigned int size_in_indices = 0;
|
||||||
switch (buffer->render_primitive_type)
|
switch (buffer->render_primitive_type)
|
||||||
@ -2026,7 +2022,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
|
|||||||
case TBuffer::ERenderPrimitiveType::Line:
|
case TBuffer::ERenderPrimitiveType::Line:
|
||||||
case TBuffer::ERenderPrimitiveType::Triangle: { size_in_indices = buffer->indices_per_segment() * (segments_count - 1); break; }
|
case TBuffer::ERenderPrimitiveType::Triangle: { size_in_indices = buffer->indices_per_segment() * (segments_count - 1); break; }
|
||||||
}
|
}
|
||||||
it->sizes.push_back(size_in_indices);
|
render_path->sizes.push_back(size_in_indices);
|
||||||
|
|
||||||
unsigned int delta_1st = 0;
|
unsigned int delta_1st = 0;
|
||||||
if (path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= path.last.s_id)
|
if (path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= path.last.s_id)
|
||||||
@ -2035,7 +2031,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
|
|||||||
if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle)
|
if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle)
|
||||||
delta_1st *= buffer->indices_per_segment();
|
delta_1st *= buffer->indices_per_segment();
|
||||||
|
|
||||||
it->offsets.push_back(static_cast<size_t>((path.first.i_id + delta_1st) * sizeof(unsigned int)));
|
render_path->offsets.push_back(static_cast<size_t>((path.first.i_id + delta_1st) * sizeof(unsigned int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// set sequential data to their final value
|
// set sequential data to their final value
|
||||||
@ -3054,7 +3050,7 @@ void GCodeViewer::log_memory_used(const std::string& label, int64_t additional)
|
|||||||
int64_t render_paths_size = 0;
|
int64_t render_paths_size = 0;
|
||||||
for (const TBuffer& buffer : m_buffers) {
|
for (const TBuffer& buffer : m_buffers) {
|
||||||
paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path);
|
paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path);
|
||||||
render_paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.render_paths, RenderPath);
|
render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
|
||||||
for (const RenderPath& path : buffer.render_paths) {
|
for (const RenderPath& path : buffer.render_paths) {
|
||||||
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
|
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
|
||||||
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
|
render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -149,11 +151,35 @@ class GCodeViewer
|
|||||||
// Used to batch the indices needed to render paths
|
// Used to batch the indices needed to render paths
|
||||||
struct RenderPath
|
struct RenderPath
|
||||||
{
|
{
|
||||||
Color color;
|
// Render path property
|
||||||
unsigned int path_id;
|
Color color;
|
||||||
unsigned int index_buffer_id;
|
unsigned int index_buffer_id;
|
||||||
std::vector<unsigned int> sizes;
|
// Render path content
|
||||||
std::vector<size_t> offsets; // use size_t because we need an unsigned int whose size matches pointer's size (used in the call glMultiDrawElements())
|
unsigned int path_id;
|
||||||
|
std::vector<unsigned int> sizes;
|
||||||
|
std::vector<size_t> offsets; // use size_t because we need an unsigned int whose size matches pointer's size (used in the call glMultiDrawElements())
|
||||||
|
};
|
||||||
|
struct RenderPathPropertyHash {
|
||||||
|
size_t operator() (const RenderPath &p) const {
|
||||||
|
// Conver the RGB value to an integer hash.
|
||||||
|
// return (size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) * 7919) ^ size_t(p.index_buffer_id);
|
||||||
|
return size_t(int(p.color[0] * 255) + 255 * int(p.color[1] * 255) + (255 * 255) * int(p.color[2] * 255)) ^ size_t(p.index_buffer_id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct RenderPathPropertyLower {
|
||||||
|
bool operator() (const RenderPath &l, const RenderPath &r) const {
|
||||||
|
for (int i = 0; i < 3; ++ i)
|
||||||
|
if (l.color[i] < r.color[i])
|
||||||
|
return true;
|
||||||
|
else if (l.color[i] > r.color[i])
|
||||||
|
return false;
|
||||||
|
return l.index_buffer_id < r.index_buffer_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct RenderPathPropertyEqual {
|
||||||
|
bool operator() (const RenderPath &l, const RenderPath &r) const {
|
||||||
|
return l.color == r.color && l.index_buffer_id == r.index_buffer_id;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// buffer containing data for rendering a specific toolpath type
|
// buffer containing data for rendering a specific toolpath type
|
||||||
@ -172,7 +198,9 @@ class GCodeViewer
|
|||||||
|
|
||||||
std::string shader;
|
std::string shader;
|
||||||
std::vector<Path> paths;
|
std::vector<Path> paths;
|
||||||
std::vector<RenderPath> render_paths;
|
// std::set seems to perform singificantly better, at least on Windows.
|
||||||
|
// std::unordered_set<RenderPath, RenderPathPropertyHash, RenderPathPropertyEqual> render_paths;
|
||||||
|
std::set<RenderPath, RenderPathPropertyLower> render_paths;
|
||||||
bool visible{ false };
|
bool visible{ false };
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -1339,7 +1339,7 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
|
|||||||
{
|
{
|
||||||
for (GLVolume* vol : m_volumes.volumes) {
|
for (GLVolume* vol : m_volumes.volumes) {
|
||||||
if (vol->composite_id.object_id == 1000) { // wipe tower
|
if (vol->composite_id.object_id == 1000) { // wipe tower
|
||||||
vol->is_active = (visible && mo == nullptr);
|
vol->is_active = (visible && mo == nullptr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
|
if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
|
||||||
@ -3004,6 +3004,7 @@ void GLCanvas3D::on_render_timer(wxTimerEvent& evt)
|
|||||||
}
|
}
|
||||||
//render();
|
//render();
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
|
wxWakeUpIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::request_extra_frame_delayed(int miliseconds)
|
void GLCanvas3D::request_extra_frame_delayed(int miliseconds)
|
||||||
@ -4175,7 +4176,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
|||||||
custom_color[1] = clr.Green() / 255.f;
|
custom_color[1] = clr.Green() / 255.f;
|
||||||
custom_color[2] = clr.Blue() / 255.f;
|
custom_color[2] = clr.Blue() / 255.f;
|
||||||
}
|
}
|
||||||
for (const GLVolume* vol : visible_volumes)
|
for (GLVolume* vol : visible_volumes)
|
||||||
{
|
{
|
||||||
if (vol->printable && !vol->is_outside) {
|
if (vol->printable && !vol->is_outside) {
|
||||||
if (custom_color[0] < 0) {
|
if (custom_color[0] < 0) {
|
||||||
@ -4187,7 +4188,11 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
|||||||
} else {
|
} else {
|
||||||
shader->set_uniform("uniform_color", gray);
|
shader->set_uniform("uniform_color", gray);
|
||||||
}
|
}
|
||||||
|
// the volume may have been deactivated by an active gizmo
|
||||||
|
bool is_active = vol->is_active;
|
||||||
|
vol->is_active = true;
|
||||||
vol->render();
|
vol->render();
|
||||||
|
vol->is_active = is_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
@ -652,7 +652,6 @@ public:
|
|||||||
void set_toolpath_view_type(GCodeViewer::EViewType type);
|
void set_toolpath_view_type(GCodeViewer::EViewType type);
|
||||||
void set_volumes_z_range(const std::array<double, 2>& range);
|
void set_volumes_z_range(const std::array<double, 2>& range);
|
||||||
void set_toolpaths_z_range(const std::array<unsigned int, 2>& range);
|
void set_toolpaths_z_range(const std::array<unsigned int, 2>& range);
|
||||||
void set_toolpaths_range(double low, double high);
|
|
||||||
|
|
||||||
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
|
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);
|
||||||
std::vector<int> load_object(const Model& model, int obj_idx);
|
std::vector<int> load_object(const Model& model, int obj_idx);
|
||||||
|
@ -139,7 +139,7 @@ public:
|
|||||||
|
|
||||||
memDC.SetFont(m_action_font);
|
memDC.SetFont(m_action_font);
|
||||||
memDC.SetTextForeground(wxColour(0, 102, 255));
|
memDC.SetTextForeground(wxColour(0, 102, 255));
|
||||||
memDC.DrawText(text, int(m_scale * 60), int(m_scale * 275));
|
memDC.DrawText(text, int(m_scale * 60), m_action_line_y_position);
|
||||||
|
|
||||||
memDC.SelectObject(wxNullBitmap);
|
memDC.SelectObject(wxNullBitmap);
|
||||||
set_bitmap(bitmap);
|
set_bitmap(bitmap);
|
||||||
@ -214,14 +214,22 @@ public:
|
|||||||
|
|
||||||
memDc.SetFont(m_constant_text.version_font);
|
memDc.SetFont(m_constant_text.version_font);
|
||||||
memDc.DrawLabel(m_constant_text.version, banner_rect, wxALIGN_TOP | wxALIGN_LEFT);
|
memDc.DrawLabel(m_constant_text.version, banner_rect, wxALIGN_TOP | wxALIGN_LEFT);
|
||||||
|
int version_height = memDc.GetTextExtent(m_constant_text.version).GetY();
|
||||||
|
|
||||||
memDc.SetFont(m_constant_text.credits_font);
|
memDc.SetFont(m_constant_text.credits_font);
|
||||||
memDc.DrawLabel(m_constant_text.credits, banner_rect, wxALIGN_BOTTOM | wxALIGN_LEFT);
|
memDc.DrawLabel(m_constant_text.credits, banner_rect, wxALIGN_BOTTOM | wxALIGN_LEFT);
|
||||||
|
int credits_height = memDc.GetMultiLineTextExtent(m_constant_text.credits).GetY();
|
||||||
|
int text_height = memDc.GetTextExtent("text").GetY();
|
||||||
|
|
||||||
|
// calculate position for the dynamic text
|
||||||
|
int logo_and_header_height = margin + logo_size + title_height + version_height;
|
||||||
|
m_action_line_y_position = logo_and_header_height + 0.5 * (bmp.GetHeight() - margin - credits_height - logo_and_header_height - text_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxBitmap m_main_bitmap;
|
wxBitmap m_main_bitmap;
|
||||||
wxFont m_action_font;
|
wxFont m_action_font;
|
||||||
|
int m_action_line_y_position;
|
||||||
float m_scale {1.0};
|
float m_scale {1.0};
|
||||||
|
|
||||||
struct ConstantText
|
struct ConstantText
|
||||||
@ -265,7 +273,8 @@ private:
|
|||||||
float title_font_scale = (float)text_banner_width / GetTextExtent(m_constant_text.title).GetX();
|
float title_font_scale = (float)text_banner_width / GetTextExtent(m_constant_text.title).GetX();
|
||||||
scale_font(m_constant_text.title_font, title_font_scale > 3.5f ? 3.5f : title_font_scale);
|
scale_font(m_constant_text.title_font, title_font_scale > 3.5f ? 3.5f : title_font_scale);
|
||||||
|
|
||||||
scale_font(m_constant_text.version_font, 2.f);
|
float version_font_scale = (float)text_banner_width / GetTextExtent(m_constant_text.version).GetX();
|
||||||
|
scale_font(m_constant_text.version_font, version_font_scale > 2.f ? 2.f : version_font_scale);
|
||||||
|
|
||||||
// The width of the credits information string doesn't respect to the banner width some times.
|
// The width of the credits information string doesn't respect to the banner width some times.
|
||||||
// So, scale credits_font in the respect to the longest string width
|
// So, scale credits_font in the respect to the longest string width
|
||||||
@ -1945,11 +1954,9 @@ bool GUI_App::OnExceptionInMainLoop()
|
|||||||
void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
|
void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
|
||||||
{
|
{
|
||||||
size_t num_gcodes = 0;
|
size_t num_gcodes = 0;
|
||||||
for (const wxString &filename : fileNames) {
|
for (const wxString &filename : fileNames)
|
||||||
wxString fn = filename.Upper();
|
if (is_gcode_file(into_u8(filename)))
|
||||||
if (fn.EndsWith(".G") || fn.EndsWith(".GCODE"))
|
|
||||||
++ num_gcodes;
|
++ num_gcodes;
|
||||||
}
|
|
||||||
if (fileNames.size() == num_gcodes) {
|
if (fileNames.size() == num_gcodes) {
|
||||||
// Opening PrusaSlicer by drag & dropping a G-Code onto PrusaSlicer icon in Finder,
|
// Opening PrusaSlicer by drag & dropping a G-Code onto PrusaSlicer icon in Finder,
|
||||||
// just G-codes were passed. Switch to G-code viewer mode.
|
// just G-codes were passed. Switch to G-code viewer mode.
|
||||||
@ -1969,8 +1976,7 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
|||||||
std::vector<wxString> gcode_files;
|
std::vector<wxString> gcode_files;
|
||||||
std::vector<wxString> non_gcode_files;
|
std::vector<wxString> non_gcode_files;
|
||||||
for (const auto& filename : fileNames) {
|
for (const auto& filename : fileNames) {
|
||||||
wxString fn = filename.Upper();
|
if (is_gcode_file(into_u8(filename)))
|
||||||
if (fn.EndsWith(".G") || fn.EndsWith(".GCODE"))
|
|
||||||
gcode_files.emplace_back(filename);
|
gcode_files.emplace_back(filename);
|
||||||
else {
|
else {
|
||||||
files.emplace_back(into_u8(filename));
|
files.emplace_back(into_u8(filename));
|
||||||
|
@ -16,11 +16,26 @@
|
|||||||
#include <boost/nowide/iostream.hpp>
|
#include <boost/nowide/iostream.hpp>
|
||||||
#include <boost/nowide/convert.hpp>
|
#include <boost/nowide/convert.hpp>
|
||||||
|
|
||||||
|
#if __APPLE__
|
||||||
|
#include <signal.h>
|
||||||
|
#endif // __APPLE__
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
int GUI_Run(GUI_InitParams ¶ms)
|
int GUI_Run(GUI_InitParams ¶ms)
|
||||||
{
|
{
|
||||||
|
#if __APPLE__
|
||||||
|
// On OSX, we use boost::process::spawn() to launch new instances of PrusaSlicer from another PrusaSlicer.
|
||||||
|
// boost::process::spawn() sets SIGCHLD to SIGIGN for the child process, thus if a child PrusaSlicer spawns another
|
||||||
|
// subprocess and the subrocess dies, the child PrusaSlicer will not receive information on end of subprocess
|
||||||
|
// (posix waitpid() call will always fail).
|
||||||
|
// https://jmmv.dev/2008/10/boostprocess-and-sigchld.html
|
||||||
|
// The child instance of PrusaSlicer has to reset SIGCHLD to its default, so that posix waitpid() and similar continue to work.
|
||||||
|
// See GH issue #5507
|
||||||
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
#endif // __APPLE__
|
||||||
|
|
||||||
try {
|
try {
|
||||||
GUI::GUI_App* gui = new GUI::GUI_App(params.start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor);
|
GUI::GUI_App* gui = new GUI::GUI_App(params.start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor);
|
||||||
if (gui->get_app_mode() != GUI::GUI_App::EAppMode::GCodeViewer) {
|
if (gui->get_app_mode() != GUI::GUI_App::EAppMode::GCodeViewer) {
|
||||||
|
@ -1194,7 +1194,7 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||||||
**/
|
**/
|
||||||
m_prevent_list_events = true;//it's needed for GTK
|
m_prevent_list_events = true;//it's needed for GTK
|
||||||
|
|
||||||
/* Under GTK, DnD requires to the wxTextDataObject been initialized with some valid value,
|
/* Under GTK, DnD requires to the wxTextDataObject been initialized with some valid vaSome textlue,
|
||||||
* so set some nonempty string
|
* so set some nonempty string
|
||||||
*/
|
*/
|
||||||
wxTextDataObject* obj = new wxTextDataObject;
|
wxTextDataObject* obj = new wxTextDataObject;
|
||||||
@ -1226,8 +1226,10 @@ void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
|||||||
{
|
{
|
||||||
const wxDataViewItem& item = event.GetItem();
|
const wxDataViewItem& item = event.GetItem();
|
||||||
|
|
||||||
if (!can_drop(item))
|
if (!can_drop(item)) {
|
||||||
event.Veto();
|
event.Veto();
|
||||||
|
m_prevent_list_events = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectList::OnDrop(wxDataViewEvent &event)
|
void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||||
@ -1252,7 +1254,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||||||
// It looks like a fixed in current version of the wxWidgets
|
// It looks like a fixed in current version of the wxWidgets
|
||||||
// #ifdef __WXGTK__
|
// #ifdef __WXGTK__
|
||||||
// /* Under GTK, DnD moves an item between another two items.
|
// /* Under GTK, DnD moves an item between another two items.
|
||||||
// * And event.GetItem() return item, which is under "insertion line"
|
// * And event.GetItem() return item, which is under "insertion line"Some text
|
||||||
// * So, if we move item down we should to decrease the to_volume_id value
|
// * So, if we move item down we should to decrease the to_volume_id value
|
||||||
// **/
|
// **/
|
||||||
// if (to_volume_id > from_volume_id) to_volume_id--;
|
// if (to_volume_id > from_volume_id) to_volume_id--;
|
||||||
|
@ -401,7 +401,7 @@ void Preview::reload_print(bool keep_volumes)
|
|||||||
m_volumes_cleanup_required = !keep_volumes;
|
m_volumes_cleanup_required = !keep_volumes;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* __linux __ */
|
#endif /* __linux__ */
|
||||||
if (
|
if (
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
m_volumes_cleanup_required ||
|
m_volumes_cleanup_required ||
|
||||||
|
@ -252,14 +252,31 @@ namespace instance_check_internal
|
|||||||
|
|
||||||
bool instance_check(int argc, char** argv, bool app_config_single_instance)
|
bool instance_check(int argc, char** argv, bool app_config_single_instance)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
std::size_t hashed_path;
|
||||||
boost::system::error_code ec;
|
|
||||||
#endif
|
|
||||||
std::size_t hashed_path =
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
|
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
|
||||||
#else
|
#else
|
||||||
std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]), ec).string());
|
boost::system::error_code ec;
|
||||||
|
#ifdef __linux__
|
||||||
|
// If executed by an AppImage, start the AppImage, not the main process.
|
||||||
|
// see https://docs.appimage.org/packaging-guide/environment-variables.html#id2
|
||||||
|
const char *appimage_env = std::getenv("APPIMAGE");
|
||||||
|
bool appimage_env_valid = false;
|
||||||
|
if (appimage_env) {
|
||||||
|
try {
|
||||||
|
auto appimage_path = boost::filesystem::canonical(boost::filesystem::path(appimage_env));
|
||||||
|
if (boost::filesystem::exists(appimage_path)) {
|
||||||
|
hashed_path = std::hash<std::string>{}(appimage_path.string());
|
||||||
|
appimage_env_valid = true;
|
||||||
|
}
|
||||||
|
} catch (std::exception &) {
|
||||||
|
}
|
||||||
|
if (! appimage_env_valid)
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "APPIMAGE environment variable was set, but it does not point to a valid file: " << appimage_env;
|
||||||
|
}
|
||||||
|
if (! appimage_env_valid)
|
||||||
|
#endif // __linux__
|
||||||
|
hashed_path = std::hash<std::string>{}(boost::filesystem::canonical(boost::filesystem::system_complete(argv[0]), ec).string());
|
||||||
if (ec.value() > 0) { // canonical was not able to find the executable (can happen with appimage on some systems. Does it fail on Fuse file systems?)
|
if (ec.value() > 0) { // canonical was not able to find the executable (can happen with appimage on some systems. Does it fail on Fuse file systems?)
|
||||||
ec.clear();
|
ec.clear();
|
||||||
// Compose path with boost canonical of folder and filename
|
// Compose path with boost canonical of folder and filename
|
||||||
@ -269,7 +286,7 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance)
|
|||||||
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
|
hashed_path = std::hash<std::string>{}(boost::filesystem::system_complete(argv[0]).string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // win32
|
#endif // _WIN32
|
||||||
|
|
||||||
std::string lock_name = std::to_string(hashed_path);
|
std::string lock_name = std::to_string(hashed_path);
|
||||||
GUI::wxGetApp().set_instance_hash(hashed_path);
|
GUI::wxGetApp().set_instance_hash(hashed_path);
|
||||||
|
@ -73,9 +73,14 @@ void FillBedJob::prepare()
|
|||||||
// This is the maximum number of items, the real number will always be close but less.
|
// This is the maximum number of items, the real number will always be close but less.
|
||||||
int needed_items = (bed_area - fixed_area) / poly_area;
|
int needed_items = (bed_area - fixed_area) / poly_area;
|
||||||
|
|
||||||
ModelInstance *mi = model_object->instances[0];
|
int sel_id = m_plater->get_selection().get_instance_idx();
|
||||||
|
// if the selection is not a single instance, choose the first as template
|
||||||
|
sel_id = std::max(sel_id, 0);
|
||||||
|
ModelInstance *mi = model_object->instances[sel_id];
|
||||||
|
ArrangePolygon template_ap = get_arrange_poly(PtrWrapper{mi}, m_plater);
|
||||||
|
|
||||||
for (int i = 0; i < needed_items; ++i) {
|
for (int i = 0; i < needed_items; ++i) {
|
||||||
ArrangePolygon ap;
|
ArrangePolygon ap = template_ap;
|
||||||
ap.poly = m_selected.front().poly;
|
ap.poly = m_selected.front().poly;
|
||||||
ap.bed_idx = arrangement::UNARRANGED;
|
ap.bed_idx = arrangement::UNARRANGED;
|
||||||
ap.setter = [this, mi](const ArrangePolygon &p) {
|
ap.setter = [this, mi](const ArrangePolygon &p) {
|
||||||
|
@ -1235,11 +1235,11 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||||||
|
|
||||||
if (this->activate_existing(notification.get())) {
|
if (this->activate_existing(notification.get())) {
|
||||||
m_pop_notifications.back()->update(notification->get_data());
|
m_pop_notifications.back()->update(notification->get_data());
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame_delayed(33);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
m_pop_notifications.emplace_back(std::move(notification));
|
m_pop_notifications.emplace_back(std::move(notification));
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame_delayed(33);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1389,15 +1389,19 @@ void NotificationManager::update_notifications()
|
|||||||
if (!top_level_wnd->IsActive())
|
if (!top_level_wnd->IsActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static size_t last_size = m_pop_notifications.size();
|
//static size_t last_size = m_pop_notifications.size();
|
||||||
|
|
||||||
|
//request frames
|
||||||
|
int64_t next_render = std::numeric_limits<int64_t>::max();
|
||||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||||
std::unique_ptr<PopNotification>& notification = *it;
|
std::unique_ptr<PopNotification>& notification = *it;
|
||||||
|
notification->set_paused(m_hovered);
|
||||||
|
notification->update_state();
|
||||||
|
next_render = std::min<int64_t>(next_render, notification->next_render());
|
||||||
if (notification->get_state() == PopNotification::EState::Finished)
|
if (notification->get_state() == PopNotification::EState::Finished)
|
||||||
it = m_pop_notifications.erase(it);
|
it = m_pop_notifications.erase(it);
|
||||||
else {
|
else {
|
||||||
notification->set_paused(m_hovered);
|
|
||||||
notification->update_state();
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1438,16 +1442,11 @@ void NotificationManager::update_notifications()
|
|||||||
if (m_requires_render)
|
if (m_requires_render)
|
||||||
m_requires_update = true;
|
m_requires_update = true;
|
||||||
*/
|
*/
|
||||||
//request frames
|
|
||||||
int64_t next_render = std::numeric_limits<int64_t>::max();
|
|
||||||
const int64_t max = std::numeric_limits<int64_t>::max();
|
|
||||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
|
||||||
next_render = std::min<int64_t>(next_render, notification->next_render());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_render == 0)
|
if (next_render == 0)
|
||||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame_delayed(33); //few milliseconds to get from GLCanvas::render
|
||||||
else if (next_render < max)
|
else if (next_render < std::numeric_limits<int64_t>::max())
|
||||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame_delayed(int(next_render));
|
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame_delayed(int(next_render));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -585,7 +585,7 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (printer_name == m_default_name) {
|
if (printer_name == m_default_name) {
|
||||||
warning_catcher(this, _L("You should to change a name of your printer device. It can't be saved."));
|
warning_catcher(this, _L("You should change the name of your printer device."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3596,6 +3596,14 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
|||||||
*/
|
*/
|
||||||
wxGetApp().obj_list()->update_object_list_by_printer_technology();
|
wxGetApp().obj_list()->update_object_list_by_printer_technology();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// From the Win 2004 preset combobox lose a focus after change the preset selection
|
||||||
|
// and that is why the up/down arrow doesn't work properly
|
||||||
|
// (see https://github.com/prusa3d/PrusaSlicer/issues/5531 ).
|
||||||
|
// So, set the focus to the combobox explicitly
|
||||||
|
combo->SetFocus();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
||||||
@ -4885,9 +4893,7 @@ void Plater::load_gcode()
|
|||||||
|
|
||||||
void Plater::load_gcode(const wxString& filename)
|
void Plater::load_gcode(const wxString& filename)
|
||||||
{
|
{
|
||||||
if (filename.empty() ||
|
if (! is_gcode_file(into_u8(filename)) || m_last_loaded_gcode == filename)
|
||||||
(!filename.Lower().EndsWith(".gcode") && !filename.Lower().EndsWith(".g")) ||
|
|
||||||
m_last_loaded_gcode == filename)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_last_loaded_gcode = filename;
|
m_last_loaded_gcode = filename;
|
||||||
|
@ -32,6 +32,14 @@
|
|||||||
#include "PhysicalPrinterDialog.hpp"
|
#include "PhysicalPrinterDialog.hpp"
|
||||||
#include "SavePresetDialog.hpp"
|
#include "SavePresetDialog.hpp"
|
||||||
|
|
||||||
|
// A workaround for a set of issues related to text fitting into gtk widgets:
|
||||||
|
// See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584
|
||||||
|
#if defined(__WXGTK20__) || defined(__WXGTK3__)
|
||||||
|
#include <glib-2.0/glib-object.h>
|
||||||
|
#include <pango-1.0/pango/pango-layout.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using Slic3r::GUI::format_wxstr;
|
using Slic3r::GUI::format_wxstr;
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -179,6 +187,25 @@ void PresetComboBox::update_selection()
|
|||||||
|
|
||||||
SetSelection(m_last_selected);
|
SetSelection(m_last_selected);
|
||||||
SetToolTip(GetString(m_last_selected));
|
SetToolTip(GetString(m_last_selected));
|
||||||
|
|
||||||
|
// A workaround for a set of issues related to text fitting into gtk widgets:
|
||||||
|
// See e.g.: https://github.com/prusa3d/PrusaSlicer/issues/4584
|
||||||
|
#if defined(__WXGTK20__) || defined(__WXGTK3__)
|
||||||
|
GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_widget));
|
||||||
|
|
||||||
|
// 'cells' contains the GtkCellRendererPixBuf for the icon,
|
||||||
|
// 'cells->next' contains GtkCellRendererText for the text we need to ellipsize
|
||||||
|
if (!cells || !cells->next) return;
|
||||||
|
|
||||||
|
auto cell = static_cast<GtkCellRendererText *>(cells->next->data);
|
||||||
|
|
||||||
|
if (!cell) return;
|
||||||
|
|
||||||
|
g_object_set(G_OBJECT(cell), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||||
|
|
||||||
|
// Only the list of cells must be freed, the renderer isn't ours to free
|
||||||
|
g_list_free(cells);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PresetComboBox::update(std::string select_preset_name)
|
void PresetComboBox::update(std::string select_preset_name)
|
||||||
@ -905,6 +932,13 @@ TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
evt.StopPropagation();
|
evt.StopPropagation();
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
// From the Win 2004 preset combobox lose a focus after change the preset selection
|
||||||
|
// and that is why the up/down arrow doesn't work properly
|
||||||
|
// (see https://github.com/prusa3d/PrusaSlicer/issues/5531 ).
|
||||||
|
// So, set the focus to the combobox explicitly
|
||||||
|
this->SetFocus();
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,17 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr
|
|||||||
Fit();
|
Fit();
|
||||||
CenterOnParent();
|
CenterOnParent();
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
// On Linux with GTK2 when text control lose the focus then selection (colored background) disappears but text color stay white
|
||||||
|
// and as a result the text is invisible with light mode
|
||||||
|
// see https://github.com/prusa3d/PrusaSlicer/issues/4532
|
||||||
|
// Workaround: Unselect text selection explicitly on kill focus
|
||||||
|
txt_filename->Bind(wxEVT_KILL_FOCUS, [this](wxEvent& e) {
|
||||||
|
e.Skip();
|
||||||
|
txt_filename->SetInsertionPoint(txt_filename->GetLastPosition());
|
||||||
|
}, txt_filename->GetId());
|
||||||
|
#endif /* __linux__ */
|
||||||
|
|
||||||
Bind(wxEVT_SHOW, [=](const wxShowEvent &) {
|
Bind(wxEVT_SHOW, [=](const wxShowEvent &) {
|
||||||
// Another similar case where the function only works with EVT_SHOW + CallAfter,
|
// Another similar case where the function only works with EVT_SHOW + CallAfter,
|
||||||
// this time on Mac.
|
// this time on Mac.
|
||||||
|
@ -261,19 +261,31 @@ void RemovableDriveManager::eject_drive()
|
|||||||
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
||||||
this->update();
|
this->update();
|
||||||
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
||||||
|
#if __APPLE__
|
||||||
|
// If eject is still pending on the eject thread, wait until it finishes.
|
||||||
|
//FIXME while waiting for the eject thread to finish, the main thread is not pumping Cocoa messages, which may lead
|
||||||
|
// to blocking by the diskutil tool for a couple (up to 10) seconds. This is likely not critical, as the eject normally
|
||||||
|
// finishes quickly.
|
||||||
|
this->eject_thread_finish();
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
|
BOOST_LOG_TRIVIAL(info) << "Ejecting started";
|
||||||
|
|
||||||
tbb::mutex::scoped_lock lock(m_drives_mutex);
|
DriveData drive_data;
|
||||||
auto it_drive_data = this->find_last_save_path_drive_data();
|
{
|
||||||
if (it_drive_data != m_current_drives.end()) {
|
tbb::mutex::scoped_lock lock(m_drives_mutex);
|
||||||
std::string correct_path(m_last_save_path);
|
auto it_drive_data = this->find_last_save_path_drive_data();
|
||||||
#ifndef __APPLE__
|
if (it_drive_data == m_current_drives.end())
|
||||||
for (size_t i = 0; i < correct_path.size(); ++i)
|
return;
|
||||||
if (correct_path[i]==' ') {
|
drive_data = *it_drive_data;
|
||||||
correct_path = correct_path.insert(i,1,'\\');
|
}
|
||||||
++ i;
|
|
||||||
}
|
std::string correct_path(m_last_save_path);
|
||||||
|
#if __APPLE__
|
||||||
|
// On Apple, run the eject asynchronously on a worker thread, see the discussion at GH issue #4844.
|
||||||
|
m_eject_thread = new boost::thread([this, correct_path, drive_data]()
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
//std::cout<<"Ejecting "<<(*it).name<<" from "<< correct_path<<"\n";
|
//std::cout<<"Ejecting "<<(*it).name<<" from "<< correct_path<<"\n";
|
||||||
// there is no usable command in c++ so terminal command is used instead
|
// there is no usable command in c++ so terminal command is used instead
|
||||||
// but neither triggers "succesful safe removal messege"
|
// but neither triggers "succesful safe removal messege"
|
||||||
@ -296,31 +308,36 @@ void RemovableDriveManager::eject_drive()
|
|||||||
// wait for command to finnish (blocks ui thread)
|
// wait for command to finnish (blocks ui thread)
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
child.wait(ec);
|
child.wait(ec);
|
||||||
|
bool success = false;
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// The wait call can fail, as it did in https://github.com/prusa3d/PrusaSlicer/issues/5507
|
// The wait call can fail, as it did in https://github.com/prusa3d/PrusaSlicer/issues/5507
|
||||||
// It can happen even in cases where the eject is sucessful, but better report it as failed.
|
// It can happen even in cases where the eject is sucessful, but better report it as failed.
|
||||||
// We did not find a way to reliably retrieve the exit code of the process.
|
// We did not find a way to reliably retrieve the exit code of the process.
|
||||||
BOOST_LOG_TRIVIAL(error) << "boost::process::child::wait() failed during Ejection. State of Ejection is unknown. Error code: " << ec.value();
|
BOOST_LOG_TRIVIAL(error) << "boost::process::child::wait() failed during Ejection. State of Ejection is unknown. Error code: " << ec.value();
|
||||||
assert(m_callback_evt_handler);
|
} else {
|
||||||
if (m_callback_evt_handler)
|
int err = child.exit_code();
|
||||||
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
|
if (err) {
|
||||||
return;
|
BOOST_LOG_TRIVIAL(error) << "Ejecting failed. Exit code: " << err;
|
||||||
|
} else {
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Ejecting finished";
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int err = child.exit_code();
|
|
||||||
if (err) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "Ejecting failed. Exit code: " << err;
|
|
||||||
assert(m_callback_evt_handler);
|
|
||||||
if (m_callback_evt_handler)
|
|
||||||
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(*it_drive_data, false)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Ejecting finished";
|
|
||||||
|
|
||||||
assert(m_callback_evt_handler);
|
assert(m_callback_evt_handler);
|
||||||
if (m_callback_evt_handler)
|
if (m_callback_evt_handler)
|
||||||
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(std::move(*it_drive_data), true)));
|
wxPostEvent(m_callback_evt_handler, RemovableDriveEjectEvent(EVT_REMOVABLE_DRIVE_EJECTED, std::pair<DriveData, bool>(drive_data, success)));
|
||||||
m_current_drives.erase(it_drive_data);
|
if (success) {
|
||||||
|
// Remove the drive_data from m_current drives, searching by value, not by pointer, as m_current_drives may get modified during
|
||||||
|
// asynchronous execution on m_eject_thread.
|
||||||
|
tbb::mutex::scoped_lock lock(m_drives_mutex);
|
||||||
|
auto it = std::find(m_current_drives.begin(), m_current_drives.end(), drive_data);
|
||||||
|
if (it != m_current_drives.end())
|
||||||
|
m_current_drives.erase(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#if __APPLE__
|
||||||
|
);
|
||||||
|
#endif // __APPLE__
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RemovableDriveManager::get_removable_drive_path(const std::string &path)
|
std::string RemovableDriveManager::get_removable_drive_path(const std::string &path)
|
||||||
@ -382,7 +399,11 @@ void RemovableDriveManager::init(wxEvtHandler *callback_evt_handler)
|
|||||||
void RemovableDriveManager::shutdown()
|
void RemovableDriveManager::shutdown()
|
||||||
{
|
{
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
this->unregister_window_osx();
|
// If eject is still pending on the eject thread, wait until it finishes.
|
||||||
|
//FIXME while waiting for the eject thread to finish, the main thread is not pumping Cocoa messages, which may lead
|
||||||
|
// to blocking by the diskutil tool for a couple (up to 10) seconds. This is likely not critical, as the eject normally
|
||||||
|
// finishes quickly.
|
||||||
|
this->eject_thread_finish();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
||||||
@ -493,4 +514,15 @@ std::vector<DriveData>::const_iterator RemovableDriveManager::find_last_save_pat
|
|||||||
[this](const DriveData &data){ return data.path == m_last_save_path; });
|
[this](const DriveData &data){ return data.path == m_last_save_path; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __APPLE__
|
||||||
|
void RemovableDriveManager::eject_thread_finish()
|
||||||
|
{
|
||||||
|
if (m_eject_thread) {
|
||||||
|
m_eject_thread->join();
|
||||||
|
delete m_eject_thread;
|
||||||
|
m_eject_thread = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __APPLE__
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
@ -132,6 +132,8 @@ private:
|
|||||||
void eject_device(const std::string &path);
|
void eject_device(const std::string &path);
|
||||||
// Opaque pointer to RemovableDriveManagerMM
|
// Opaque pointer to RemovableDriveManagerMM
|
||||||
void *m_impl_osx;
|
void *m_impl_osx;
|
||||||
|
boost::thread *m_eject_thread { nullptr };
|
||||||
|
void eject_thread_finish();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -316,6 +316,13 @@ void Tab::create_preset_tab()
|
|||||||
// This helps to process all the cursor key events on Windows in the tree control,
|
// This helps to process all the cursor key events on Windows in the tree control,
|
||||||
// so that the cursor jumps to the last item.
|
// so that the cursor jumps to the last item.
|
||||||
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) {
|
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) {
|
||||||
|
#ifdef __linux__
|
||||||
|
// Events queue is opposite On Linux. wxEVT_SET_FOCUS invokes after wxEVT_TREE_SEL_CHANGED,
|
||||||
|
// and a result wxEVT_KILL_FOCUS doesn't invoke for the TextCtrls.
|
||||||
|
// see https://github.com/prusa3d/PrusaSlicer/issues/5720
|
||||||
|
// So, call SetFocus explicitly for this control before changing of the selection
|
||||||
|
m_treectrl->SetFocus();
|
||||||
|
#endif
|
||||||
if (!m_disable_tree_sel_changed_event && !m_pages.empty()) {
|
if (!m_disable_tree_sel_changed_event && !m_pages.empty()) {
|
||||||
if (m_page_switch_running)
|
if (m_page_switch_running)
|
||||||
m_page_switch_planned = true;
|
m_page_switch_planned = true;
|
||||||
@ -508,7 +515,7 @@ void Tab::update_labels_colour()
|
|||||||
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
|
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
|
||||||
opt.first == "compatible_prints" || opt.first == "compatible_printers" ) {
|
opt.first == "compatible_prints" || opt.first == "compatible_printers" ) {
|
||||||
if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end())
|
if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end())
|
||||||
*m_colored_Label_colors.at(opt.first) = *color;
|
m_colored_Label_colors.at(opt.first) = *color;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +554,7 @@ void Tab::decorate()
|
|||||||
|
|
||||||
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
|
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
|
||||||
opt.first == "compatible_prints" || opt.first == "compatible_printers")
|
opt.first == "compatible_prints" || opt.first == "compatible_printers")
|
||||||
colored_label_clr = (m_colored_Label_colors.find(opt.first) == m_colored_Label_colors.end()) ? nullptr : m_colored_Label_colors.at(opt.first);
|
colored_label_clr = (m_colored_Label_colors.find(opt.first) == m_colored_Label_colors.end()) ? nullptr : &m_colored_Label_colors.at(opt.first);
|
||||||
|
|
||||||
if (!colored_label_clr) {
|
if (!colored_label_clr) {
|
||||||
field = get_field(opt.first);
|
field = get_field(opt.first);
|
||||||
@ -3622,8 +3629,8 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin
|
|||||||
line.widget = widget;
|
line.widget = widget;
|
||||||
line.label_path = path;
|
line.label_path = path;
|
||||||
|
|
||||||
m_colored_Label_colors[opt_key] = &m_default_text_clr;
|
m_colored_Label_colors[opt_key] = m_default_text_clr;
|
||||||
line.full_Label_color = m_colored_Label_colors[opt_key];
|
line.full_Label_color = &m_colored_Label_colors[opt_key];
|
||||||
|
|
||||||
optgroup->append_line(line);
|
optgroup->append_line(line);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ public:
|
|||||||
|
|
||||||
// map of option name -> wxColour (color of the colored label, associated with option)
|
// map of option name -> wxColour (color of the colored label, associated with option)
|
||||||
// Used for options which don't have corresponded field
|
// Used for options which don't have corresponded field
|
||||||
std::map<std::string, wxColour*> m_colored_Label_colors;
|
std::map<std::string, wxColour> m_colored_Label_colors;
|
||||||
|
|
||||||
// Counter for the updating (because of an update() function can have a recursive behavior):
|
// Counter for the updating (because of an update() function can have a recursive behavior):
|
||||||
// 1. increase value from the very beginning of an update() function
|
// 1. increase value from the very beginning of an update() function
|
||||||
|
@ -78,6 +78,12 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
|
|||||||
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
|
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
|
||||||
args.emplace_back("--single-instance");
|
args.emplace_back("--single-instance");
|
||||||
boost::process::spawn(bin_path, args);
|
boost::process::spawn(bin_path, args);
|
||||||
|
// boost::process::spawn() sets SIGCHLD to SIGIGN for the child process, thus if a child PrusaSlicer spawns another
|
||||||
|
// subprocess and the subrocess dies, the child PrusaSlicer will not receive information on end of subprocess
|
||||||
|
// (posix waitpid() call will always fail).
|
||||||
|
// https://jmmv.dev/2008/10/boostprocess-and-sigchld.html
|
||||||
|
// The child instance of PrusaSlicer has to reset SIGCHLD to its default, so that posix waitpid() and similar continue to work.
|
||||||
|
// See GH issue #5507
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex) {
|
catch (const std::exception& ex) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << bin_path.string() << "\": " << ex.what();
|
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << bin_path.string() << "\": " << ex.what();
|
||||||
@ -87,7 +93,7 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
|
|||||||
{
|
{
|
||||||
std::vector<const char*> args;
|
std::vector<const char*> args;
|
||||||
args.reserve(3);
|
args.reserve(3);
|
||||||
#ifdef __linux
|
#ifdef __linux__
|
||||||
static const char* gcodeviewer_param = "--gcodeviewer";
|
static const char* gcodeviewer_param = "--gcodeviewer";
|
||||||
{
|
{
|
||||||
// If executed by an AppImage, start the AppImage, not the main process.
|
// If executed by an AppImage, start the AppImage, not the main process.
|
||||||
@ -99,7 +105,7 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
|
|||||||
args.emplace_back(gcodeviewer_param);
|
args.emplace_back(gcodeviewer_param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __linux
|
#endif // __linux__
|
||||||
std::string my_path;
|
std::string my_path;
|
||||||
if (args.empty()) {
|
if (args.empty()) {
|
||||||
// Binary path was not set to the AppImage in the Linux specific block above, call the application directly.
|
// Binary path was not set to the AppImage in the Linux specific block above, call the application directly.
|
||||||
|
@ -313,7 +313,7 @@ void Serial::set_baud_rate(unsigned baud_rate)
|
|||||||
speed_t newSpeed = baud_rate;
|
speed_t newSpeed = baud_rate;
|
||||||
handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed));
|
handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed));
|
||||||
handle_errno(::tcsetattr(handle, TCSANOW, &ios));
|
handle_errno(::tcsetattr(handle, TCSANOW, &ios));
|
||||||
#elif __linux
|
#elif __linux__
|
||||||
|
|
||||||
/* The following definitions are kindly borrowed from:
|
/* The following definitions are kindly borrowed from:
|
||||||
/usr/include/asm-generic/termbits.h
|
/usr/include/asm-generic/termbits.h
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
set(SLIC3R_APP_NAME "SuperSlicer")
|
set(SLIC3R_APP_NAME "SuperSlicer")
|
||||||
set(SLIC3R_APP_KEY "SuperSlicer")
|
set(SLIC3R_APP_KEY "SuperSlicer")
|
||||||
set(SLIC3R_VERSION "2.3.55")
|
set(SLIC3R_VERSION "2.3.55")
|
||||||
set(SLIC3R_VERSION_FULL "2.3.55.4")
|
set(SLIC3R_VERSION_FULL "2.3.55.5")
|
||||||
set(SLIC3R_BUILD_ID "SuperSlicer_${SLIC3R_VERSION_FULL}")
|
set(SLIC3R_BUILD_ID "SuperSlicer_${SLIC3R_VERSION_FULL}")
|
||||||
set(SLIC3R_RC_VERSION "2,3,55,4")
|
set(SLIC3R_RC_VERSION "2,3,55,5")
|
||||||
set(SLIC3R_RC_VERSION_DOTS "${SLIC3R_VERSION_FULL}")
|
set(SLIC3R_RC_VERSION_DOTS "${SLIC3R_VERSION_FULL}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user