Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer
|
@ -227,6 +227,9 @@ endif(WIN32)
|
|||
|
||||
add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO)
|
||||
|
||||
# Disable unsafe implicit wxString to const char* / std::string and vice versa. This implicit conversion breaks the UTF-8 encoding quite often.
|
||||
add_definitions(-DwxNO_UNSAFE_WXSTRING_CONV)
|
||||
|
||||
if (SLIC3R_PROFILE)
|
||||
message("PrusaSlicer will be built with a Shiny invasive profiler")
|
||||
add_definitions(-DSLIC3R_PROFILE)
|
||||
|
|
11
resources/icons/eject_sd.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 800 800" enable-background="new 0 0 800 800" xml:space="preserve">
|
||||
<path fill="#ED6B21" d="M594.8,558.94v71.52H205.95v-71.52H594.8 M627.56,502.24H173.18c-13.21,0-23.93,10.71-23.93,23.93v137.06
|
||||
c0,13.21,10.71,23.93,23.93,23.93h454.38c13.21,0,23.93-10.71,23.93-23.93V526.17C651.49,512.96,640.78,502.24,627.56,502.24
|
||||
L627.56,502.24z"/>
|
||||
<path fill="#ED6B21" d="M400.24,206.82l137.59,182.73H262.83L400.24,206.82 M400.23,128.4c-7.17,0-14.34,3.18-19.12,9.55
|
||||
L178.06,407.94c-11.86,15.77-0.61,38.31,19.12,38.31h406.34c19.74,0,30.99-22.55,19.11-38.32l-203.3-269.99
|
||||
C414.55,131.58,407.39,128.4,400.23,128.4L400.23,128.4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 899 B |
|
@ -1,168 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 3.7041666 3.7041667"
|
||||
height="3.7041667mm"
|
||||
width="3.7041667mm">
|
||||
<defs
|
||||
id="defs2">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3733">
|
||||
<path
|
||||
d="M 0,800 H 800 V 0 H 0 Z"
|
||||
id="path3731" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4697">
|
||||
<path
|
||||
d="M 0,800 H 800 V 0 H 0 Z"
|
||||
id="path4695" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4697-9">
|
||||
<path
|
||||
d="M 0,800 H 800 V 0 H 0 Z"
|
||||
id="path4695-2" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(294.04601,-97.736694)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="translate(-265.33929,12.851203)"
|
||||
id="layer1-0">
|
||||
<g
|
||||
transform="matrix(1.31769,0,0,1.31769,-167.28747,-111.35623)"
|
||||
id="layer1-3">
|
||||
<g
|
||||
id="g4685"
|
||||
transform="matrix(0.00352778,0,0,-0.00352778,105.26858,151.76571)">
|
||||
<path
|
||||
d="M 381.663,302.607 H 558.791 V 65.846 H 381.663 Z"
|
||||
style="fill:#d8d8db;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4687" />
|
||||
<path
|
||||
d="m 470.227,302.607 h 95.411 V 65.846 h -95.411 z"
|
||||
style="fill:#f7f7f8;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4689" />
|
||||
<g
|
||||
id="g4691">
|
||||
<g
|
||||
id="g4693"
|
||||
clip-path="url(#clipPath4697-9)">
|
||||
<g
|
||||
id="g4699"
|
||||
transform="translate(380.7793,225.1963)">
|
||||
<path
|
||||
d="m 0,0 h 174.037 c 39.032,0 70.675,31.643 70.675,70.675 v 372.92 c 0,39.033 -31.643,70.675 -70.675,70.675 H 0 c -39.033,0 -70.675,-31.642 -70.675,-70.675 V 70.675 C -70.675,31.643 -39.033,0 0,0"
|
||||
style="fill:#e96700;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4701" />
|
||||
</g>
|
||||
<g
|
||||
id="g4703"
|
||||
transform="translate(377.0244,168.7666)">
|
||||
<path
|
||||
d="m 0,0 h -237.865 c -8.782,0 -15.902,7.12 -15.902,15.902 v 365.743 c 0,8.782 7.12,15.901 15.902,15.901 H 28.933 c 8.782,0 15.902,-7.119 15.902,-15.901 V 56.43 C 38.907,48.507 9.055,8.503 0,0"
|
||||
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4705" />
|
||||
</g>
|
||||
<g
|
||||
id="g4707"
|
||||
transform="translate(421.8594,225.1963)">
|
||||
<path
|
||||
d="M 0,0 C -7.399,-10.049 -35.78,-47.927 -44.835,-56.43 H -282.7"
|
||||
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4709" />
|
||||
</g>
|
||||
<g
|
||||
id="g4711"
|
||||
transform="translate(421.8594,225.1963)">
|
||||
<path
|
||||
d="M 0,0 C -5.876,-7.899 -35.78,-47.927 -44.835,-56.43"
|
||||
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4713" />
|
||||
</g>
|
||||
<g
|
||||
id="g4715"
|
||||
transform="translate(333.957,198.1406)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 81.276 c 0,2.195 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.781 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4717" />
|
||||
</g>
|
||||
<g
|
||||
id="g4719"
|
||||
transform="translate(297.957,198.1406)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 81.276 c 0,2.195 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.781 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4721" />
|
||||
</g>
|
||||
<g
|
||||
id="g4723"
|
||||
transform="translate(261.957,198.1406)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 81.276 c 0,2.195 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.781 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4725" />
|
||||
</g>
|
||||
<g
|
||||
id="g4727"
|
||||
transform="translate(225.957,198.1406)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 81.276 c 0,2.195 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.781 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4729" />
|
||||
</g>
|
||||
<g
|
||||
id="g4731"
|
||||
transform="translate(189.957,198.1406)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 81.276 c 0,2.195 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.781 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4733" />
|
||||
</g>
|
||||
<g
|
||||
id="g4735"
|
||||
transform="translate(369.2207,225.1963)">
|
||||
<path
|
||||
d="m 0,0 h -22.969 c -2.196,0 -3.976,1.78 -3.976,3.976 v 54.22 c 0,2.196 1.78,3.976 3.976,3.976 H 0 c 2.196,0 3.976,-1.78 3.976,-3.976 V 3.976 C 3.976,1.78 2.196,0 0,0"
|
||||
style="fill:#efee86;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4737" />
|
||||
</g>
|
||||
<path
|
||||
d="m 450.019,104.056 h -50.577 v 33.128 h 50.577 z"
|
||||
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4739" />
|
||||
<path
|
||||
d="m 543.221,104.056 h -50.576 v 33.128 h 50.576 z"
|
||||
style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4741" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 800 800" enable-background="new 0 0 800 800" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#808080" d="M580.82,576.8H462.03v0c0,3.06-0.99,6.04-2.82,8.49l-0.49,0.65c-36.26,48.48-43.59,55.36-45.99,57.62
|
||||
c-1.47,1.38-3.2,2.4-5.06,3.04v89.54h88.56h88.56h6.85V575.98C588.11,576.52,584.5,576.8,580.82,576.8z M476.02,697.94h-50.58
|
||||
v-33.13h50.58V697.94z M569.22,697.94h-50.58v-33.13h50.58V697.94z"/>
|
||||
<path fill="#808080" d="M431.96,235.69h-266.8c-8.78,0-15.9,7.12-15.9,15.9v365.74c0,8.78,7.12,15.9,15.9,15.9h237.87
|
||||
c9.06-8.5,38.91-48.51,44.83-56.43V251.59C447.86,242.81,440.74,235.69,431.96,235.69z M219.93,599.88c0,2.2-1.78,3.98-3.98,3.98
|
||||
h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M255.93,599.88
|
||||
c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98
|
||||
V599.88z M291.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97
|
||||
c2.2,0,3.98,1.78,3.98,3.98V599.88z M327.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28
|
||||
c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M363.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97
|
||||
c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M399.2,572.83
|
||||
c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-54.22c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98
|
||||
V572.83z"/>
|
||||
<path fill="#ED6B21" d="M580.82,62.53H406.78c-39.03,0-70.67,31.64-70.67,70.67v88.31h95.85c16.58,0,30.08,13.49,30.08,30.08V576.8
|
||||
h118.78c39.03,0,70.67-31.64,70.67-70.67V133.21C651.49,94.18,619.85,62.53,580.82,62.53z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 2 KiB |
|
@ -1,25 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="support">
|
||||
<polygon fill="none" stroke="#808080" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="8,1
|
||||
2.31,4.79 2.31,8.57 2.31,8.79 2.31,10.47 8,14.25 13.69,10.47 13.69,8.79 13.69,8.57 13.69,4.79 "/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="12.69" y1="15" x2="12.69" y2="12.44"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="13.87" y1="15" x2="13.87" y2="11.64"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2.13" y1="15" x2="2.13" y2="11.64"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.33" y1="15" x2="3.33" y2="12.44"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="4.51" y1="15" x2="4.51" y2="13.22"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="5.66" y1="15" x2="5.66" y2="14"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="10.34" y1="15" x2="10.34" y2="14"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="11.5" y1="15" x2="11.5" y2="13.22"/>
|
||||
<g id="hollowing">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M9.73,13.27c-0.06-0.09-0.19-0.11-0.28-0.05l-1.28,0.85c-0.09,0.06-0.24,0.06-0.33,0l-1.28-0.85
|
||||
c-0.09-0.06-0.22-0.04-0.28,0.05L6.1,13.52c-0.06,0.09-0.04,0.21,0.05,0.27l1.68,1.12c0.09,0.06,0.24,0.06,0.33,0l1.68-1.12
|
||||
c0.09-0.06,0.11-0.18,0.05-0.27L9.73,13.27z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M8.17,1.14c-0.09-0.06-0.24-0.06-0.33,0L2.17,4.92C2.07,4.98,2,5.12,2,5.23v1.6c0,0.11,0,0.29,0,0.4v3.6
|
||||
c0,0.11,0.07,0.25,0.17,0.31l2.82,1.88c0.09,0.06,0.22,0.04,0.28-0.05l0.18-0.25c0.06-0.09,0.04-0.21-0.05-0.27l-2.52-1.68
|
||||
c-0.09-0.06-0.17-0.2-0.17-0.31V7.23c0-0.11,0-0.29,0-0.4V5.61c0-0.11,0.07-0.25,0.17-0.31l4.96-3.31c0.09-0.06,0.24-0.06,0.33,0
|
||||
l4.96,3.31c0.09,0.06,0.17,0.2,0.17,0.31v1.22c0,0.11,0,0.29,0,0.4v3.22c0,0.11-0.07,0.25-0.17,0.31l-2.52,1.68
|
||||
c-0.09,0.06-0.11,0.18-0.05,0.27l0.18,0.25c0.06,0.09,0.19,0.11,0.28,0.05l2.82-1.88c0.09-0.06,0.17-0.2,0.17-0.31v-3.6
|
||||
c0-0.11,0-0.29,0-0.4v-1.6c0-0.11-0.07-0.25-0.17-0.31L8.17,1.14z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M8.83,3.91c-0.07,0-0.14-0.02-0.2-0.06L8,3.43L7.37,3.85c-0.17,0.11-0.39,0.06-0.5-0.1
|
||||
c-0.11-0.17-0.06-0.39,0.1-0.5L7.8,2.7c0.12-0.08,0.28-0.08,0.4,0l0.83,0.55c0.17,0.11,0.21,0.33,0.1,0.5
|
||||
C9.06,3.85,8.95,3.91,8.83,3.91z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M3.69,7.23c-0.2,0-0.36-0.16-0.36-0.36v-1c0-0.12,0.06-0.23,0.16-0.3l0.83-0.55
|
||||
c0.17-0.11,0.39-0.06,0.5,0.1s0.06,0.39-0.1,0.5L4.05,6.06v0.81C4.05,7.07,3.89,7.23,3.69,7.23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M4.52,11.09c-0.07,0-0.14-0.02-0.2-0.06l-0.83-0.55c-0.1-0.07-0.16-0.18-0.16-0.3V9.19
|
||||
c0-0.2,0.16-0.36,0.36-0.36s0.36,0.16,0.36,0.36v0.8l0.67,0.44c0.17,0.11,0.21,0.33,0.1,0.5C4.75,11.03,4.64,11.09,4.52,11.09z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M8,13.42c-0.07,0-0.14-0.02-0.2-0.06l-0.83-0.55c-0.17-0.11-0.21-0.33-0.1-0.5s0.33-0.21,0.5-0.1L8,12.63
|
||||
l0.63-0.42c0.17-0.11,0.39-0.06,0.5,0.1s0.06,0.39-0.1,0.5L8.2,13.36C8.14,13.4,8.07,13.42,8,13.42z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M11.48,11.09c-0.12,0-0.23-0.06-0.3-0.16c-0.11-0.17-0.07-0.39,0.1-0.5l0.67-0.44v-0.8
|
||||
c0-0.2,0.16-0.36,0.36-0.36s0.36,0.16,0.36,0.36v0.99c0,0.12-0.06,0.23-0.16,0.3l-0.83,0.55C11.62,11.07,11.55,11.09,11.48,11.09
|
||||
z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M12.31,7.23c-0.2,0-0.36-0.16-0.36-0.36V6.06l-0.67-0.44c-0.17-0.11-0.21-0.33-0.1-0.5
|
||||
c0.11-0.17,0.33-0.21,0.5-0.1l0.83,0.55c0.1,0.07,0.16,0.18,0.16,0.3v1C12.67,7.07,12.51,7.23,12.31,7.23z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.8 KiB |
22
resources/icons/white/export_to_sd.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 800 800" enable-background="new 0 0 800 800" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M580.82,576.8H462.03v0c0,3.06-0.99,6.04-2.82,8.49l-0.49,0.65c-36.26,48.48-43.59,55.36-45.99,57.62
|
||||
c-1.47,1.38-3.2,2.4-5.06,3.04v89.54h88.56h88.56h6.85V575.98C588.11,576.52,584.5,576.8,580.82,576.8z M476.02,697.94h-50.58
|
||||
v-33.13h50.58V697.94z M569.22,697.94h-50.58v-33.13h50.58V697.94z"/>
|
||||
<path fill="#FFFFFF" d="M431.96,235.69h-266.8c-8.78,0-15.9,7.12-15.9,15.9v365.74c0,8.78,7.12,15.9,15.9,15.9h237.87
|
||||
c9.06-8.5,38.91-48.51,44.83-56.43V251.59C447.86,242.81,440.74,235.69,431.96,235.69z M219.93,599.88c0,2.2-1.78,3.98-3.98,3.98
|
||||
h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M255.93,599.88
|
||||
c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98
|
||||
V599.88z M291.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97
|
||||
c2.2,0,3.98,1.78,3.98,3.98V599.88z M327.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-81.28
|
||||
c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M363.93,599.88c0,2.2-1.78,3.98-3.98,3.98h-22.97
|
||||
c-2.2,0-3.98-1.78-3.98-3.98v-81.28c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98V599.88z M399.2,572.83
|
||||
c0,2.2-1.78,3.98-3.98,3.98h-22.97c-2.2,0-3.98-1.78-3.98-3.98v-54.22c0-2.2,1.78-3.98,3.98-3.98h22.97c2.2,0,3.98,1.78,3.98,3.98
|
||||
V572.83z"/>
|
||||
<path fill="#ED6B21" d="M580.82,62.53H406.78c-39.03,0-70.67,31.64-70.67,70.67v88.31h95.85c16.58,0,30.08,13.49,30.08,30.08V576.8
|
||||
h118.78c39.03,0,70.67-31.64,70.67-70.67V133.21C651.49,94.18,619.85,62.53,580.82,62.53z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -1,25 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="support">
|
||||
<polygon fill="none" stroke="#808080" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="8,1
|
||||
2.31,4.79 2.31,8.57 2.31,8.79 2.31,10.47 8,14.25 13.69,10.47 13.69,8.79 13.69,8.57 13.69,4.79 "/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="12.69" y1="15" x2="12.69" y2="12.44"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="13.87" y1="15" x2="13.87" y2="11.64"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2.13" y1="15" x2="2.13" y2="11.64"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="3.33" y1="15" x2="3.33" y2="12.44"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="4.51" y1="15" x2="4.51" y2="13.22"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="5.66" y1="15" x2="5.66" y2="14"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="10.34" y1="15" x2="10.34" y2="14"/>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="11.5" y1="15" x2="11.5" y2="13.22"/>
|
||||
<g id="hollowing">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M9.73,13.27c-0.06-0.09-0.19-0.11-0.28-0.05l-1.28,0.85c-0.09,0.06-0.24,0.06-0.33,0l-1.28-0.85
|
||||
c-0.09-0.06-0.22-0.04-0.28,0.05L6.1,13.52c-0.06,0.09-0.04,0.21,0.05,0.27l1.68,1.12c0.09,0.06,0.24,0.06,0.33,0l1.68-1.12
|
||||
c0.09-0.06,0.11-0.18,0.05-0.27L9.73,13.27z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M8.17,1.14c-0.09-0.06-0.24-0.06-0.33,0L2.17,4.92C2.07,4.98,2,5.12,2,5.23v1.6c0,0.11,0,0.29,0,0.4v3.6
|
||||
c0,0.11,0.07,0.25,0.17,0.31l2.82,1.88c0.09,0.06,0.22,0.04,0.28-0.05l0.18-0.25c0.06-0.09,0.04-0.21-0.05-0.27l-2.52-1.68
|
||||
c-0.09-0.06-0.17-0.2-0.17-0.31V7.23c0-0.11,0-0.29,0-0.4V5.61c0-0.11,0.07-0.25,0.17-0.31l4.96-3.31c0.09-0.06,0.24-0.06,0.33,0
|
||||
l4.96,3.31c0.09,0.06,0.17,0.2,0.17,0.31v1.22c0,0.11,0,0.29,0,0.4v3.22c0,0.11-0.07,0.25-0.17,0.31l-2.52,1.68
|
||||
c-0.09,0.06-0.11,0.18-0.05,0.27l0.18,0.25c0.06,0.09,0.19,0.11,0.28,0.05l2.82-1.88c0.09-0.06,0.17-0.2,0.17-0.31v-3.6
|
||||
c0-0.11,0-0.29,0-0.4v-1.6c0-0.11-0.07-0.25-0.17-0.31L8.17,1.14z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M8.83,3.91c-0.07,0-0.14-0.02-0.2-0.06L8,3.43L7.37,3.85c-0.17,0.11-0.39,0.06-0.5-0.1
|
||||
c-0.11-0.17-0.06-0.39,0.1-0.5L7.8,2.7c0.12-0.08,0.28-0.08,0.4,0l0.83,0.55c0.17,0.11,0.21,0.33,0.1,0.5
|
||||
C9.06,3.85,8.95,3.91,8.83,3.91z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M3.69,7.23c-0.2,0-0.36-0.16-0.36-0.36v-1c0-0.12,0.06-0.23,0.16-0.3l0.83-0.55
|
||||
c0.17-0.11,0.39-0.06,0.5,0.1s0.06,0.39-0.1,0.5L4.05,6.06v0.81C4.05,7.07,3.89,7.23,3.69,7.23z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M4.52,11.09c-0.07,0-0.14-0.02-0.2-0.06l-0.83-0.55c-0.1-0.07-0.16-0.18-0.16-0.3V9.19
|
||||
c0-0.2,0.16-0.36,0.36-0.36s0.36,0.16,0.36,0.36v0.8l0.67,0.44c0.17,0.11,0.21,0.33,0.1,0.5C4.75,11.03,4.64,11.09,4.52,11.09z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M8,13.42c-0.07,0-0.14-0.02-0.2-0.06l-0.83-0.55c-0.17-0.11-0.21-0.33-0.1-0.5s0.33-0.21,0.5-0.1L8,12.63
|
||||
l0.63-0.42c0.17-0.11,0.39-0.06,0.5,0.1s0.06,0.39-0.1,0.5L8.2,13.36C8.14,13.4,8.07,13.42,8,13.42z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M11.48,11.09c-0.12,0-0.23-0.06-0.3-0.16c-0.11-0.17-0.07-0.39,0.1-0.5l0.67-0.44v-0.8
|
||||
c0-0.2,0.16-0.36,0.36-0.36s0.36,0.16,0.36,0.36v0.99c0,0.12-0.06,0.23-0.16,0.3l-0.83,0.55C11.62,11.07,11.55,11.09,11.48,11.09
|
||||
z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M12.31,7.23c-0.2,0-0.36-0.16-0.36-0.36V6.06l-0.67-0.44c-0.17-0.11-0.21-0.33-0.1-0.5
|
||||
c0.11-0.17,0.33-0.21,0.5-0.1l0.83,0.55c0.1,0.07,0.16,0.18,0.16,0.3v1C12.67,7.07,12.51,7.23,12.31,7.23z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.8 KiB |
|
@ -1,4 +1,6 @@
|
|||
min_slic3r_version = 2.2.0-alpha3
|
||||
0.0.2 Updated for PrusaSlicer 2.2.0-rc
|
||||
0.0.2-beta Update for PrusaSlicer 2.2.0-beta
|
||||
0.0.2-alpha1 Extended list of default filaments to be installed
|
||||
0.0.2-alpha0 Print bed textures are now configurable from the Preset Bundle. Requires PrusaSlicer 2.2.0-alpha3 and newer.
|
||||
# The following line (max_slic3r_version) forces the users of PrusaSlicer 2.2.0-alpha3 and newer to update the profiles to 1.1.1-alpha3 and newer,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
name = Creality
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.0.2-alpha1
|
||||
config_version = 0.0.2
|
||||
# Where to get the updates from?
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
|
||||
# changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
min_slic3r_version = 2.2.0-alpha3
|
||||
1.1.1 Added Verbatim and Fiberlogy PETG filament profiles. Updated auto cooling settings for ABS.
|
||||
1.1.1-beta Updated for PrusaSlicer 2.2.0-beta
|
||||
1.1.1-alpha4 Extended list of default filaments to be installed, top/bottom_solid_min_thickness defined, infill_acceleration changed etc
|
||||
1.1.1-alpha3 Print bed textures are now configurable from the Preset Bundle. Requires PrusaSlicer 2.2.0-alpha3 and newer.
|
||||
# The following line (max_slic3r_version) forces the users of PrusaSlicer 2.2.0-alpha3 and newer to update the profiles to 1.1.1-alpha3 and newer,
|
||||
|
@ -8,6 +10,8 @@ min_slic3r_version = 2.2.0-alpha0
|
|||
1.1.1-alpha2 Bumped up config version, so our in house customer will get updated profiles.
|
||||
1.1.0 Filament aliases, Creality profiles and other goodies for PrusaSlicer 2.2.0-alpha0
|
||||
min_slic3r_version = 2.1.1-beta0
|
||||
1.0.8 Various changes in FFF profiles, new filaments/materials added. See changelog.
|
||||
1.0.7 Updated layer height limits for MINI
|
||||
1.0.6 Added Prusa MINI profiles
|
||||
min_slic3r_version = 2.1.0-alpha0
|
||||
1.0.5 Added SLA materials
|
||||
|
@ -118,4 +122,4 @@ min_slic3r_version = 1.40.0-alpha
|
|||
0.1.3 Fixed an incorrect position of the max_print_height parameter
|
||||
0.1.2 Wipe tower changes
|
||||
0.1.1 Minor print speed adjustments
|
||||
0.1.0 Initial
|
||||
0.1.0 Initial
|
|
@ -5,7 +5,7 @@
|
|||
name = Prusa Research
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 1.1.1-alpha4
|
||||
config_version = 1.1.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
|
||||
changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
|
@ -1538,12 +1538,12 @@ start_filament_gcode = "M900 K0 ; Filament gcode"
|
|||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
bed_temperature = 110
|
||||
bridge_fan_speed = 30
|
||||
bridge_fan_speed = 25
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 3
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #3A80CA
|
||||
filament_colour = #FFF2EC
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_type = ABS
|
||||
|
@ -1555,6 +1555,28 @@ temperature = 255
|
|||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}18{else}30{endif} ; Filament gcode"
|
||||
compatible_printers_condition = printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:*ABSC*]
|
||||
inherits = *common*
|
||||
bed_temperature = 110
|
||||
bridge_fan_speed = 25
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 4
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 20
|
||||
slowdown_below_layer_time = 20
|
||||
filament_colour = #FFF2EC
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_type = ABS
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 255
|
||||
max_fan_speed = 15
|
||||
min_fan_speed = 15
|
||||
min_print_speed = 15
|
||||
temperature = 255
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}18{else}30{endif} ; Filament gcode"
|
||||
compatible_printers_condition = printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:*FLEX*]
|
||||
inherits = *common*
|
||||
bed_temperature = 50
|
||||
|
@ -1744,7 +1766,7 @@ filament_cost = 25.4
|
|||
filament_density = 1.24
|
||||
|
||||
[filament:Fillamentum ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 32.4
|
||||
filament_density = 1.04
|
||||
|
@ -1827,25 +1849,25 @@ temperature = 220
|
|||
filament_retract_lift = 0.2
|
||||
|
||||
[filament:Generic ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Generic
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
|
||||
[filament:Esun ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Esun
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
|
||||
[filament:Hatchbox ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Hatchbox
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
|
||||
[filament:Plasty Mladec ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Plasty Mladec
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
|
@ -1867,7 +1889,6 @@ inherits = *PLA*
|
|||
filament_vendor = Generic
|
||||
filament_cost = 25.4
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:Generic FLEX]
|
||||
inherits = *FLEX*
|
||||
|
@ -1938,7 +1959,7 @@ filament_cost = 77.3
|
|||
filament_density = 1.20
|
||||
filament_type = PC
|
||||
bed_temperature = 115
|
||||
filament_colour = #3A80CA
|
||||
filament_colour = #FFF2EC
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 270
|
||||
temperature = 270
|
||||
|
@ -1954,7 +1975,6 @@ cooling = 0
|
|||
fan_always_on = 0
|
||||
filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 3.8
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'"
|
||||
filament_ramming_parameters = "120 100 8.3871 8.6129 8.93548 9.22581 9.48387 9.70968 9.87097 10.0323 10.2258 10.4194 10.6452 10.8065| 0.05 8.34193 0.45 8.73548 0.95 9.34836 1.45 9.78385 1.95 10.0871 2.45 10.5161 2.95 10.8903 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_type = PVA
|
||||
|
@ -1963,11 +1983,10 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/}0{elsi
|
|||
temperature = 195
|
||||
|
||||
[filament:Prusa ABS]
|
||||
inherits = *ABS*
|
||||
inherits = *ABSC*
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
|
||||
|
||||
[filament:*ABS MMU2*]
|
||||
inherits = Prusa ABS
|
||||
|
@ -1984,12 +2003,10 @@ filament_unloading_speed = 20
|
|||
|
||||
[filament:Generic ABS @MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
# alias = Generic ABS
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Prusament ASA @MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
# alias = Prusament ASA
|
||||
filament_vendor = Prusa Polymers
|
||||
filament_cost = 35.28
|
||||
filament_density = 1.07
|
||||
|
@ -2013,7 +2030,6 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{el
|
|||
|
||||
[filament:Prusa ABS @MMU2]
|
||||
inherits = *ABS MMU2*
|
||||
# alias = Prusa ABS
|
||||
filament_vendor = Made for Prusa
|
||||
|
||||
[filament:Plasty Mladec ABS @MMU2]
|
||||
|
@ -2027,7 +2043,7 @@ filament_cost = 27.3
|
|||
filament_density = 1.04
|
||||
bridge_fan_speed = 50
|
||||
cooling = 1
|
||||
extrusion_multiplier = 0.9
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 10
|
||||
filament_colour = #FFFFD7
|
||||
|
@ -2063,7 +2079,20 @@ inherits = *PET*
|
|||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PETG print settings:\n\nE3D Edge\nPlasty Mladec PETG"
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Verbatim PETG]
|
||||
inherits = *PET*
|
||||
filament_vendor = Verbatim
|
||||
filament_cost = 27.90
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Fiberlogy PETG]
|
||||
inherits = *PET*
|
||||
filament_vendor = Fiberlogy
|
||||
filament_cost = 21.50
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Prusament PETG]
|
||||
|
@ -2078,11 +2107,9 @@ compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2S
|
|||
|
||||
[filament:Prusa PETG @0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PETG print settings:\n\nE3D Edge\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Prusament PETG @0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
|
@ -2096,9 +2123,27 @@ filament_type = PETG
|
|||
[filament:Plasty Mladec PETG @0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
filament_vendor = Plasty Mladec
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_cost = 24.99
|
||||
first_layer_temperature = 230
|
||||
temperature = 240
|
||||
filament_cost = 27.92
|
||||
filament_density = 1.27
|
||||
filament_type = PETG
|
||||
|
||||
[filament:Verbatim PETG @0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
filament_vendor = Verbatim
|
||||
first_layer_temperature = 230
|
||||
temperature = 240
|
||||
filament_cost = 27.90
|
||||
filament_density = 1.27
|
||||
filament_type = PETG
|
||||
|
||||
[filament:Fiberlogy PETG @0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
filament_vendor = Fiberlogy
|
||||
first_layer_temperature = 230
|
||||
temperature = 240
|
||||
filament_cost = 21.50
|
||||
filament_density = 1.27
|
||||
filament_type = PETG
|
||||
|
||||
|
@ -2112,7 +2157,6 @@ filament_cooling_initial_speed = 2
|
|||
filament_cooling_moves = 1
|
||||
filament_load_time = 15
|
||||
filament_loading_speed = 14
|
||||
filament_notes = PET
|
||||
filament_ramming_parameters = "120 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_unload_time = 12
|
||||
filament_unloading_speed = 20
|
||||
|
@ -2128,7 +2172,6 @@ filament_max_volumetric_speed = 13
|
|||
|
||||
[filament:Generic PETG @MMU2]
|
||||
inherits = *PET MMU2*
|
||||
# alias = Generic PETG
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Plasty Mladec PETG @MMU2]
|
||||
|
@ -2137,35 +2180,29 @@ filament_vendor = Plasty Mladec
|
|||
|
||||
[filament:Prusa PETG @MMU2]
|
||||
inherits = *PET MMU2*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
|
||||
[filament:Prusament PETG @MMU2]
|
||||
inherits = *PET MMU2*
|
||||
filament_type = PETG
|
||||
# alias = Prusament PETG
|
||||
filament_vendor = Prusa Polymers
|
||||
|
||||
[filament:Generic PETG @MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
# alias = Generic PETG
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Prusa PETG @MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
|
||||
[filament:Prusament PETG @MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
filament_type = PETG
|
||||
# alias = Prusament PETG
|
||||
filament_vendor = Prusa Polymers
|
||||
|
||||
[filament:Plasty Mladec PETG @MMU2 0.6 nozzle]
|
||||
inherits = *PET MMU2 06*
|
||||
filament_type = PETG
|
||||
# alias = Prusament PETG
|
||||
filament_vendor = Plasty Mladec
|
||||
|
||||
[filament:Prusa PLA]
|
||||
|
@ -2321,7 +2358,6 @@ fan_always_on = 0
|
|||
fan_below_layer_time = 100
|
||||
filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH"
|
||||
filament_soluble = 1
|
||||
filament_type = PVA
|
||||
first_layer_bed_temperature = 60
|
||||
|
@ -2373,7 +2409,6 @@ filament_loading_speed = 14
|
|||
filament_loading_speed_start = 19
|
||||
filament_max_volumetric_speed = 3.8
|
||||
filament_minimal_purge_on_wipe_tower = 15
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+"
|
||||
filament_ramming_parameters = "120 110 3.83871 3.90323 3.96774 4.03226 4.09677 4.19355 4.3871 4.83871 5.67742 6.93548 8.54839 10.3226 11.9677 13.2581 14.129 14.5806| 0.05 3.8258 0.45 3.89676 0.95 4.05807 1.45 4.23548 1.95 5.18386 2.45 7.80651 2.95 11.5356 3.45 13.9872 3.95 14.7613 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_toolchange_delay = 0
|
||||
|
@ -2404,7 +2439,6 @@ fan_always_on = 1
|
|||
fan_below_layer_time = 100
|
||||
filament_colour = #DEE0E6
|
||||
filament_max_volumetric_speed = 5
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA"
|
||||
filament_type = PP
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 220
|
||||
|
@ -2445,7 +2479,6 @@ temperature = 270
|
|||
|
||||
[filament:ColorFabb XT-CF20 @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = ColorFabb XT-CF20
|
||||
filament_vendor = ColorFabb
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model=="MK2SMM"
|
||||
extrusion_multiplier = 1.2
|
||||
|
@ -2460,7 +2493,6 @@ temperature = 260
|
|||
|
||||
[filament:ColorFabb nGen @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = ColorFabb nGen
|
||||
filament_vendor = ColorFabb
|
||||
filament_cost = 21.2
|
||||
filament_density = 1.2
|
||||
|
@ -2474,16 +2506,13 @@ min_fan_speed = 20
|
|||
|
||||
[filament:E3D Edge @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = E3D Edge
|
||||
filament_vendor = E3D
|
||||
filament_cost = 56.9
|
||||
filament_density = 1.26
|
||||
filament_type = EDGE
|
||||
filament_notes = "List of manufacturers tested with standard PETG print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Fillamentum CPE @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Fillamentum CPE
|
||||
filament_vendor = Fillamentum
|
||||
filament_cost = 54.1
|
||||
filament_density = 1.25
|
||||
|
@ -2496,29 +2525,36 @@ temperature = 275
|
|||
|
||||
[filament:Generic PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Generic PETG
|
||||
filament_vendor = Generic
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
|
||||
[filament:Plasty Mladec PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Generic PETG
|
||||
filament_vendor = Plasty Mladec
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
|
||||
[filament:Verbatim PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_vendor = Verbatim
|
||||
filament_cost = 27.90
|
||||
filament_density = 1.27
|
||||
|
||||
[filament:Fiberlogy PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
filament_vendor = Fiberlogy
|
||||
filament_cost = 21.50
|
||||
filament_density = 1.27
|
||||
|
||||
[filament:Prusa PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PETG print settings:\n\nE3D Edge\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Prusament PETG @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Prusament PETG
|
||||
filament_vendor = Prusa Polymers
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
|
@ -2528,7 +2564,6 @@ filament_type = PETG
|
|||
|
||||
[filament:Taulman T-Glase @MMU1]
|
||||
inherits = *PETMMU1*
|
||||
# alias = Taulman T-Glase
|
||||
filament_vendor = Taulman
|
||||
filament_cost = 40
|
||||
filament_density = 1.27
|
||||
|
@ -2554,7 +2589,6 @@ compatible_printers_condition = printer_model=="MK2SMM"
|
|||
|
||||
[filament:Generic FLEX @MMU1]
|
||||
inherits = *FLEX*
|
||||
# alias = Generic FLEX
|
||||
filament_vendor = Generic
|
||||
filament_cost = 82
|
||||
filament_density = 1.22
|
||||
|
@ -2569,7 +2603,6 @@ compatible_printers_condition = printer_model=="MK2SMM"
|
|||
[filament:Generic PETG @MINI]
|
||||
inherits = Generic PETG; *PETMINI*
|
||||
filament_vendor = Generic
|
||||
# alias = Generic PETG
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
|
||||
|
@ -2581,35 +2614,79 @@ filament_cost = 27.82
|
|||
filament_density = 1.27
|
||||
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
|
||||
|
||||
[filament:Verbatim PETG @MINI]
|
||||
inherits = Generic PETG; *PETMINI*
|
||||
filament_vendor = Verbatim
|
||||
filament_cost = 27.90
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
|
||||
|
||||
[filament:Fiberlogy PETG @MINI]
|
||||
inherits = Generic PETG; *PETMINI*
|
||||
filament_vendor = Fiberlogy
|
||||
filament_cost = 21.50
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6
|
||||
|
||||
[filament:Generic ABS @MINI]
|
||||
inherits = Generic ABS; *ABSMINI*
|
||||
filament_vendor = Generic
|
||||
# alias = Generic ABS
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Esun ABS @MINI]
|
||||
inherits = Generic ABS; *ABSMINI*
|
||||
filament_vendor = Esun
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Hatchbox ABS @MINI]
|
||||
inherits = Generic ABS; *ABSMINI*
|
||||
filament_vendor = Hatchbox
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Plasty Mladec ABS @MINI]
|
||||
inherits = Generic ABS; *ABSMINI*
|
||||
filament_vendor = Plasty Mladec
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Prusament PETG @MINI]
|
||||
inherits = Prusament PETG; *PETMINI*
|
||||
filament_vendor = Prusa Polymers
|
||||
# alias = Prusament PETG
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_density = 1.27
|
||||
|
@ -2618,7 +2695,6 @@ compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.
|
|||
|
||||
[filament:Prusament PETG @0.6 nozzle MINI]
|
||||
inherits = Prusament PETG; *PETMINI06*
|
||||
# alias = Prusament PETG
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_density = 1.27
|
||||
|
@ -2626,16 +2702,21 @@ filament_cost = 24.99
|
|||
|
||||
[filament:Generic PETG @0.6 nozzle MINI]
|
||||
inherits = Generic PETG; *PETMINI06*
|
||||
# alias = Generic PETG
|
||||
|
||||
[filament:Plasty Mladec PETG @0.6 nozzle MINI]
|
||||
inherits = Generic PETG; *PETMINI06*
|
||||
filament_vendor = Plasty Mladec
|
||||
# alias = Generic PETG
|
||||
|
||||
[filament:Verbatim PETG @0.6 nozzle MINI]
|
||||
inherits = Generic PETG; *PETMINI06*
|
||||
filament_vendor = Verbatim
|
||||
|
||||
[filament:Fiberlogy PETG @0.6 nozzle MINI]
|
||||
inherits = Generic PETG; *PETMINI06*
|
||||
filament_vendor = Fiberlogy
|
||||
|
||||
[filament:Prusament ASA @MINI]
|
||||
inherits = Prusament ASA; *ABSMINI*
|
||||
# alias = Prusament ASA
|
||||
first_layer_temperature = 260
|
||||
first_layer_bed_temperature = 100
|
||||
temperature = 260
|
||||
|
@ -2654,7 +2735,6 @@ filament_density = 1.07
|
|||
|
||||
[filament:Fillamentum Flexfill 98A @MINI]
|
||||
inherits = SemiFlex or Flexfill 98A; *FLEXMINI*
|
||||
# alias = Fillamentum Flexfill 98A
|
||||
filament_vendor = Fillamentum
|
||||
first_layer_temperature = 240
|
||||
temperature = 240
|
||||
|
@ -2662,7 +2742,6 @@ filament_max_volumetric_speed = 1.35
|
|||
|
||||
[filament:Generic FLEX @MINI]
|
||||
inherits = SemiFlex or Flexfill 98A; *FLEXMINI*
|
||||
# alias = Semiflex or Flex 98A
|
||||
filament_vendor = Generic
|
||||
fan_always_on = 0
|
||||
bridge_fan_speed = 80
|
||||
|
@ -2673,7 +2752,6 @@ filament_max_volumetric_speed = 1.35
|
|||
|
||||
[filament:AmazonBasics TPU @MINI]
|
||||
inherits = *FLEXMINI*
|
||||
# alias = AmazonBasics TPU
|
||||
filament_vendor = AmazonBasics
|
||||
filament_max_volumetric_speed = 1.5
|
||||
first_layer_temperature = 235
|
||||
|
@ -2689,7 +2767,6 @@ filament_density = 1.21
|
|||
|
||||
[filament:SainSmart TPU @MINI]
|
||||
inherits = *FLEXMINI*
|
||||
# alias = SainSmart TPU
|
||||
filament_vendor = SainSmart
|
||||
filament_max_volumetric_speed = 1.8
|
||||
first_layer_temperature = 235
|
||||
|
@ -2708,7 +2785,6 @@ filament_density = 1.21
|
|||
|
||||
[filament:Filatech FilaFlex40 @MINI]
|
||||
inherits = *FLEXMINI*
|
||||
# alias = Filatech FilaFlex40
|
||||
filament_vendor = Filatech
|
||||
filament_max_volumetric_speed = 1.8
|
||||
fan_always_on = 1
|
||||
|
@ -2728,7 +2804,6 @@ filament_cost = 51.45
|
|||
|
||||
[filament:Fillamentum Flexfill 92A @MINI]
|
||||
inherits = *FLEXMINI*
|
||||
# alias = Fillamentum Flexfill 92A
|
||||
filament_vendor = Fillamentum
|
||||
first_layer_temperature = 245
|
||||
temperature = 245
|
||||
|
@ -2753,7 +2828,6 @@ start_filament_gcode = "M900 K0 ; Filament gcode"
|
|||
|
||||
[filament:Fillamentum CPE @MINI]
|
||||
inherits = Fillamentum CPE; *PETMINI*
|
||||
# alias = Fillamentum CPE
|
||||
first_layer_temperature = 265
|
||||
first_layer_bed_temperature = 90
|
||||
temperature = 265
|
||||
|
@ -2763,25 +2837,29 @@ filament_density = 1.25
|
|||
|
||||
[filament:ColorFabb nGen @MINI]
|
||||
inherits = ColorFabb nGen; *PETMINI*
|
||||
# alias = ColorFabb nGen
|
||||
filament_cost = 52.46
|
||||
filament_density = 1.2
|
||||
|
||||
[filament:E3D PC-ABS @MINI]
|
||||
inherits = E3D PC-ABS; *ABSMINI*
|
||||
# alias = E3D PC-ABS
|
||||
filament_density = 1.05
|
||||
filament_cost = 28.80
|
||||
|
||||
[filament:Fillamentum ABS @MINI]
|
||||
inherits = Fillamentum ABS; *ABSMINI*
|
||||
# alias = Fillamentum ABS
|
||||
filament_cost = 32.4
|
||||
filament_density = 1.04
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Fillamentum ASA @MINI]
|
||||
inherits = Fillamentum ASA; *ABSMINI*
|
||||
# alias = Fillamentum ASA
|
||||
first_layer_temperature = 255
|
||||
first_layer_bed_temperature = 100
|
||||
temperature = 255
|
||||
|
@ -2800,11 +2878,10 @@ filament_density = 1.07
|
|||
|
||||
[filament:Polymaker PC-Max @MINI]
|
||||
inherits = Polymaker PC-Max; *ABSMINI*
|
||||
# alias = Polymaker PC-Max
|
||||
filament_type = PC
|
||||
filament_max_volumetric_speed = 7
|
||||
bed_temperature = 100
|
||||
filament_colour = #3A80CA
|
||||
filament_colour = #FFF2EC
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 270
|
||||
temperature = 270
|
||||
|
@ -2814,14 +2891,20 @@ filament_density = 1.20
|
|||
|
||||
[filament:Prusa ABS @MINI]
|
||||
inherits = *ABSMINI*
|
||||
# alias = Prusa ABS
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
min_fan_speed = 15
|
||||
max_fan_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
disable_fan_first_layers = 4
|
||||
fan_below_layer_time = 20
|
||||
bridge_fan_speed = 25
|
||||
|
||||
[filament:Generic HIPS @MINI]
|
||||
inherits = *ABSMINI*
|
||||
# alias = Generic HIPS
|
||||
filament_vendor = Generic
|
||||
filament_cost = 27.3
|
||||
filament_density = 1.04
|
||||
|
@ -2840,7 +2923,6 @@ temperature = 230
|
|||
|
||||
[filament:ColorFabb HT @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = ColorFabb HT
|
||||
filament_vendor = ColorFabb
|
||||
bed_temperature = 100
|
||||
bridge_fan_speed = 30
|
||||
|
@ -2858,7 +2940,6 @@ temperature = 270
|
|||
|
||||
[filament:ColorFabb XT @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = ColorFabb XT
|
||||
filament_vendor = ColorFabb
|
||||
filament_type = PETG
|
||||
filament_cost = 62.9
|
||||
|
@ -2869,7 +2950,6 @@ temperature = 270
|
|||
|
||||
[filament:ColorFabb XT-CF20 @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = ColorFabb XT-CF20
|
||||
filament_vendor = ColorFabb
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_model=="MINI"
|
||||
extrusion_multiplier = 1.2
|
||||
|
@ -2883,7 +2963,6 @@ temperature = 260
|
|||
|
||||
[filament:Taulman T-Glase @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = Taulman T-Glase
|
||||
filament_vendor = Taulman
|
||||
filament_cost = 40
|
||||
filament_density = 1.27
|
||||
|
@ -2897,7 +2976,6 @@ min_fan_speed = 0
|
|||
|
||||
[filament:E3D Edge @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = E3D Edge
|
||||
filament_vendor = E3D
|
||||
filament_cost = 56.9
|
||||
filament_density = 1.26
|
||||
|
@ -2905,7 +2983,6 @@ filament_type = EDGE
|
|||
|
||||
[filament:Prusa PETG @MINI]
|
||||
inherits = *PETMINI*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
|
@ -2913,7 +2990,6 @@ compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.
|
|||
|
||||
[filament:Prusa PETG @0.6 nozzle MINI]
|
||||
inherits = *PETMINI06*
|
||||
# alias = Prusa PETG
|
||||
filament_vendor = Made for Prusa
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
|
|
|
@ -855,7 +855,12 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons)
|
|||
}
|
||||
|
||||
// Outer offset shall not split the input contour into multiples. It is expected, that the solution will be non empty and it will contain just a single polygon.
|
||||
ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
|
||||
ClipperLib::Paths fix_after_outer_offset(
|
||||
const ClipperLib::Path &input,
|
||||
// combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta)
|
||||
// to produce a CCW output contour from CCW input contour for a positive offset.
|
||||
ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive
|
||||
bool reverse_result) // = false
|
||||
{
|
||||
ClipperLib::Paths solution;
|
||||
if (! input.empty()) {
|
||||
|
@ -867,8 +872,13 @@ ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperL
|
|||
return solution;
|
||||
}
|
||||
|
||||
// Inner offset may split the source contour into multiple contours, but one shall not be inside the other.
|
||||
ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
|
||||
// Inner offset may split the source contour into multiple contours, but one resulting contour shall not lie inside the other.
|
||||
ClipperLib::Paths fix_after_inner_offset(
|
||||
const ClipperLib::Path &input,
|
||||
// combination of default prameters to correspond to void ClipperOffset::Execute(Paths& solution, double delta)
|
||||
// to produce a CCW output contour from CCW input contour for a negative offset.
|
||||
ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative
|
||||
bool reverse_result) // = true
|
||||
{
|
||||
ClipperLib::Paths solution;
|
||||
if (! input.empty()) {
|
||||
|
@ -1041,12 +1051,20 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v
|
|||
|
||||
// 1) Offset the outer contour.
|
||||
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true);
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : contours)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 2) Offset the holes one by one, collect the results.
|
||||
ClipperLib::Paths holes;
|
||||
holes.reserve(expoly.holes.size());
|
||||
for (const Polygon& hole : expoly.holes)
|
||||
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, false));
|
||||
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false));
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : holes)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
ClipperLib::Paths output;
|
||||
|
@ -1077,12 +1095,20 @@ for (const std::vector<float>& ds : deltas)
|
|||
|
||||
// 1) Offset the outer contour.
|
||||
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : contours)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 2) Offset the holes one by one, collect the results.
|
||||
ClipperLib::Paths holes;
|
||||
holes.reserve(expoly.holes.size());
|
||||
for (const Polygon& hole : expoly.holes)
|
||||
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : holes)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
ClipperLib::Paths output;
|
||||
|
@ -1113,12 +1139,20 @@ for (const std::vector<float>& ds : deltas)
|
|||
|
||||
// 1) Offset the outer contour.
|
||||
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : contours)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 2) Offset the holes one by one, collect the results.
|
||||
ClipperLib::Paths holes;
|
||||
holes.reserve(expoly.holes.size());
|
||||
for (const Polygon& hole : expoly.holes)
|
||||
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : holes)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
unscaleClipperPolygons(contours);
|
||||
|
@ -1152,13 +1186,21 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s
|
|||
#endif /* NDEBUG */
|
||||
|
||||
// 1) Offset the outer contour.
|
||||
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, false);
|
||||
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true);
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : contours)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 2) Offset the holes one by one, collect the results.
|
||||
ClipperLib::Paths holes;
|
||||
holes.reserve(expoly.holes.size());
|
||||
for (const Polygon& hole : expoly.holes)
|
||||
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, true));
|
||||
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, false));
|
||||
#ifndef NDEBUG
|
||||
for (auto &c : holes)
|
||||
assert(ClipperLib::Area(c) > 0.);
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// 3) Subtract holes from the contours.
|
||||
unscaleClipperPolygons(contours);
|
||||
|
|
|
@ -686,6 +686,7 @@ public:
|
|||
ConfigOption* clone() const override { return new ConfigOptionString(*this); }
|
||||
ConfigOptionString& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionString &rhs) const { return this->value == rhs.value; }
|
||||
bool empty() const { return this->value.empty(); }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
|
|
|
@ -13,6 +13,12 @@ static constexpr char ColorChangeCode[] = "M600";
|
|||
static constexpr char PausePrintCode[] = "M601";
|
||||
static constexpr char ToolChangeCode[] = "tool_change";
|
||||
|
||||
enum CustomGcodeType
|
||||
{
|
||||
cgtColorChange,
|
||||
cgtPausePrint,
|
||||
};
|
||||
|
||||
namespace CustomGCode {
|
||||
|
||||
struct Item
|
||||
|
|
|
@ -524,11 +524,22 @@ static inline void smooth_compensation_banded(const Points &contour, float band,
|
|||
}
|
||||
}
|
||||
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &external_perimeter_flow, const double compensation)
|
||||
#ifndef NDEBUG
|
||||
static bool validate_expoly_orientation(const ExPolygon &expoly)
|
||||
{
|
||||
bool valid = expoly.contour.is_counter_clockwise();
|
||||
for (auto &h : expoly.holes)
|
||||
valid &= h.is_clockwise();
|
||||
return valid;
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, double min_contour_width, const double compensation)
|
||||
{
|
||||
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
|
||||
double min_contour_width = double(external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing());
|
||||
assert(validate_expoly_orientation(input_expoly));
|
||||
|
||||
double scaled_compensation = scale_(compensation);
|
||||
min_contour_width = scale_(min_contour_width);
|
||||
double min_contour_width_compensated = min_contour_width + 2. * scaled_compensation;
|
||||
// Make the search radius a bit larger for the averaging in contour_distance over a fan of rays to work.
|
||||
double search_radius = min_contour_width_compensated + min_contour_width * 0.5;
|
||||
|
@ -547,6 +558,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
|
|||
{
|
||||
EdgeGrid::Grid grid;
|
||||
ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front();
|
||||
assert(validate_expoly_orientation(simplified));
|
||||
BoundingBox bbox = get_extents(simplified.contour);
|
||||
bbox.offset(SCALED_EPSILON);
|
||||
grid.set_bbox(bbox);
|
||||
|
@ -559,6 +571,7 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
|
|||
Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1];
|
||||
std::vector<ResampledPoint> resampled_point_parameters;
|
||||
poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters);
|
||||
assert(poly.is_counter_clockwise() == (idx_contour == 0));
|
||||
std::vector<float> dists = contour_distance2(grid, idx_contour, poly.points, resampled_point_parameters, scaled_compensation, search_radius);
|
||||
for (float &d : dists) {
|
||||
// printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d));
|
||||
|
@ -593,10 +606,18 @@ ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &
|
|||
assert(out_vec.size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert(validate_expoly_orientation(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input, const Flow &external_perimeter_flow, const double compensation)
|
||||
{
|
||||
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
|
||||
double min_contour_width = double(external_perimeter_flow.width + external_perimeter_flow.spacing());
|
||||
return elephant_foot_compensation(input, min_contour_width, compensation);
|
||||
}
|
||||
|
||||
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation)
|
||||
{
|
||||
ExPolygons out;
|
||||
|
@ -606,4 +627,13 @@ ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &exter
|
|||
return out;
|
||||
}
|
||||
|
||||
ExPolygons elephant_foot_compensation(const ExPolygons &input, double min_contour_width, const double compensation)
|
||||
{
|
||||
ExPolygons out;
|
||||
out.reserve(input.size());
|
||||
for (const ExPolygon &expoly : input)
|
||||
out.emplace_back(elephant_foot_compensation(expoly, min_contour_width, compensation));
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -8,6 +8,8 @@ namespace Slic3r {
|
|||
|
||||
class Flow;
|
||||
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input, double min_countour_width, const double compensation);
|
||||
ExPolygons elephant_foot_compensation(const ExPolygons &input, double min_countour_width, const double compensation);
|
||||
ExPolygon elephant_foot_compensation(const ExPolygon &input, const Flow &external_perimeter_flow, const double compensation);
|
||||
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation);
|
||||
|
||||
|
|
|
@ -11,18 +11,10 @@ void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities,
|
|||
if (role != erMixed) {
|
||||
auto first = extrusion_entities.begin();
|
||||
auto last = extrusion_entities.end();
|
||||
auto result = first;
|
||||
while (first != last) {
|
||||
// The caller wants only paths with a specific extrusion role.
|
||||
auto role2 = (*first)->role();
|
||||
if (role != role2) {
|
||||
// This extrusion entity does not match the role asked.
|
||||
assert(role2 != erMixed);
|
||||
*result = *first;
|
||||
++ result;
|
||||
}
|
||||
++ first;
|
||||
}
|
||||
extrusion_entities.erase(
|
||||
std::remove_if(first, last, [&role](const ExtrusionEntity* ee) {
|
||||
return ee->role() != role; }),
|
||||
last);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
FlowErrorNegativeSpacing::FlowErrorNegativeSpacing() :
|
||||
FlowError("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?") {}
|
||||
|
||||
FlowErrorNegativeFlow::FlowErrorNegativeFlow() :
|
||||
FlowError("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?") {}
|
||||
|
||||
// This static method returns a sane extrusion width default.
|
||||
float Flow::auto_extrusion_width(FlowRole role, float nozzle_diameter)
|
||||
{
|
||||
|
@ -52,7 +58,7 @@ static inline FlowRole opt_key_to_flow_role(const std::string &opt_key)
|
|||
|
||||
static inline void throw_on_missing_variable(const std::string &opt_key, const char *dependent_opt_key)
|
||||
{
|
||||
throw std::runtime_error((boost::format(L("Cannot calculate extrusion width for %1%: Variable \"%2%\" not accessible.")) % opt_key % dependent_opt_key).str());
|
||||
throw FlowErrorMissingVariable((boost::format(L("Cannot calculate extrusion width for %1%: Variable \"%2%\" not accessible.")) % opt_key % dependent_opt_key).str());
|
||||
}
|
||||
|
||||
// Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser.
|
||||
|
@ -174,7 +180,7 @@ float Flow::spacing() const
|
|||
#endif
|
||||
// assert(res > 0.f);
|
||||
if (res <= 0.f)
|
||||
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
|
||||
throw FlowErrorNegativeSpacing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -190,7 +196,7 @@ float Flow::spacing(const Flow &other) const
|
|||
0.5 * this->spacing() + 0.5 * other.spacing());
|
||||
// assert(res > 0.f);
|
||||
if (res <= 0.f)
|
||||
throw std::runtime_error("Flow::spacing() produced negative spacing. Did you set some extrusion width too small?");
|
||||
throw FlowErrorNegativeSpacing();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -204,7 +210,7 @@ double Flow::mm3_per_mm() const
|
|||
float(this->height * (this->width - this->height * (1. - 0.25 * PI)));
|
||||
//assert(res > 0.);
|
||||
if (res <= 0.)
|
||||
throw std::runtime_error("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?");
|
||||
throw FlowErrorNegativeFlow();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,31 @@ enum FlowRole {
|
|||
frSupportMaterialInterface,
|
||||
};
|
||||
|
||||
class FlowError : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
FlowError(const std::string& what_arg) : invalid_argument(what_arg) {}
|
||||
FlowError(const char* what_arg) : invalid_argument(what_arg) {}
|
||||
};
|
||||
|
||||
class FlowErrorNegativeSpacing : public FlowError
|
||||
{
|
||||
public:
|
||||
FlowErrorNegativeSpacing();
|
||||
};
|
||||
|
||||
class FlowErrorNegativeFlow : public FlowError
|
||||
{
|
||||
public:
|
||||
FlowErrorNegativeFlow();
|
||||
};
|
||||
|
||||
class FlowErrorMissingVariable : public FlowError
|
||||
{
|
||||
public:
|
||||
FlowErrorMissingVariable(const std::string& what_arg) : FlowError(what_arg) {}
|
||||
};
|
||||
|
||||
class Flow
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1060,9 +1060,9 @@ namespace DoExport {
|
|||
print_statistics.clear();
|
||||
print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/();
|
||||
print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A";
|
||||
print_statistics.estimated_normal_color_print_times = normal_time_estimator.get_color_times_dhms(true);
|
||||
print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true);
|
||||
if (silent_time_estimator_enabled)
|
||||
print_statistics.estimated_silent_color_print_times = silent_time_estimator.get_color_times_dhms(true);
|
||||
print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true);
|
||||
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
|
||||
if (! extruders.empty()) {
|
||||
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||
|
@ -1104,11 +1104,11 @@ namespace DoExport {
|
|||
print_statistics.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.;
|
||||
}
|
||||
filament_stats_string_out += out_filament_used_mm.first;
|
||||
filament_stats_string_out += out_filament_used_cm3.first;
|
||||
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||
if (out_filament_used_g.second)
|
||||
filament_stats_string_out += out_filament_used_g.first;
|
||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||
if (out_filament_cost.second)
|
||||
filament_stats_string_out += out_filament_cost.first;
|
||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||
}
|
||||
return filament_stats_string_out;
|
||||
}
|
||||
|
@ -1550,6 +1550,7 @@ void GCode::_do_export(Print& print, FILE* file)
|
|||
m_writer.extruders(),
|
||||
// Modifies
|
||||
print.m_print_statistics));
|
||||
_write(file, "\n");
|
||||
_write_format(file, "; total filament used [g] = %.1lf\n", print.m_print_statistics.total_weight);
|
||||
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost);
|
||||
if (print.m_print_statistics.total_toolchanges > 0)
|
||||
|
@ -1852,7 +1853,7 @@ namespace ProcessLayer
|
|||
if (!pause_print_msg.empty())
|
||||
gcode += "M117 " + pause_print_msg + "\n";
|
||||
// add tag for time estimator
|
||||
//gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n";
|
||||
gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n";
|
||||
}
|
||||
else // custom Gcode
|
||||
{
|
||||
|
@ -3436,7 +3437,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
|||
if (this_override == nullptr || (*this_override)[copy] == -int(extruder)-1)
|
||||
target_eec.emplace_back(entities[i]);
|
||||
}
|
||||
for (; i < overrides.size(); ++ i)
|
||||
for (; i < entities.size(); ++ i)
|
||||
target_eec.emplace_back(entities[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,6 +174,7 @@ namespace Slic3r {
|
|||
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
|
||||
|
||||
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
|
||||
const std::string GCodeTimeEstimator::Pause_Print_Tag = "PRINT_PAUSE";
|
||||
|
||||
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
|
||||
: m_mode(mode)
|
||||
|
@ -212,8 +213,8 @@ namespace Slic3r {
|
|||
}
|
||||
_calculate_time();
|
||||
|
||||
if (m_needs_color_times && (m_color_time_cache != 0.0f))
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
|
@ -230,8 +231,8 @@ namespace Slic3r {
|
|||
|
||||
_calculate_time();
|
||||
|
||||
if (m_needs_color_times && (m_color_time_cache != 0.0f))
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
|
@ -245,8 +246,8 @@ namespace Slic3r {
|
|||
m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
|
||||
_calculate_time();
|
||||
|
||||
if (m_needs_color_times && (m_color_time_cache != 0.0f))
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
|
@ -263,8 +264,8 @@ namespace Slic3r {
|
|||
m_parser.parse_line(line, action);
|
||||
_calculate_time();
|
||||
|
||||
if (m_needs_color_times && (m_color_time_cache != 0.0f))
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
|
||||
m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache});
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
|
@ -351,8 +352,8 @@ namespace Slic3r {
|
|||
}
|
||||
|
||||
// check tags
|
||||
// remove color change tag
|
||||
if (gcode_line == "; " + Color_Change_Tag)
|
||||
// remove Color_Change_Tag and Pause_Print_Tag
|
||||
if (gcode_line == "; " + Color_Change_Tag || gcode_line == "; " + Pause_Print_Tag)
|
||||
continue;
|
||||
|
||||
// replaces placeholders for initial line M73 with the real lines
|
||||
|
@ -717,25 +718,26 @@ namespace Slic3r {
|
|||
return _get_time_minutes(get_time());
|
||||
}
|
||||
|
||||
std::vector<float> GCodeTimeEstimator::get_color_times() const
|
||||
std::vector<std::pair<CustomGcodeType, float>> GCodeTimeEstimator::get_custom_gcode_times() const
|
||||
{
|
||||
return m_color_times;
|
||||
return m_custom_gcode_times;
|
||||
}
|
||||
|
||||
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
float total_time = 0.0f;
|
||||
for (float t : m_color_times)
|
||||
// for (float t : m_color_times)
|
||||
for (auto t : m_custom_gcode_times)
|
||||
{
|
||||
std::string time = _get_time_dhms(t);
|
||||
std::string time = _get_time_dhms(t.second);
|
||||
if (include_remaining)
|
||||
{
|
||||
time += " (";
|
||||
time += _get_time_dhms(m_time - total_time);
|
||||
time += ")";
|
||||
}
|
||||
total_time += t;
|
||||
total_time += t.second;
|
||||
ret.push_back(time);
|
||||
}
|
||||
return ret;
|
||||
|
@ -745,20 +747,42 @@ namespace Slic3r {
|
|||
{
|
||||
std::vector<std::string> ret;
|
||||
float total_time = 0.0f;
|
||||
for (float t : m_color_times)
|
||||
// for (float t : m_color_times)
|
||||
for (auto t : m_custom_gcode_times)
|
||||
{
|
||||
std::string time = _get_time_minutes(t);
|
||||
std::string time = _get_time_minutes(t.second);
|
||||
if (include_remaining)
|
||||
{
|
||||
time += " (";
|
||||
time += _get_time_minutes(m_time - total_time);
|
||||
time += ")";
|
||||
}
|
||||
total_time += t;
|
||||
total_time += t.second;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CustomGcodeType, std::string>> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const
|
||||
{
|
||||
std::vector<std::pair<CustomGcodeType, std::string>> ret;
|
||||
|
||||
float total_time = 0.0f;
|
||||
for (auto t : m_custom_gcode_times)
|
||||
{
|
||||
std::string time = _get_time_dhm(t.second);
|
||||
if (include_remaining)
|
||||
{
|
||||
time += " (";
|
||||
time += _get_time_dhm(m_time - total_time);
|
||||
time += ")";
|
||||
}
|
||||
total_time += t.second;
|
||||
ret.push_back({t.first, time});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t GCodeTimeEstimator::memory_used() const
|
||||
{
|
||||
|
@ -791,9 +815,9 @@ namespace Slic3r {
|
|||
|
||||
m_last_st_synchronized_block_id = -1;
|
||||
|
||||
m_needs_color_times = false;
|
||||
m_color_times.clear();
|
||||
m_color_time_cache = 0.0f;
|
||||
m_needs_custom_gcode_times = false;
|
||||
m_custom_gcode_times.clear();
|
||||
m_custom_gcode_time_cache = 0.0f;
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_reset_time()
|
||||
|
@ -814,7 +838,7 @@ namespace Slic3r {
|
|||
_recalculate_trapezoids();
|
||||
|
||||
m_time += get_additional_time();
|
||||
m_color_time_cache += get_additional_time();
|
||||
m_custom_gcode_time_cache += get_additional_time();
|
||||
|
||||
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i)
|
||||
{
|
||||
|
@ -835,7 +859,7 @@ namespace Slic3r {
|
|||
it->second.time += block_time;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
m_color_time_cache += block_time;
|
||||
m_custom_gcode_time_cache += block_time;
|
||||
}
|
||||
|
||||
m_last_st_synchronized_block_id = (int)m_blocks.size() - 1;
|
||||
|
@ -1466,26 +1490,34 @@ namespace Slic3r {
|
|||
{
|
||||
std::string comment = line.comment();
|
||||
|
||||
// color change tag
|
||||
// Color_Change_Tag
|
||||
size_t pos = comment.find(Color_Change_Tag);
|
||||
if (pos != comment.npos)
|
||||
{
|
||||
_process_color_change_tag();
|
||||
_process_custom_gcode_tag(cgtColorChange);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pause_Print_Tag
|
||||
pos = comment.find(Pause_Print_Tag);
|
||||
if (pos != comment.npos)
|
||||
{
|
||||
_process_custom_gcode_tag(cgtPausePrint);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GCodeTimeEstimator::_process_color_change_tag()
|
||||
void GCodeTimeEstimator::_process_custom_gcode_tag(CustomGcodeType code)
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
m_needs_color_times = true;
|
||||
m_needs_custom_gcode_times = true;
|
||||
_calculate_time();
|
||||
if (m_color_time_cache != 0.0f)
|
||||
if (m_custom_gcode_time_cache != 0.0f)
|
||||
{
|
||||
m_color_times.push_back(m_color_time_cache);
|
||||
m_color_time_cache = 0.0f;
|
||||
m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache});
|
||||
m_custom_gcode_time_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "libslic3r.h"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "GCodeReader.hpp"
|
||||
#include "CustomGCode.hpp"
|
||||
|
||||
#define ENABLE_MOVE_STATS 0
|
||||
|
||||
|
@ -23,6 +24,7 @@ namespace Slic3r {
|
|||
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
|
||||
|
||||
static const std::string Color_Change_Tag;
|
||||
static const std::string Pause_Print_Tag;
|
||||
|
||||
enum EMode : unsigned char
|
||||
{
|
||||
|
@ -240,10 +242,10 @@ namespace Slic3r {
|
|||
int m_last_st_synchronized_block_id;
|
||||
float m_time; // s
|
||||
|
||||
// data to calculate color print times
|
||||
bool m_needs_color_times;
|
||||
std::vector<float> m_color_times;
|
||||
float m_color_time_cache;
|
||||
// data to calculate custom code times
|
||||
bool m_needs_custom_gcode_times;
|
||||
std::vector<std::pair<CustomGcodeType, float>> m_custom_gcode_times;
|
||||
float m_custom_gcode_time_cache;
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
MovesStatsMap _moves_stats;
|
||||
|
@ -369,8 +371,8 @@ namespace Slic3r {
|
|||
// Returns the estimated time, in minutes (integer)
|
||||
std::string get_time_minutes() const;
|
||||
|
||||
// Returns the estimated time, in seconds, for each color
|
||||
std::vector<float> get_color_times() const;
|
||||
// Returns the estimated time, in seconds, for each custom gcode
|
||||
std::vector<std::pair<CustomGcodeType, float>> get_custom_gcode_times() const;
|
||||
|
||||
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
|
||||
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||
|
@ -380,6 +382,10 @@ namespace Slic3r {
|
|||
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
|
||||
std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
|
||||
|
||||
// Returns the estimated time, in format DDd HHh MMm, for each custom_gcode
|
||||
// If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)"
|
||||
std::vector<std::pair<CustomGcodeType, std::string>> get_custom_gcode_times_dhm(bool include_remaining) const;
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t memory_used() const;
|
||||
|
||||
|
@ -460,8 +466,8 @@ namespace Slic3r {
|
|||
// Returns true if any tag has been processed
|
||||
bool _process_tags(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes color change tag
|
||||
void _process_color_change_tag();
|
||||
// Processes ColorChangeTag and PausePrintTag
|
||||
void _process_custom_gcode_tag(CustomGcodeType code);
|
||||
|
||||
// Simulates firmware st_synchronize() call
|
||||
void _simulate_st_synchronize();
|
||||
|
|
|
@ -613,8 +613,12 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
|
||||
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
|
||||
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
|
||||
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
|
||||
// see "Placeholders do not respect filament overrides." GH issue #3649
|
||||
m_placeholder_parser.apply_config(filament_overrides);
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
m_config.apply_only(new_full_config, print_diff, true);
|
||||
//FIXME use move semantics once ConfigBase supports it.
|
||||
m_config.apply(filament_overrides);
|
||||
// Handle changes to object config defaults
|
||||
m_default_object_config.apply_only(new_full_config, object_diff, true);
|
||||
|
@ -1935,7 +1939,7 @@ void Print::_make_brim()
|
|||
for (size_t i = 0; i < loops_trimmed_order.size();) {
|
||||
// Find all pieces that the initial loop was split into.
|
||||
size_t j = i + 1;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].first == loops_trimmed_order[j].first; ++ j) ;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
|
||||
auto *loop = new ExtrusionLoop();
|
||||
|
|
|
@ -153,15 +153,15 @@ public:
|
|||
Layer* get_layer(int idx) { return m_layers[idx]; }
|
||||
// Get a layer exactly at print_z.
|
||||
const Layer* get_layer_at_printz(coordf_t print_z) const {
|
||||
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [print_z](const Layer *layer) { return layer->print_z < print_z; });
|
||||
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [print_z](const Layer *layer) { return layer->print_z < print_z; });
|
||||
return (it == m_layers.end() || (*it)->print_z != print_z) ? nullptr : *it;
|
||||
}
|
||||
Layer* get_layer_at_printz(coordf_t print_z) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z)); }
|
||||
// Get a layer approximately at print_z.
|
||||
const Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const {
|
||||
coordf_t limit = print_z + epsilon;
|
||||
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [limit](const Layer *layer) { return layer->print_z < limit; });
|
||||
return (it == m_layers.end() || (*it)->print_z < print_z - epsilon) ? nullptr : *it;
|
||||
coordf_t limit = print_z - epsilon;
|
||||
auto it = Slic3r::lower_bound_by_predicate(m_layers.begin(), m_layers.end(), [limit](const Layer *layer) { return layer->print_z < limit; });
|
||||
return (it == m_layers.end() || (*it)->print_z > print_z + epsilon) ? nullptr : *it;
|
||||
}
|
||||
Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_printz(print_z, epsilon)); }
|
||||
|
||||
|
@ -305,8 +305,8 @@ struct PrintStatistics
|
|||
PrintStatistics() { clear(); }
|
||||
std::string estimated_normal_print_time;
|
||||
std::string estimated_silent_print_time;
|
||||
std::vector<std::string> estimated_normal_color_print_times;
|
||||
std::vector<std::string> estimated_silent_color_print_times;
|
||||
std::vector<std::pair<CustomGcodeType, std::string>> estimated_normal_custom_gcode_print_times;
|
||||
std::vector<std::pair<CustomGcodeType, std::string>> estimated_silent_custom_gcode_print_times;
|
||||
double total_used_filament;
|
||||
double total_extruded_volume;
|
||||
double total_cost;
|
||||
|
@ -326,8 +326,8 @@ struct PrintStatistics
|
|||
void clear() {
|
||||
estimated_normal_print_time.clear();
|
||||
estimated_silent_print_time.clear();
|
||||
estimated_normal_color_print_times.clear();
|
||||
estimated_silent_color_print_times.clear();
|
||||
estimated_normal_custom_gcode_print_times.clear();
|
||||
estimated_silent_custom_gcode_print_times.clear();
|
||||
total_used_filament = 0.;
|
||||
total_extruded_volume = 0.;
|
||||
total_cost = 0.;
|
||||
|
|
|
@ -113,6 +113,16 @@ void PrintConfigDef::init_common_params()
|
|||
"If left blank, the default OS CA certificate repository is used.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("elefant_foot_compensation", coFloat);
|
||||
def->label = L("Elephant foot compensation");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("The first layer will be shrunk in the XY plane by the configured value "
|
||||
"to compensate for the 1st layer squish aka an Elephant Foot effect.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.2));
|
||||
}
|
||||
|
||||
void PrintConfigDef::init_fff_params()
|
||||
|
@ -371,16 +381,6 @@ void PrintConfigDef::init_fff_params()
|
|||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloat(6));
|
||||
|
||||
def = this->add("elefant_foot_compensation", coFloat);
|
||||
def->label = L("Elephant foot compensation");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("The first layer will be shrunk in the XY plane by the configured value "
|
||||
"to compensate for the 1st layer squish aka an Elephant Foot effect.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("end_gcode", coString);
|
||||
def->label = L("End G-code");
|
||||
def->tooltip = L("This end procedure is inserted at the end of the output file. "
|
||||
|
@ -2442,6 +2442,15 @@ void PrintConfigDef::init_sla_params()
|
|||
"to the sign of the correction.");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.0));
|
||||
|
||||
def = this->add("elefant_foot_min_width", coFloat);
|
||||
def->label = L("Elephant foot minimum width");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("Minimum width of features to maintain when doing elephant foot compensation.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.2));
|
||||
|
||||
def = this->add("gamma_correction", coFloat);
|
||||
def->label = L("Printer gamma correction");
|
||||
|
@ -2644,6 +2653,16 @@ void PrintConfigDef::init_sla_params()
|
|||
def->max = 15;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
|
||||
def = this->add("support_max_bridges_on_pillar", coInt);
|
||||
def->label = L("Max bridges on a pillar");
|
||||
def->tooltip = L(
|
||||
"Maximum number of bridges that can be placed on a pillar. Bridges "
|
||||
"hold support point pinheads and connect to pillars as small branches.");
|
||||
def->min = 0;
|
||||
def->max = 50;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionInt(3));
|
||||
|
||||
def = this->add("support_pillar_connection_mode", coEnum);
|
||||
def->label = L("Support pillar connection mode");
|
||||
|
@ -2840,7 +2859,7 @@ void PrintConfigDef::init_sla_params()
|
|||
def->min = 45;
|
||||
def->max = 90;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(45.0));
|
||||
def->set_default_value(new ConfigOptionFloat(90.0));
|
||||
|
||||
def = this->add("pad_around_object", coBool);
|
||||
def->label = L("Pad around object");
|
||||
|
|
|
@ -980,6 +980,9 @@ public:
|
|||
|
||||
// Radius in mm of the support pillars.
|
||||
ConfigOptionFloat support_pillar_diameter /*= 0.8*/;
|
||||
|
||||
// How much bridge (supporting another pinhead) can be placed on a pillar.
|
||||
ConfigOptionInt support_max_bridges_on_pillar;
|
||||
|
||||
// How the pillars are bridged together
|
||||
ConfigOptionEnum<SLAPillarConnectionMode> support_pillar_connection_mode;
|
||||
|
@ -1101,6 +1104,7 @@ protected:
|
|||
OPT_PTR(support_head_penetration);
|
||||
OPT_PTR(support_head_width);
|
||||
OPT_PTR(support_pillar_diameter);
|
||||
OPT_PTR(support_max_bridges_on_pillar);
|
||||
OPT_PTR(support_pillar_connection_mode);
|
||||
OPT_PTR(support_buildplate_only);
|
||||
OPT_PTR(support_pillar_widening_factor);
|
||||
|
@ -1175,6 +1179,8 @@ public:
|
|||
ConfigOptionBool display_mirror_y;
|
||||
ConfigOptionFloats relative_correction;
|
||||
ConfigOptionFloat absolute_correction;
|
||||
ConfigOptionFloat elefant_foot_compensation;
|
||||
ConfigOptionFloat elefant_foot_min_width;
|
||||
ConfigOptionFloat gamma_correction;
|
||||
ConfigOptionFloat fast_tilt_time;
|
||||
ConfigOptionFloat slow_tilt_time;
|
||||
|
@ -1198,6 +1204,8 @@ protected:
|
|||
OPT_PTR(display_orientation);
|
||||
OPT_PTR(relative_correction);
|
||||
OPT_PTR(absolute_correction);
|
||||
OPT_PTR(elefant_foot_compensation);
|
||||
OPT_PTR(elefant_foot_min_width);
|
||||
OPT_PTR(gamma_correction);
|
||||
OPT_PTR(fast_tilt_time);
|
||||
OPT_PTR(slow_tilt_time);
|
||||
|
|
|
@ -1139,10 +1139,9 @@ void PrintObject::discover_vertical_shells()
|
|||
}
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
polygons_append(holes, cache_top_botom_regions[idx_layer].holes);
|
||||
{
|
||||
if (int n_top_layers = region_config.top_solid_layers.value; n_top_layers > 0) {
|
||||
// Gather top regions projected to this layer.
|
||||
coordf_t print_z = layer->print_z;
|
||||
int n_top_layers = region_config.top_solid_layers.value;
|
||||
coordf_t print_z = layer->print_z;
|
||||
for (int i = int(idx_layer) + 1;
|
||||
i < int(cache_top_botom_regions.size()) &&
|
||||
(i < int(idx_layer) + n_top_layers ||
|
||||
|
@ -1159,10 +1158,9 @@ void PrintObject::discover_vertical_shells()
|
|||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if (int n_bottom_layers = region_config.bottom_solid_layers.value; n_bottom_layers > 0) {
|
||||
// Gather bottom regions projected to this layer.
|
||||
coordf_t bottom_z = layer->bottom_z();
|
||||
int n_bottom_layers = region_config.bottom_solid_layers.value;
|
||||
coordf_t bottom_z = layer->bottom_z();
|
||||
for (int i = int(idx_layer) - 1;
|
||||
i >= 0 &&
|
||||
(i > int(idx_layer) - n_bottom_layers ||
|
||||
|
@ -2356,6 +2354,9 @@ void PrintObject::discover_horizontal_shells()
|
|||
for (size_t idx_surface_type = 0; idx_surface_type < 3; ++ idx_surface_type) {
|
||||
m_print->throw_if_canceled();
|
||||
SurfaceType type = (idx_surface_type == 0) ? stTop : (idx_surface_type == 1) ? stBottom : stBottomBridge;
|
||||
int num_solid_layers = (type == stTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||
if (num_solid_layers == 0)
|
||||
continue;
|
||||
// Find slices of current type for current layer.
|
||||
// Use slices instead of fill_surfaces, because they also include the perimeter area,
|
||||
// which needs to be propagated in shells; we need to grow slices like we did for
|
||||
|
@ -2384,9 +2385,9 @@ void PrintObject::discover_horizontal_shells()
|
|||
// Scatter top / bottom regions to other layers. Scattering process is inherently serial, it is difficult to parallelize without locking.
|
||||
for (int n = (type == stTop) ? int(i) - 1 : int(i) + 1;
|
||||
(type == stTop) ?
|
||||
(n >= 0 && (int(i) - n < region_config.top_solid_layers.value ||
|
||||
(n >= 0 && (int(i) - n < num_solid_layers ||
|
||||
print_z - m_layers[n]->print_z < region_config.top_solid_min_thickness.value - EPSILON)) :
|
||||
(n < int(m_layers.size()) && (n - int(i) < region_config.bottom_solid_layers.value ||
|
||||
(n < int(m_layers.size()) && (n - int(i) < num_solid_layers ||
|
||||
m_layers[n]->bottom_z() - bottom_z < region_config.bottom_solid_min_thickness.value - EPSILON));
|
||||
(type == stTop) ? -- n : ++ n)
|
||||
{
|
||||
|
|
|
@ -41,7 +41,6 @@ const double SupportConfig::max_dual_pillar_height_mm = 35.0;
|
|||
const double SupportConfig::optimizer_rel_score_diff = 1e-6;
|
||||
const unsigned SupportConfig::optimizer_max_iterations = 1000;
|
||||
const unsigned SupportConfig::pillar_cascade_neighbors = 3;
|
||||
const unsigned SupportConfig::max_bridges_on_pillar = 3;
|
||||
|
||||
void SupportTree::retrieve_full_mesh(TriangleMesh &outmesh) const {
|
||||
outmesh.merge(retrieve_mesh(MeshType::Support));
|
||||
|
|
|
@ -83,6 +83,8 @@ struct SupportConfig
|
|||
// body. This is only useful when elevation is set to zero.
|
||||
double pillar_base_safety_distance_mm = 0.5;
|
||||
|
||||
unsigned max_bridges_on_pillar = 3;
|
||||
|
||||
double head_fullwidth() const {
|
||||
return 2 * head_front_radius_mm + head_width_mm +
|
||||
2 * head_back_radius_mm - head_penetration_mm;
|
||||
|
@ -103,7 +105,7 @@ struct SupportConfig
|
|||
static const double optimizer_rel_score_diff;
|
||||
static const unsigned optimizer_max_iterations;
|
||||
static const unsigned pillar_cascade_neighbors;
|
||||
static const unsigned max_bridges_on_pillar;
|
||||
|
||||
};
|
||||
|
||||
enum class MeshType { Support, Pad };
|
||||
|
|
|
@ -65,6 +65,8 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c)
|
|||
c.support_base_safety_distance.getFloat() < EPSILON ?
|
||||
scfg.safety_distance_mm : c.support_base_safety_distance.getFloat();
|
||||
|
||||
scfg.max_bridges_on_pillar = unsigned(c.support_max_bridges_on_pillar.getInt());
|
||||
|
||||
return scfg;
|
||||
}
|
||||
|
||||
|
@ -785,6 +787,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
|||
"material_correction",
|
||||
"relative_correction",
|
||||
"absolute_correction",
|
||||
"elefant_foot_compensation",
|
||||
"elefant_foot_min_width",
|
||||
"gamma_correction"
|
||||
};
|
||||
|
||||
|
@ -944,6 +948,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||
|| opt_key == "support_head_penetration"
|
||||
|| opt_key == "support_head_width"
|
||||
|| opt_key == "support_pillar_diameter"
|
||||
|| opt_key == "support_max_bridges_on_pillar"
|
||||
|| opt_key == "support_pillar_connection_mode"
|
||||
|| opt_key == "support_buildplate_only"
|
||||
|| opt_key == "support_base_diameter"
|
||||
|
@ -1087,8 +1092,7 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
|||
|
||||
const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const
|
||||
{
|
||||
size_t idx = o == soModel ? m_model_slices_idx :
|
||||
m_support_slices_idx;
|
||||
size_t idx = o == soModel ? m_model_slices_idx : m_support_slices_idx;
|
||||
|
||||
if(m_po == nullptr) return EMPTY_SLICE;
|
||||
|
||||
|
|
|
@ -152,6 +152,10 @@ public:
|
|||
}
|
||||
|
||||
const ExPolygons& get_slice(SliceOrigin o) const;
|
||||
size_t get_slice_idx(SliceOrigin o) const
|
||||
{
|
||||
return o == soModel ? m_model_slices_idx : m_support_slices_idx;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <libslic3r/SLA/Pad.hpp>
|
||||
#include <libslic3r/SLA/SupportPointGenerator.hpp>
|
||||
|
||||
#include <libslic3r/ElephantFootCompensation.hpp>
|
||||
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
|
||||
// For geometry algorithms with native Clipper types (no copies and conversions)
|
||||
|
@ -78,6 +80,40 @@ SLAPrint::Steps::Steps(SLAPrint *print)
|
|||
, objectstep_scale{(max_objstatus - min_objstatus) / (objcount * 100.0)}
|
||||
{}
|
||||
|
||||
void SLAPrint::Steps::apply_printer_corrections(SLAPrintObject &po, SliceOrigin o)
|
||||
{
|
||||
if (o == soSupport && !po.m_supportdata) return;
|
||||
|
||||
auto faded_lyrs = size_t(po.m_config.faded_layers.getInt());
|
||||
double min_w = m_print->m_printer_config.elefant_foot_min_width.getFloat() / 2.;
|
||||
double start_efc = m_print->m_printer_config.elefant_foot_compensation.getFloat();
|
||||
|
||||
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
|
||||
coord_t clpr_offs = scaled(doffs);
|
||||
|
||||
faded_lyrs = std::min(po.m_slice_index.size(), faded_lyrs);
|
||||
|
||||
auto efc = [start_efc, faded_lyrs](size_t pos) {
|
||||
return (faded_lyrs - 1 - pos) * start_efc / (faded_lyrs - 1);
|
||||
};
|
||||
|
||||
std::vector<ExPolygons> &slices = o == soModel ?
|
||||
po.m_model_slices :
|
||||
po.m_supportdata->support_slices;
|
||||
|
||||
if (clpr_offs != 0) for (size_t i = 0; i < po.m_slice_index.size(); ++i) {
|
||||
size_t idx = po.m_slice_index[i].get_slice_idx(o);
|
||||
if (idx < slices.size())
|
||||
slices[idx] = offset_ex(slices[idx], float(clpr_offs));
|
||||
}
|
||||
|
||||
if (start_efc > 0.) for (size_t i = 0; i < faded_lyrs; ++i) {
|
||||
size_t idx = po.m_slice_index[i].get_slice_idx(o);
|
||||
if (idx < slices.size())
|
||||
slices[idx] = elephant_foot_compensation(slices[idx], min_w, efc(i));
|
||||
}
|
||||
}
|
||||
|
||||
void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
|
||||
{
|
||||
po.m_hollowing_data.reset();
|
||||
|
@ -236,20 +272,15 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||
}
|
||||
|
||||
auto mit = slindex_it;
|
||||
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
|
||||
coord_t clpr_offs = scaled(doffs);
|
||||
for(size_t id = 0;
|
||||
for (size_t id = 0;
|
||||
id < po.m_model_slices.size() && mit != po.m_slice_index.end();
|
||||
id++)
|
||||
{
|
||||
// We apply the printer correction offset here.
|
||||
if(clpr_offs != 0)
|
||||
po.m_model_slices[id] =
|
||||
offset_ex(po.m_model_slices[id], float(clpr_offs));
|
||||
|
||||
id++) {
|
||||
mit->set_model_slice_idx(po, id); ++mit;
|
||||
}
|
||||
|
||||
// We apply the printer correction offset here.
|
||||
apply_printer_corrections(po, soModel);
|
||||
|
||||
if(po.m_config.supports_enable.getBool() || po.m_config.pad_enable.getBool())
|
||||
{
|
||||
po.m_supportdata.reset(new SLAPrintObject::SupportData(mesh));
|
||||
|
@ -446,21 +477,15 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) {
|
|||
auto heights = reserve_vector<float>(po.m_slice_index.size());
|
||||
|
||||
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
|
||||
|
||||
|
||||
sd->support_slices = sd->support_tree_ptr->slice(
|
||||
heights, float(po.config().slice_closing_radius.value));
|
||||
heights, float(po.config().slice_closing_radius.value));
|
||||
}
|
||||
|
||||
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
|
||||
coord_t clpr_offs = scaled(doffs);
|
||||
|
||||
for (size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i) {
|
||||
// We apply the printer correction offset here.
|
||||
if (clpr_offs != 0)
|
||||
sd->support_slices[i] = offset_ex(sd->support_slices[i], float(clpr_offs));
|
||||
|
||||
for (size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i)
|
||||
po.m_slice_index[i].set_support_slice_idx(po, i);
|
||||
}
|
||||
|
||||
apply_printer_corrections(po, soSupport);
|
||||
|
||||
// Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update
|
||||
// status to the 3D preview to load the SLA slices.
|
||||
|
|
|
@ -43,6 +43,8 @@ private:
|
|||
bool canceled() const { return m_print->canceled(); }
|
||||
void initialize_printer_input();
|
||||
|
||||
void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o);
|
||||
|
||||
public:
|
||||
Steps(SLAPrint *print);
|
||||
|
||||
|
|
|
@ -43,10 +43,12 @@
|
|||
|
||||
|
||||
//==================
|
||||
// 2.2.0.beta1 techs
|
||||
// 2.2.0.rc1 techs
|
||||
//==================
|
||||
#define ENABLE_2_2_0_BETA1 1
|
||||
#define ENABLE_2_2_0_RC1 1
|
||||
|
||||
// Enable hack to remove crash when closing on OSX 10.9.5
|
||||
#define ENABLE_HACK_CLOSING_ON_OSX_10_9_5 (1 && ENABLE_2_2_0_RC1)
|
||||
|
||||
//==================
|
||||
// 2.3.0.alpha1 techs
|
||||
|
|
|
@ -64,15 +64,23 @@ extern std::string normalize_utf8_nfc(const char *src);
|
|||
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
|
||||
extern std::error_code rename_file(const std::string &from, const std::string &to);
|
||||
|
||||
enum CopyFileResult {
|
||||
SUCCESS = 0,
|
||||
FAIL_COPY_FILE,
|
||||
FAIL_FILES_DIFFERENT,
|
||||
FAIL_RENAMING,
|
||||
FAIL_CHECK_ORIGIN_NOT_OPENED,
|
||||
FAIL_CHECK_TARGET_NOT_OPENED
|
||||
};
|
||||
// Copy a file, adjust the access attributes, so that the target is writable.
|
||||
int copy_file_inner(const std::string &from, const std::string &to);
|
||||
CopyFileResult copy_file_inner(const std::string &from, const std::string &to);
|
||||
// Copy file to a temp file first, then rename it to the final file name.
|
||||
// If with_check is true, then the content of the copied file is compared to the content
|
||||
// of the source file before renaming.
|
||||
extern int copy_file(const std::string &from, const std::string &to, const bool with_check = false);
|
||||
extern CopyFileResult copy_file(const std::string &from, const std::string &to, const bool with_check = false);
|
||||
|
||||
// Compares two files, returns 0 if identical, -1 if different.
|
||||
extern int check_copy(const std::string& origin, const std::string& copy);
|
||||
// Compares two files if identical.
|
||||
extern CopyFileResult check_copy(const std::string& origin, const std::string& copy);
|
||||
|
||||
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/1298
|
||||
|
|
|
@ -417,7 +417,7 @@ std::error_code rename_file(const std::string &from, const std::string &to)
|
|||
#endif
|
||||
}
|
||||
|
||||
int copy_file_inner(const std::string& from, const std::string& to)
|
||||
CopyFileResult copy_file_inner(const std::string& from, const std::string& to)
|
||||
{
|
||||
const boost::filesystem::path source(from);
|
||||
const boost::filesystem::path target(to);
|
||||
|
@ -433,38 +433,40 @@ int copy_file_inner(const std::string& from, const std::string& to)
|
|||
boost::filesystem::permissions(target, perms, ec);
|
||||
boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec);
|
||||
if (ec) {
|
||||
return -1;
|
||||
return FAIL_COPY_FILE;
|
||||
}
|
||||
boost::filesystem::permissions(target, perms, ec);
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int copy_file(const std::string &from, const std::string &to, const bool with_check)
|
||||
CopyFileResult copy_file(const std::string &from, const std::string &to, const bool with_check)
|
||||
{
|
||||
std::string to_temp = to + ".tmp";
|
||||
int ret_val = copy_file_inner(from,to_temp);
|
||||
if(ret_val == 0)
|
||||
CopyFileResult ret_val = copy_file_inner(from,to_temp);
|
||||
if(ret_val == SUCCESS)
|
||||
{
|
||||
if (with_check)
|
||||
ret_val = check_copy(from, to_temp);
|
||||
|
||||
if (ret_val == 0 && rename_file(to_temp, to))
|
||||
ret_val = -3;
|
||||
ret_val = FAIL_RENAMING;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int check_copy(const std::string &origin, const std::string ©)
|
||||
CopyFileResult check_copy(const std::string &origin, const std::string ©)
|
||||
{
|
||||
std::ifstream f1(origin, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
|
||||
std::ifstream f2(copy, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
|
||||
boost::nowide::ifstream f1(origin, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
|
||||
boost::nowide::ifstream f2(copy, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
|
||||
|
||||
if (f1.fail() || f2.fail())
|
||||
return -2;
|
||||
if (f1.fail())
|
||||
return FAIL_CHECK_ORIGIN_NOT_OPENED;
|
||||
if (f2.fail())
|
||||
return FAIL_CHECK_TARGET_NOT_OPENED;
|
||||
|
||||
std::streampos fsize = f1.tellg();
|
||||
if (fsize != f2.tellg())
|
||||
return -2;
|
||||
return FAIL_FILES_DIFFERENT;
|
||||
|
||||
f1.seekg(0, std::ifstream::beg);
|
||||
f2.seekg(0, std::ifstream::beg);
|
||||
|
@ -481,12 +483,12 @@ int check_copy(const std::string &origin, const std::string ©)
|
|||
if (origin_cnt != copy_cnt ||
|
||||
(origin_cnt > 0 && std::memcmp(buffer_origin.data(), buffer_copy.data(), origin_cnt) != 0))
|
||||
// Files are different.
|
||||
return -2;
|
||||
return FAIL_FILES_DIFFERENT;
|
||||
fsize -= origin_cnt;
|
||||
} while (f1.good() && f2.good());
|
||||
|
||||
// All data has been read and compared equal.
|
||||
return (f1.eof() && f2.eof() && fsize == 0) ? 0 : -2;
|
||||
return (f1.eof() && f2.eof() && fsize == 0) ? SUCCESS : FAIL_FILES_DIFFERENT;
|
||||
}
|
||||
|
||||
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
|
||||
|
|
|
@ -105,20 +105,28 @@ void BackgroundSlicingProcess::process_fff()
|
|||
GUI::RemovableDriveManager::get_instance().update();
|
||||
bool with_check = GUI::RemovableDriveManager::get_instance().is_path_on_removable_drive(export_path);
|
||||
int copy_ret_val = copy_file(m_temp_output_path, export_path, with_check);
|
||||
if (with_check && copy_ret_val == -2)
|
||||
{
|
||||
std::string err_msg = "Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at " + export_path + ".tmp.";
|
||||
throw std::runtime_error(_utf8(L(err_msg)));
|
||||
}
|
||||
else if (copy_ret_val == -3)
|
||||
{
|
||||
std::string err_msg = "Renaming of the G-code after copying to the selected destination folder has failed. Current path is " + export_path + ".tmp. Please try exporting again.";
|
||||
throw std::runtime_error(_utf8(L(err_msg)));
|
||||
}
|
||||
else if ( copy_ret_val != 0)
|
||||
{
|
||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?")));
|
||||
switch (copy_ret_val){
|
||||
case SUCCESS: break; // no error
|
||||
case FAIL_COPY_FILE:
|
||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?")));
|
||||
break;
|
||||
case FAIL_FILES_DIFFERENT:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_RENAMING:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_ORIGIN_NOT_OPENED:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_TARGET_NOT_OPENED:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
default:
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unexpected fail code(" << (int)copy_ret_val << ") durring copy_file() to " << export_path << ".";
|
||||
break;
|
||||
}
|
||||
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
run_post_process_scripts(export_path, m_fff_print->config());
|
||||
m_print->set_status(100, (boost::format(_utf8(L("G-code file exported to %1%"))) % export_path).str());
|
||||
|
@ -216,7 +224,7 @@ void BackgroundSlicingProcess::thread_proc()
|
|||
wxString errmsg = wxString::Format(_(L("%s has encountered an error. It was likely caused by running out of memory. "
|
||||
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
||||
"be glad if you reported it.")), SLIC3R_APP_NAME);
|
||||
error = errmsg.ToStdString() + "\n\n" + std::string(ex.what());
|
||||
error = std::string(errmsg.ToUTF8()) + "\n\n" + std::string(ex.what());
|
||||
} catch (std::exception &ex) {
|
||||
error = ex.what();
|
||||
} catch (...) {
|
||||
|
@ -484,7 +492,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
|||
|
||||
if (m_print == m_fff_print) {
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
if (copy_file(m_temp_output_path, source_path.string()) != 0) {
|
||||
if (copy_file(m_temp_output_path, source_path.string()) != SUCCESS) {
|
||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||
}
|
||||
run_post_process_scripts(source_path.string(), m_fff_print->config());
|
||||
|
|
|
@ -220,7 +220,7 @@ wxPanel* BedShapePanel::init_texture_panel()
|
|||
if (m_custom_texture != NONE)
|
||||
{
|
||||
if (!exists)
|
||||
tooltip_text += _(L("Not found: "));
|
||||
tooltip_text += _(L("Not found:")) + " ";
|
||||
|
||||
tooltip_text += _(m_custom_texture);
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ wxPanel* BedShapePanel::init_model_panel()
|
|||
if (m_custom_model != NONE)
|
||||
{
|
||||
if (!exists)
|
||||
tooltip_text += _(L("Not found: "));
|
||||
tooltip_text += _(L("Not found:")) + " ";
|
||||
|
||||
tooltip_text += _(m_custom_model);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ Camera::Camera()
|
|||
, m_distance(DefaultDistance)
|
||||
, m_gui_scale(1.0)
|
||||
, m_view_matrix(Transform3d::Identity())
|
||||
, m_view_rotation(1., 0., 0., 0.)
|
||||
, m_projection_matrix(Transform3d::Identity())
|
||||
{
|
||||
set_default_orientation();
|
||||
|
@ -85,7 +86,13 @@ void Camera::select_next_type()
|
|||
|
||||
void Camera::set_target(const Vec3d& target)
|
||||
{
|
||||
translate_world(target - m_target);
|
||||
Vec3d new_target = validate_target(target);
|
||||
Vec3d new_displacement = new_target - m_target;
|
||||
if (!new_displacement.isApprox(Vec3d::Zero()))
|
||||
{
|
||||
m_target = new_target;
|
||||
m_view_matrix.translate(-new_displacement);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::update_zoom(double delta_zoom)
|
||||
|
@ -299,17 +306,6 @@ void Camera::debug_render() const
|
|||
}
|
||||
#endif // ENABLE_CAMERA_STATISTICS
|
||||
|
||||
void Camera::translate_world(const Vec3d& displacement)
|
||||
{
|
||||
Vec3d new_target = validate_target(m_target + displacement);
|
||||
Vec3d new_displacement = new_target - m_target;
|
||||
if (!new_displacement.isApprox(Vec3d::Zero()))
|
||||
{
|
||||
m_target += new_displacement;
|
||||
m_view_matrix.translate(-new_displacement);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, bool apply_limits)
|
||||
{
|
||||
m_zenit += Geometry::rad2deg(delta_zenit_rad);
|
||||
|
@ -324,50 +320,23 @@ void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, b
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME -> The following is a HACK !!!
|
||||
// When the value of the zenit rotation is large enough, the following call to rotate() shows
|
||||
// numerical instability introducing some scaling into m_view_matrix (verified by checking
|
||||
// that the camera space unit vectors are no more unit).
|
||||
// See also https://dev.prusa3d.com/browse/SPE-1082
|
||||
// We split the zenit rotation into a set of smaller rotations which are then applied.
|
||||
static const double MAX_ALLOWED = Geometry::deg2rad(0.1);
|
||||
unsigned int zenit_steps_count = 1 + (unsigned int)(std::abs(delta_zenit_rad) / MAX_ALLOWED);
|
||||
double zenit_step = delta_zenit_rad / (double)zenit_steps_count;
|
||||
|
||||
Vec3d target = m_target;
|
||||
translate_world(-target);
|
||||
|
||||
if (zenit_step != 0.0)
|
||||
{
|
||||
Vec3d right = get_dir_right();
|
||||
for (unsigned int i = 0; i < zenit_steps_count; ++i)
|
||||
{
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(zenit_step, right));
|
||||
}
|
||||
}
|
||||
|
||||
if (delta_azimut_rad != 0.0)
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()));
|
||||
|
||||
translate_world(target);
|
||||
Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target;
|
||||
auto rot_z = Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ());
|
||||
m_view_rotation *= rot_z * Eigen::AngleAxisd(delta_zenit_rad, rot_z.inverse() * get_dir_right());
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.));
|
||||
}
|
||||
|
||||
// Virtual trackball, rotate around an axis, where the eucledian norm of the axis gives the rotation angle in radians.
|
||||
void Camera::rotate_local_around_target(const Vec3d& rotation_rad)
|
||||
{
|
||||
rotate_local_around_pivot(rotation_rad, m_target);
|
||||
}
|
||||
|
||||
void Camera::rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& pivot)
|
||||
{
|
||||
// we use a copy of the pivot because a reference to the current m_target may be passed in (see i.e. rotate_local_around_target())
|
||||
// and m_target is modified by the translate_world() calls
|
||||
Vec3d center = pivot;
|
||||
translate_world(-center);
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(0), get_dir_right()));
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(1), get_dir_up()));
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(2), get_dir_forward()));
|
||||
translate_world(center);
|
||||
update_zenit();
|
||||
double angle = rotation_rad.norm();
|
||||
if (std::abs(angle) > EPSILON) {
|
||||
Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target;
|
||||
Vec3d axis = m_view_rotation.conjugate() * rotation_rad.normalized();
|
||||
m_view_rotation *= Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis));
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.));
|
||||
update_zenit();
|
||||
}
|
||||
}
|
||||
|
||||
double Camera::min_zoom() const
|
||||
|
@ -588,6 +557,9 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up
|
|||
m_view_matrix(3, 2) = 0.0;
|
||||
m_view_matrix(3, 3) = 1.0;
|
||||
|
||||
// Initialize the rotation quaternion from the rotation submatrix of of m_view_matrix.
|
||||
m_view_rotation = Eigen::Quaterniond(m_view_matrix.matrix().template block<3, 3>(0, 0));
|
||||
|
||||
update_zenit();
|
||||
}
|
||||
|
||||
|
@ -598,8 +570,8 @@ void Camera::set_default_orientation()
|
|||
double phi_rad = Geometry::deg2rad(45.0);
|
||||
double sin_theta = ::sin(theta_rad);
|
||||
Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
|
||||
m_view_matrix = Transform3d::Identity();
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(theta_rad, Vec3d::UnitX())).rotate(Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ())).translate(-camera_pos);
|
||||
m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ());
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- camera_pos), m_view_rotation, Vec3d(1., 1., 1.));
|
||||
}
|
||||
|
||||
Vec3d Camera::validate_target(const Vec3d& target) const
|
||||
|
|
|
@ -43,6 +43,8 @@ private:
|
|||
|
||||
mutable std::array<int, 4> m_viewport;
|
||||
mutable Transform3d m_view_matrix;
|
||||
// We are calculating the rotation part of the m_view_matrix from m_view_rotation.
|
||||
mutable Eigen::Quaterniond m_view_rotation;
|
||||
mutable Transform3d m_projection_matrix;
|
||||
mutable std::pair<double, double> m_frustrum_zs;
|
||||
|
||||
|
@ -107,7 +109,7 @@ public:
|
|||
#endif // ENABLE_CAMERA_STATISTICS
|
||||
|
||||
// translate the camera in world space
|
||||
void translate_world(const Vec3d& displacement);
|
||||
void translate_world(const Vec3d& displacement) { this->set_target(m_target + displacement); }
|
||||
|
||||
// rotate the camera on a sphere having center == m_target and radius == m_distance
|
||||
// using the given variations of spherical coordinates
|
||||
|
@ -117,9 +119,6 @@ public:
|
|||
// rotate the camera around three axes parallel to the camera local axes and passing through m_target
|
||||
void rotate_local_around_target(const Vec3d& rotation_rad);
|
||||
|
||||
// rotate the camera around three axes parallel to the camera local axes and passing through the given pivot point
|
||||
void rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& pivot);
|
||||
|
||||
// returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis
|
||||
bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; }
|
||||
|
||||
|
|
|
@ -347,6 +347,7 @@ void ConfigManipulation::toggle_print_sla_options(DynamicPrintConfig* config)
|
|||
toggle_field("support_head_penetration", supports_en);
|
||||
toggle_field("support_head_width", supports_en);
|
||||
toggle_field("support_pillar_diameter", supports_en);
|
||||
toggle_field("support_max_bridges_on_pillar", supports_en);
|
||||
toggle_field("support_pillar_connection_mode", supports_en);
|
||||
toggle_field("support_buildplate_only", supports_en);
|
||||
toggle_field("support_base_diameter", supports_en);
|
||||
|
|
|
@ -162,7 +162,7 @@ void ConfigSnapshotDialog::on_dpi_changed(const wxRect &suggested_rect)
|
|||
|
||||
void ConfigSnapshotDialog::onLinkClicked(wxHtmlLinkEvent &event)
|
||||
{
|
||||
m_snapshot_to_activate = event.GetLinkInfo().GetHref();
|
||||
m_snapshot_to_activate = event.GetLinkInfo().GetHref().ToUTF8();
|
||||
this->EndModal(wxID_CLOSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ PageWelcome::PageWelcome(ConfigWizard *parent)
|
|||
, welcome_text(append_text(wxString::Format(
|
||||
_(L("Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")),
|
||||
SLIC3R_APP_NAME,
|
||||
ConfigWizard::name())
|
||||
_(ConfigWizard::name()))
|
||||
))
|
||||
, cbox_reset(append(
|
||||
new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)")))
|
||||
|
@ -748,7 +748,8 @@ PageCustom::PageCustom(ConfigWizard *parent)
|
|||
|
||||
cb_custom->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) {
|
||||
tc_profile_name->Enable(custom_wanted());
|
||||
wizard_p()->on_custom_setup();
|
||||
wizard_p()->on_custom_setup(custom_wanted());
|
||||
|
||||
});
|
||||
|
||||
append(cb_custom);
|
||||
|
@ -1396,7 +1397,7 @@ void ConfigWizard::priv::load_pages()
|
|||
if (any_sla_selected) { index->add_page(page_sla_materials); }
|
||||
|
||||
// there should to be selected at least one printer
|
||||
btn_finish->Enable(any_fff_selected || any_sla_selected);
|
||||
btn_finish->Enable(any_fff_selected || any_sla_selected || custom_printer_selected);
|
||||
|
||||
index->add_page(page_update);
|
||||
index->add_page(page_reload_from_disk);
|
||||
|
@ -1599,8 +1600,9 @@ void ConfigWizard::priv::update_materials(Technology technology)
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigWizard::priv::on_custom_setup()
|
||||
void ConfigWizard::priv::on_custom_setup(const bool custom_wanted)
|
||||
{
|
||||
custom_printer_selected = custom_wanted;
|
||||
load_pages();
|
||||
}
|
||||
|
||||
|
@ -1723,6 +1725,8 @@ bool ConfigWizard::priv::on_bnt_finish()
|
|||
if (any_sla_selected)
|
||||
page_sla_materials->reload_presets();
|
||||
|
||||
// theres no need to check that filament is selected if we have only custom printer
|
||||
if (custom_printer_selected && !any_fff_selected && !any_sla_selected) return true;
|
||||
// check, that there is selected at least one filament/material
|
||||
return check_materials_in_config(T_ANY);
|
||||
}
|
||||
|
@ -1751,13 +1755,13 @@ bool ConfigWizard::priv::check_materials_in_config(Technology technology, bool s
|
|||
|
||||
if (any_fff_selected && technology & T_FFF && !exist_preset(AppConfig::SECTION_FILAMENTS, filaments))
|
||||
{
|
||||
if (show_info_msg)
|
||||
{
|
||||
wxString message = _(L("You have to select at least one filament for selected printers")) + "\n\n\t" +
|
||||
_(L("Do you want to automatic select default filaments?"));
|
||||
ask_and_selected_default_materials(message, T_FFF);
|
||||
}
|
||||
return false;
|
||||
if (show_info_msg)
|
||||
{
|
||||
wxString message = _(L("You have to select at least one filament for selected printers")) + "\n\n\t" +
|
||||
_(L("Do you want to automatic select default filaments?"));
|
||||
ask_and_selected_default_materials(message, T_FFF);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (any_sla_selected && technology & T_SLA && !exist_preset(AppConfig::SECTION_MATERIALS, sla_materials))
|
||||
|
@ -1875,6 +1879,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
if (bundle.second.is_prusa_bundle) { continue; }
|
||||
|
||||
const auto config = enabled_vendors.find(bundle.first);
|
||||
if (config == enabled_vendors.end()) { continue; }
|
||||
for (const auto &model : bundle.second.vendor_profile->models) {
|
||||
const auto model_it = config->second.find(model.id);
|
||||
if (model_it != config->second.end() && model_it->second.size() > 0) {
|
||||
|
@ -1925,7 +1930,6 @@ bool ConfigWizard::priv::check_fff_selected()
|
|||
for (const auto& printer: pages_3rdparty)
|
||||
if (printer.second.first) // FFF page
|
||||
ret |= printer.second.first->any_selected();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1942,7 +1946,7 @@ bool ConfigWizard::priv::check_sla_selected()
|
|||
// Public
|
||||
|
||||
ConfigWizard::ConfigWizard(wxWindow *parent)
|
||||
: DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
: DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(name()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, p(new priv(this))
|
||||
{
|
||||
this->SetFont(wxGetApp().normal_font());
|
||||
|
@ -1997,6 +2001,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
|
|||
// Pages for 3rd party vendors
|
||||
p->create_3rdparty_pages(); // Needs to be done _before_ creating PageVendors
|
||||
p->add_page(p->page_vendors = new PageVendors(this));
|
||||
p->add_page(p->page_custom = new PageCustom(this));
|
||||
p->custom_printer_selected = p->page_custom->custom_wanted();
|
||||
|
||||
p->any_sla_selected = p->check_sla_selected();
|
||||
p->any_fff_selected = p->check_fff_selected();
|
||||
|
@ -2008,7 +2014,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
|
|||
p->add_page(p->page_sla_materials = new PageMaterials(this, &p->sla_materials,
|
||||
_(L("SLA Material Profiles Selection")) + " ", _(L("SLA Materials")), _(L("Layer height:")) ));
|
||||
|
||||
p->add_page(p->page_custom = new PageCustom(this));
|
||||
|
||||
p->add_page(p->page_update = new PageUpdate(this));
|
||||
p->add_page(p->page_reload_from_disk = new PageReloadFromDisk(this));
|
||||
p->add_page(p->page_mode = new PageMode(this));
|
||||
|
|
|
@ -447,6 +447,7 @@ struct ConfigWizard::priv
|
|||
std::unique_ptr<DynamicPrintConfig> custom_config; // Backing for custom printer definition
|
||||
bool any_fff_selected; // Used to decide whether to display Filaments page
|
||||
bool any_sla_selected; // Used to decide whether to display SLA Materials page
|
||||
bool custom_printer_selected;
|
||||
|
||||
wxScrolledWindow *hscroll = nullptr;
|
||||
wxBoxSizer *hscroll_sizer = nullptr;
|
||||
|
@ -497,7 +498,7 @@ struct ConfigWizard::priv
|
|||
void set_run_reason(RunReason run_reason);
|
||||
void update_materials(Technology technology);
|
||||
|
||||
void on_custom_setup();
|
||||
void on_custom_setup(const bool custom_wanted);
|
||||
void on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt);
|
||||
void select_default_materials_for_printer_model(const std::vector<VendorProfile::PrinterModel> &models,
|
||||
Technology technology,
|
||||
|
|
|
@ -77,6 +77,7 @@ Control::Control( wxWindow *parent,
|
|||
|
||||
m_selection = ssUndef;
|
||||
m_ticks.set_pause_print_msg(_utf8(L("Place bearings in slots and resume printing")));
|
||||
m_ticks.set_extruder_colors(&m_extruder_colors);
|
||||
|
||||
// slider events
|
||||
this->Bind(wxEVT_PAINT, &Control::OnPaint, this);
|
||||
|
@ -332,6 +333,13 @@ void Control::SetTicksValues(const CustomGCode::Info& custom_gcode_per_print_z)
|
|||
Update();
|
||||
}
|
||||
|
||||
void Control::SetDrawMode(bool is_sla_print, bool is_sequential_print)
|
||||
{
|
||||
m_draw_mode = is_sla_print ? dmSlaPrint :
|
||||
is_sequential_print ? dmSequentialFffPrint :
|
||||
dmRegular;
|
||||
}
|
||||
|
||||
void Control::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder)
|
||||
{
|
||||
m_mode = !is_one_extruder_printed_model ? t_mode::MultiExtruder :
|
||||
|
@ -344,6 +352,11 @@ void Control::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, c
|
|||
UseDefaultColors(m_mode == t_mode::SingleExtruder);
|
||||
}
|
||||
|
||||
void Control::SetExtruderColors( const std::vector<std::string>& extruder_colors)
|
||||
{
|
||||
m_extruder_colors = extruder_colors;
|
||||
}
|
||||
|
||||
void Control::get_lower_and_higher_position(int& lower_pos, int& higher_pos)
|
||||
{
|
||||
const double step = get_scroll_step();
|
||||
|
@ -441,7 +454,7 @@ void Control::draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, const Selec
|
|||
dc.DrawLine(pt_beg, pt_end);
|
||||
|
||||
//draw action icon
|
||||
if (m_is_enabled_tick_manipulation)
|
||||
if (m_draw_mode == dmRegular)
|
||||
draw_action_icon(dc, pt_beg, pt_end);
|
||||
}
|
||||
}
|
||||
|
@ -612,10 +625,10 @@ void Control::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& hig
|
|||
|
||||
void Control::draw_ticks(wxDC& dc)
|
||||
{
|
||||
if (!m_is_enabled_tick_manipulation)
|
||||
if (m_draw_mode == dmSlaPrint)
|
||||
return;
|
||||
|
||||
dc.SetPen(m_is_enabled_tick_manipulation ? DARK_GREY_PEN : LIGHT_GREY_PEN );
|
||||
dc.SetPen(m_draw_mode == dmRegular ? DARK_GREY_PEN : LIGHT_GREY_PEN );
|
||||
int height, width;
|
||||
get_size(&width, &height);
|
||||
const wxCoord mid = is_horizontal() ? 0.5*height : 0.5*width;
|
||||
|
@ -633,7 +646,11 @@ void Control::draw_ticks(wxDC& dc)
|
|||
|
||||
// get icon name if it is
|
||||
std::string icon_name;
|
||||
if (tick.gcode == ColorChangeCode || tick.gcode == ToolChangeCode) {
|
||||
|
||||
// if we have non-regular draw mode, all ticks should be marked with error icon
|
||||
if (m_draw_mode != dmRegular)
|
||||
icon_name = focused_tick ? "error_tick_f" : "error_tick";
|
||||
else if (tick.gcode == ColorChangeCode || tick.gcode == ToolChangeCode) {
|
||||
if (m_ticks.is_conflict_tick(tick, m_mode, m_only_extruder, m_values[tick.tick]))
|
||||
icon_name = focused_tick ? "error_tick_f" : "error_tick";
|
||||
}
|
||||
|
@ -666,7 +683,7 @@ std::string Control::get_color_for_tool_change_tick(std::set<TickCode>::const_it
|
|||
return it_n->color;
|
||||
}
|
||||
|
||||
return it->color;
|
||||
return m_extruder_colors[current_extruder-1]; // return a color for a specific extruder from the colors list
|
||||
}
|
||||
|
||||
std::string Control::get_color_for_color_change_tick(std::set<TickCode>::const_iterator it) const
|
||||
|
@ -682,6 +699,8 @@ std::string Control::get_color_for_color_change_tick(std::set<TickCode>::const_i
|
|||
return it->color;
|
||||
break;
|
||||
}
|
||||
if (it_n->gcode == ColorChangeCode && it_n->extruder == it->extruder)
|
||||
return it->color;
|
||||
}
|
||||
if (!is_tool_change && it->extruder == def_extruder)
|
||||
return it->color;
|
||||
|
@ -705,7 +724,7 @@ wxRect Control::get_colored_band_rect()
|
|||
|
||||
void Control::draw_colored_band(wxDC& dc)
|
||||
{
|
||||
if (!m_is_enabled_tick_manipulation)
|
||||
if (m_draw_mode != dmRegular)
|
||||
return;
|
||||
|
||||
auto draw_band = [](wxDC& dc, const wxColour& clr, const wxRect& band_rc)
|
||||
|
@ -725,7 +744,7 @@ void Control::draw_colored_band(wxDC& dc)
|
|||
}
|
||||
|
||||
const int default_color_idx = m_mode==t_mode::MultiAsSingle ? std::max<int>(m_only_extruder - 1, 0) : 0;
|
||||
draw_band(dc, wxColour(GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config()[default_color_idx]), main_band);
|
||||
draw_band(dc, wxColour(m_extruder_colors[default_color_idx]), main_band);
|
||||
|
||||
std::set<TickCode>::const_iterator tick_it = m_ticks.ticks.begin();
|
||||
|
||||
|
@ -771,7 +790,7 @@ void Control::draw_one_layer_icon(wxDC& dc)
|
|||
|
||||
void Control::draw_revert_icon(wxDC& dc)
|
||||
{
|
||||
if (m_ticks.empty() || !m_is_enabled_tick_manipulation)
|
||||
if (m_ticks.empty() || m_draw_mode != dmRegular)
|
||||
return;
|
||||
|
||||
int width, height;
|
||||
|
@ -804,7 +823,7 @@ void Control::draw_cog_icon(wxDC& dc)
|
|||
|
||||
void Control::update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection)
|
||||
{
|
||||
const wxRect& rect = wxRect(begin_x, begin_y, m_thumb_size.x, int(m_thumb_size.y*0.5));
|
||||
const wxRect& rect = wxRect(begin_x, begin_y + (selection == ssLower ? int(m_thumb_size.y * 0.5) : 0), m_thumb_size.x, int(m_thumb_size.y*0.5));
|
||||
if (selection == ssLower)
|
||||
m_rect_lower_thumb = rect;
|
||||
else
|
||||
|
@ -822,10 +841,15 @@ int Control::get_value_from_position(const wxCoord x, const wxCoord y)
|
|||
return int(m_min_value + double(height - SLIDER_MARGIN - y) / step + 0.5);
|
||||
}
|
||||
|
||||
void Control::detect_selected_slider(const wxPoint& pt)
|
||||
bool Control::detect_selected_slider(const wxPoint& pt)
|
||||
{
|
||||
m_selection = is_point_in_rect(pt, m_rect_lower_thumb) ? ssLower :
|
||||
is_point_in_rect(pt, m_rect_higher_thumb) ? ssHigher : ssUndef;
|
||||
if (is_point_in_rect(pt, m_rect_lower_thumb))
|
||||
m_selection = ssLower;
|
||||
else if(is_point_in_rect(pt, m_rect_higher_thumb))
|
||||
m_selection = ssHigher;
|
||||
else
|
||||
return false; // pt doesn't referenced to any thumb
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Control::is_point_in_rect(const wxPoint& pt, const wxRect& rect)
|
||||
|
@ -880,7 +904,7 @@ void Control::OnLeftDown(wxMouseEvent& event)
|
|||
m_mouse = maOneLayerIconClick;
|
||||
else if (is_point_in_rect(pos, m_rect_cog_icon))
|
||||
m_mouse = maCogIconClick;
|
||||
else if (m_is_enabled_tick_manipulation)
|
||||
else if (m_draw_mode == dmRegular)
|
||||
{
|
||||
if (is_point_in_rect(pos, m_rect_tick_action)) {
|
||||
auto it = m_ticks.ticks.find(TickCode{ m_selection == ssLower ? m_lower_value : m_higher_value });
|
||||
|
@ -890,6 +914,9 @@ void Control::OnLeftDown(wxMouseEvent& event)
|
|||
m_mouse = maRevertIconClick;
|
||||
}
|
||||
|
||||
if (m_mouse == maNone)
|
||||
detect_selected_slider(pos);
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
@ -931,6 +958,8 @@ wxString Control::get_tooltip(int tick/*=-1*/)
|
|||
if (m_focus == fiColorBand)
|
||||
return m_mode != t_mode::SingleExtruder ? "" :
|
||||
_(L("Edit current color - Right click the colored slider segment"));
|
||||
if (m_draw_mode == dmSlaPrint)
|
||||
return ""; // no drawn ticks and no tooltips for them in SlaPrinting mode
|
||||
|
||||
wxString tooltip;
|
||||
const auto tick_code_it = m_ticks.ticks.find(TickCode{tick});
|
||||
|
@ -953,9 +982,9 @@ wxString Control::get_tooltip(int tick/*=-1*/)
|
|||
// Show list of actions with new tick
|
||||
tooltip += ( m_mode == t_mode::MultiAsSingle ?
|
||||
_(L("Add extruder change - Left click")) :
|
||||
m_mode == t_mode::SingleExtruder ?
|
||||
_(L("Add color change - Left click for predefined color or"
|
||||
"Shift + Left click for custom color selection")) :
|
||||
m_mode == t_mode::SingleExtruder ?
|
||||
_(L("Add color change - Left click for predefined color or "
|
||||
"Shift + Left click for custom color selection")) :
|
||||
_(L("Add color change - Left click")) ) + " " +
|
||||
_(L("or press \"+\" key")) + "\n" + (
|
||||
is_osx ?
|
||||
|
@ -965,18 +994,23 @@ wxString Control::get_tooltip(int tick/*=-1*/)
|
|||
|
||||
if (tick_code_it != m_ticks.ticks.end()) // tick exists
|
||||
{
|
||||
if (m_draw_mode == dmSequentialFffPrint)
|
||||
return _(L("The sequential print is on.\n"
|
||||
"It's impossible to apply any custom G-code for objects printing sequentually.\n"
|
||||
"This code won't be processed during G-code generation."));
|
||||
|
||||
// Show custom Gcode as a first string of tooltop
|
||||
tooltip = " ";
|
||||
tooltip += tick_code_it->gcode == ColorChangeCode ? (
|
||||
m_mode == t_mode::SingleExtruder ?
|
||||
tooltip += tick_code_it->gcode == ColorChangeCode ? ( m_mode == t_mode::SingleExtruder ?
|
||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\") for Extruder %2%"))) %
|
||||
tick_code_it->gcode % tick_code_it->extruder).str()) ) :
|
||||
tick_code_it->gcode % tick_code_it->extruder).str()) ) :
|
||||
tick_code_it->gcode == PausePrintCode ?
|
||||
from_u8((boost::format(_utf8(L("Pause print (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
||||
from_u8((boost::format(_utf8(L("Pause print (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
||||
tick_code_it->gcode == ToolChangeCode ?
|
||||
from_u8((boost::format(_utf8(L("Extruder (tool) is changed to Extruder \"%1%\""))) % tick_code_it->extruder ).str()) :
|
||||
from_u8((boost::format(_utf8(L("\"%1%\""))) % tick_code_it->gcode ).str()) ;
|
||||
from_u8((boost::format(_utf8(L("Extruder (tool) is changed to Extruder \"%1%\""))) %
|
||||
tick_code_it->extruder ).str()) :
|
||||
from_u8(tick_code_it->gcode);
|
||||
|
||||
// If tick is marked as a conflict (exclamation icon),
|
||||
// we should to explain why
|
||||
|
@ -1031,11 +1065,7 @@ void Control::OnMotion(wxMouseEvent& event)
|
|||
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
|
||||
int tick = -1;
|
||||
|
||||
/* Note: Checking "!m_is_one_layer" is commented now because of
|
||||
* it looks like unnecessary and cause a tooltip "One layer" showing when OneLayerLock is on
|
||||
* #ysFIXME : Delete it after testing
|
||||
* */
|
||||
if (!m_is_left_down/* && !m_is_one_layer*/)
|
||||
if (!m_is_left_down && !m_is_right_down)
|
||||
{
|
||||
if (is_point_in_rect(pos, m_rect_one_layer_icon))
|
||||
m_focus = fiOneLayerIcon;
|
||||
|
@ -1094,6 +1124,8 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current
|
|||
{
|
||||
std::array<int, 2> active_extruders = get_active_extruders_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
|
||||
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
|
||||
|
||||
wxMenu* change_extruder_menu = new wxMenu();
|
||||
|
||||
for (int i = 1; i <= extruders_cnt; i++)
|
||||
|
@ -1104,7 +1136,7 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current
|
|||
|
||||
if (m_mode == t_mode::MultiAsSingle)
|
||||
append_menu_item(change_extruder_menu, wxID_ANY, item_name, "",
|
||||
[this, i](wxCommandEvent&) { add_code_as_tick(ToolChangeCode, i); }, "", menu,
|
||||
[this, i](wxCommandEvent&) { add_code_as_tick(ToolChangeCode, i); }, *icons[i-1], menu,
|
||||
[is_active_extruder]() { return !is_active_extruder; }, GUI::wxGetApp().plater());
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1201,7 @@ void Control::OnLeftUp(wxMouseEvent& event)
|
|||
add_current_tick();
|
||||
break;
|
||||
case maCogIconClick :
|
||||
if (m_mode == t_mode::MultiAsSingle)
|
||||
if (m_mode == t_mode::MultiAsSingle && m_draw_mode == dmRegular)
|
||||
show_cog_icon_context_menu();
|
||||
else
|
||||
jump_to_print_z();
|
||||
|
@ -1320,23 +1352,19 @@ void Control::OnRightDown(wxMouseEvent& event)
|
|||
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
|
||||
|
||||
m_mouse = maNone;
|
||||
if (m_is_enabled_tick_manipulation) {
|
||||
if (m_draw_mode == dmRegular) {
|
||||
if (is_point_in_rect(pos, m_rect_tick_action))
|
||||
{
|
||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||
m_mouse = m_ticks.ticks.find(TickCode{ tick }) == m_ticks.ticks.end() ?
|
||||
maAddMenu : maEditMenu;
|
||||
}
|
||||
else if (m_mode == t_mode::SingleExtruder && is_point_in_rect(pos, get_colored_band_rect()))
|
||||
else if (m_mode == t_mode::SingleExtruder && !detect_selected_slider(pos) && is_point_in_rect(pos, get_colored_band_rect()))
|
||||
m_mouse = maForceColorEdit;
|
||||
else if (m_mode == t_mode::MultiAsSingle && is_point_in_rect(pos, m_rect_cog_icon))
|
||||
m_mouse = maCogIconMenu;
|
||||
}
|
||||
if (m_mouse != maNone)
|
||||
return;
|
||||
|
||||
detect_selected_slider(pos);
|
||||
if (!m_selection)
|
||||
if (m_mouse != maNone || !detect_selected_slider(pos))
|
||||
return;
|
||||
|
||||
if (m_selection == ssLower)
|
||||
|
@ -1619,7 +1647,7 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height)
|
|||
|
||||
static double get_print_z_to_jump(double active_print_z, double min_z, double max_z)
|
||||
{
|
||||
wxString msg_text = _(L("Enter the height you want to jump to")) + " :";
|
||||
wxString msg_text = _(L("Enter the height you want to jump to")) + ":";
|
||||
wxString msg_header = _(L("Jump to height"));
|
||||
wxString msg_in = GUI::double_to_string(active_print_z);
|
||||
|
||||
|
@ -1766,15 +1794,16 @@ void Control::discard_all_thicks()
|
|||
void Control::move_current_thumb_to_pos(wxPoint pos)
|
||||
{
|
||||
const int tick_val = get_tick_near_point(pos);
|
||||
const int mouse_val = tick_val >= 0 && m_is_enabled_tick_manipulation ? tick_val :
|
||||
const int mouse_val = tick_val >= 0 && m_draw_mode == dmRegular ? tick_val :
|
||||
get_value_from_position(pos);
|
||||
if (mouse_val >= 0)
|
||||
{
|
||||
// if (abs(mouse_val - m_lower_value) < abs(mouse_val - m_higher_value)) {
|
||||
if (mouse_val <= m_lower_value) {
|
||||
// if (mouse_val <= m_lower_value) {
|
||||
if (m_selection == ssLower) {
|
||||
SetLowerValue(mouse_val);
|
||||
correct_lower_value();
|
||||
m_selection = ssLower;
|
||||
// m_selection = ssLower;
|
||||
}
|
||||
else {
|
||||
SetHigherValue(mouse_val);
|
||||
|
@ -1801,15 +1830,13 @@ void Control::edit_extruder_sequence()
|
|||
int extruder = 0;
|
||||
const int extr_cnt = m_extruders_sequence.extruders.size();
|
||||
|
||||
std::vector<std::string> colors = GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
|
||||
while (tick <= m_max_value)
|
||||
{
|
||||
const int cur_extruder = m_extruders_sequence.extruders[extruder];
|
||||
|
||||
bool meaningless_tick = tick == 0.0 && cur_extruder == extruder;
|
||||
if (!meaningless_tick)
|
||||
m_ticks.ticks.emplace(TickCode{tick, ToolChangeCode, cur_extruder + 1, colors[cur_extruder]});
|
||||
m_ticks.ticks.emplace(TickCode{tick, ToolChangeCode, cur_extruder + 1, m_extruder_colors[cur_extruder]});
|
||||
|
||||
extruder++;
|
||||
if (extruder == extr_cnt)
|
||||
|
@ -1869,8 +1896,8 @@ bool Control::check_ticks_changed_event(const std::string& gcode)
|
|||
return true;
|
||||
|
||||
wxString message = (m_ticks.mode == t_mode::SingleExtruder ?
|
||||
_(L("The last color change data was saved for a single extruder printer profile.")) :
|
||||
_(L("The last color change data was saved for a multiple extruder printer profile."))
|
||||
_(L("The last color change data was saved for a single extruder printing.")) :
|
||||
_(L("The last color change data was saved for a multi extruder printing."))
|
||||
) + "\n" +
|
||||
_(L("Your current changes will delete all saved color changes.")) + "\n\n\t" +
|
||||
_(L("Are you sure you want to continue?"));
|
||||
|
@ -1889,7 +1916,7 @@ bool Control::check_ticks_changed_event(const std::string& gcode)
|
|||
_(L("The last color change data was saved for a multi extruder printing.")) + "\n\n" +
|
||||
_(L("Select YES if you want to delete all saved tool changes, \n\t"
|
||||
"NO if you want all tool changes switch to color changes, \n\t"
|
||||
"or CANCEL to leave it unchanged")) + "\n\n\t" +
|
||||
"or CANCEL to leave it unchanged.")) + "\n\n\t" +
|
||||
_(L("Do you want to delete all saved tool changes?"))
|
||||
) : ( // t_mode::MultiExtruder
|
||||
_(L("The last color change data was saved for a multi extruder printing with tool changes for whole print.")) + "\n\n" +
|
||||
|
@ -1924,8 +1951,7 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, const std::string& c
|
|||
return colors[m_default_color_idx % colors.size()];
|
||||
}
|
||||
|
||||
std::vector<std::string> colors = GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
std::string color = colors[extruder - 1];
|
||||
std::string color = (*m_colors)[extruder - 1];
|
||||
|
||||
if (code == ColorChangeCode)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,13 @@ enum MouseAction
|
|||
maRevertIconClick, // LeftMouseClick on "revert" icon
|
||||
};
|
||||
|
||||
enum DrawMode
|
||||
{
|
||||
dmRegular,
|
||||
dmSlaPrint,
|
||||
dmSequentialFffPrint,
|
||||
};
|
||||
|
||||
using t_mode = CustomGCode::Mode;
|
||||
|
||||
struct TickCode
|
||||
|
@ -88,6 +95,8 @@ class TickCodeInfo
|
|||
bool m_use_default_colors= false;
|
||||
int m_default_color_idx = 0;
|
||||
|
||||
std::vector<std::string>* m_colors {nullptr};
|
||||
|
||||
std::string get_color_for_tick(TickCode tick, const std::string& code, const int extruder);
|
||||
|
||||
public:
|
||||
|
@ -115,6 +124,8 @@ public:
|
|||
bool suppressed_plus () { return m_suppress_plus; }
|
||||
bool suppressed_minus() { return m_suppress_minus; }
|
||||
void set_default_colors(bool default_colors_on) { m_use_default_colors = default_colors_on; }
|
||||
|
||||
void set_extruder_colors(std::vector<std::string>* extruder_colors) { m_colors = extruder_colors; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -197,12 +208,12 @@ public:
|
|||
CustomGCode::Info GetTicksValues() const;
|
||||
void SetTicksValues(const Slic3r::CustomGCode::Info &custom_gcode_per_print_z);
|
||||
|
||||
void EnableTickManipulation(bool enable = true) { m_is_enabled_tick_manipulation = enable; }
|
||||
void DisableTickManipulation() { EnableTickManipulation(false); }
|
||||
void SetDrawMode(bool is_sla_print, bool is_sequential_print);
|
||||
|
||||
void SetManipulationMode(t_mode mode) { m_mode = mode; }
|
||||
t_mode GetManipulationMode() const { return m_mode; }
|
||||
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder);
|
||||
void SetExtruderColors(const std::vector<std::string>& extruder_colors);
|
||||
|
||||
bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; }
|
||||
bool is_one_layer() const { return m_is_one_layer; }
|
||||
|
@ -261,7 +272,7 @@ protected:
|
|||
void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const;
|
||||
|
||||
void update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection);
|
||||
void detect_selected_slider(const wxPoint& pt);
|
||||
bool detect_selected_slider(const wxPoint& pt);
|
||||
void correct_lower_value();
|
||||
void correct_higher_value();
|
||||
void move_current_thumb(const bool condition);
|
||||
|
@ -323,9 +334,10 @@ private:
|
|||
bool m_is_right_down = false;
|
||||
bool m_is_one_layer = false;
|
||||
bool m_is_focused = false;
|
||||
bool m_is_enabled_tick_manipulation = true;
|
||||
bool m_force_mode_apply = true;
|
||||
|
||||
DrawMode m_draw_mode = dmRegular;
|
||||
|
||||
t_mode m_mode = t_mode::SingleExtruder;
|
||||
int m_only_extruder = -1;
|
||||
|
||||
|
@ -350,6 +362,8 @@ private:
|
|||
std::vector<double> m_values;
|
||||
TickCodeInfo m_ticks;
|
||||
|
||||
std::vector<std::string> m_extruder_colors;
|
||||
|
||||
// control's view variables
|
||||
wxCoord SLIDER_MARGIN; // margin around slider
|
||||
|
||||
|
|
|
@ -79,6 +79,11 @@ void Field::PostInitialize()
|
|||
BUILD();
|
||||
}
|
||||
|
||||
// Values of width to alignments of fields
|
||||
int Field::def_width() { return wxOSX ? 8 : 7; }
|
||||
int Field::def_width_wider() { return 14; }
|
||||
int Field::def_width_thinner() { return 4; }
|
||||
|
||||
void Field::on_kill_focus()
|
||||
{
|
||||
// call the registered function if it is available
|
||||
|
@ -240,6 +245,8 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
|||
set_value(wxString::Format("%s%%", stVal), false/*true*/);
|
||||
str += "%%";
|
||||
}
|
||||
else
|
||||
set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "."
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,14 +374,23 @@ void TextCtrl::BUILD() {
|
|||
temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e)
|
||||
{
|
||||
e.Skip();
|
||||
#ifdef __WXOSX__
|
||||
// OSX issue: For some unknown reason wxEVT_KILL_FOCUS is emitted twice in a row
|
||||
// Thus, suppress its second call
|
||||
if (bKilledFocus) {
|
||||
bKilledFocus = false;
|
||||
return;
|
||||
}
|
||||
bKilledFocus = true;
|
||||
#endif // __WXOSX__
|
||||
|
||||
#if !defined(__WXGTK__)
|
||||
temp->GetToolTip()->Enable(true);
|
||||
#endif // __WXGTK__
|
||||
if (bEnterPressed) {
|
||||
if (bEnterPressed)
|
||||
bEnterPressed = false;
|
||||
return;
|
||||
}
|
||||
propagate_value();
|
||||
else
|
||||
propagate_value();
|
||||
}), temp->GetId());
|
||||
|
||||
// select all text using Ctrl+A
|
||||
|
@ -423,10 +439,12 @@ bool TextCtrl::value_was_changed()
|
|||
|
||||
void TextCtrl::propagate_value()
|
||||
{
|
||||
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type) && value_was_changed())
|
||||
on_change_field();
|
||||
else
|
||||
if (!is_defined_input_value<wxTextCtrl>(window, m_opt.type) )
|
||||
// on_kill_focus() cause a call of OptionsGroup::reload_config(),
|
||||
// Thus, do it only when it's really needed (when undefined value was input)
|
||||
on_kill_focus();
|
||||
else if (value_was_changed())
|
||||
on_change_field();
|
||||
}
|
||||
|
||||
void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) {
|
||||
|
|
|
@ -225,10 +225,10 @@ public:
|
|||
bool get_enter_pressed() const { return bEnterPressed; }
|
||||
void set_enter_pressed(bool pressed) { bEnterPressed = pressed; }
|
||||
|
||||
// Values of width to "systematic" alignments of fields
|
||||
static int def_width() { return 7; }
|
||||
static int def_width_wider() { return 14; }
|
||||
static int def_width_thinner() { return 4; }
|
||||
// Values of width to alignments of fields
|
||||
static int def_width() ;
|
||||
static int def_width_wider() ;
|
||||
static int def_width_thinner() ;
|
||||
|
||||
protected:
|
||||
RevertButton* m_Undo_btn = nullptr;
|
||||
|
@ -274,6 +274,11 @@ class TextCtrl : public Field {
|
|||
bool bChangedValueEvent = true;
|
||||
void change_field_value(wxEvent& event);
|
||||
#endif //__WXGTK__
|
||||
|
||||
#ifdef __WXOSX__
|
||||
bool bKilledFocus = false;
|
||||
#endif // __WXOSX__
|
||||
|
||||
public:
|
||||
TextCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
||||
TextCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
||||
|
|
|
@ -274,7 +274,7 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
|
|||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(_(L("Higher print quality versus higher print speed.")));
|
||||
ImGui::TextUnformatted(_(L("Higher print quality versus higher print speed.")).ToUTF8());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
|
@ -734,7 +734,7 @@ static void msw_disable_cleartype(wxFont &font)
|
|||
++ startpos_weight;
|
||||
size_t endpos_weight = font_desc.find(sep, startpos_weight);
|
||||
// Parse the weight field.
|
||||
unsigned int weight = atoi(font_desc(startpos_weight, endpos_weight - startpos_weight));
|
||||
unsigned int weight = wxAtoi(font_desc(startpos_weight, endpos_weight - startpos_weight));
|
||||
size_t startpos = endpos_weight;
|
||||
for (size_t i = 0; i < 6; ++ i)
|
||||
startpos = font_desc.find(sep, startpos + 1);
|
||||
|
@ -982,12 +982,17 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
|
|||
cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code")));
|
||||
|
||||
int cnt = custom_gcode_per_print_z.size();
|
||||
int color_change_idx = color_cnt - extruders_cnt;
|
||||
for (int i = cnt-1; i >= 0; --i)
|
||||
if (custom_gcode_per_print_z[i].gcode == ColorChangeCode) {
|
||||
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
|
||||
color_pos += 4;
|
||||
color_in_pos -= 4;
|
||||
cp_legend_items.emplace_back((boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
|
||||
|
||||
// create label for color change item
|
||||
std::string id_str = std::to_string(color_change_idx--) + ": ";
|
||||
|
||||
cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1297,7 +1302,7 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
|
|||
return owner.model_instance_id == id;
|
||||
});
|
||||
if (it != owners.end())
|
||||
it->print_order = _(L("Seq.")) + "#: " + std::to_string(i + 1);
|
||||
it->print_order = std::string((_(L("Seq."))).ToUTF8()) + "#: " + std::to_string(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3465,13 +3470,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
// if dragging over blank area with left button, rotate
|
||||
if (m_hover_volume_idxs.empty() && m_mouse.is_start_position_3D_defined())
|
||||
{
|
||||
const Vec3d& orig = m_mouse.drag.start_position_3D;
|
||||
double x = Geometry::deg2rad(pos(0) - orig(0)) * (double)TRACKBALLSIZE;
|
||||
double y = Geometry::deg2rad(pos(1) - orig(1)) * (double)TRACKBALLSIZE;
|
||||
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
|
||||
if (wxGetApp().plater()->get_mouse3d_controller().is_running() || (wxGetApp().app_config->get("use_free_camera") == "1"))
|
||||
m_camera.rotate_local_around_target(Vec3d(y, x, 0.0));
|
||||
// Virtual track ball (similar to the 3DConnexion mouse).
|
||||
m_camera.rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.));
|
||||
else
|
||||
m_camera.rotate_on_sphere(x, y, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
|
||||
m_camera.rotate_on_sphere(rot.x(), rot.y(), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA);
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
// Part of temporary hack to remove crash when closing on OSX 10.9.5
|
||||
#include <wx/platinfo.h>
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#endif // __APPLE__
|
||||
|
@ -111,6 +116,9 @@ void GLCanvas3DManager::GLInfo::detect() const
|
|||
|
||||
m_max_tex_size /= 2;
|
||||
|
||||
if (Slic3r::total_physical_memory() / (1024 * 1024 * 1024) < 6)
|
||||
m_max_tex_size /= 2;
|
||||
|
||||
if (GLEW_EXT_texture_filter_anisotropic)
|
||||
glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));
|
||||
|
||||
|
@ -192,6 +200,11 @@ GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas
|
|||
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
||||
GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None;
|
||||
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
GLCanvas3DManager::OSInfo GLCanvas3DManager::s_os_info;
|
||||
#endif // __APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
GLCanvas3DManager::GLCanvas3DManager()
|
||||
: m_context(nullptr)
|
||||
|
@ -223,6 +236,15 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLTo
|
|||
m_context = new wxGLContext(canvas);
|
||||
if (m_context == nullptr)
|
||||
return false;
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// Part of temporary hack to remove crash when closing on OSX 10.9.5
|
||||
s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion();
|
||||
s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion();
|
||||
s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion();
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
}
|
||||
|
||||
canvas3D->set_context(m_context);
|
||||
|
@ -307,6 +329,15 @@ void GLCanvas3DManager::destroy()
|
|||
{
|
||||
if (m_context != nullptr)
|
||||
{
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
// this is a temporary ugly hack to solve the crash happening when closing the application on OSX 10.9.5
|
||||
// the crash is inside wxGLContext destructor
|
||||
if (s_os_info.major == 10 && s_os_info.minor == 9 && s_os_info.micro == 5)
|
||||
return;
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,17 @@ public:
|
|||
void detect() const;
|
||||
};
|
||||
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
struct OSInfo
|
||||
{
|
||||
int major{ 0 };
|
||||
int minor{ 0 };
|
||||
int micro{ 0 };
|
||||
};
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
|
||||
private:
|
||||
enum EMultisampleState : unsigned char
|
||||
{
|
||||
|
@ -81,6 +92,11 @@ private:
|
|||
CanvasesMap m_canvases;
|
||||
wxGLContext* m_context;
|
||||
static GLInfo s_gl_info;
|
||||
#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
#ifdef __APPLE__
|
||||
static OSInfo s_os_info;
|
||||
#endif //__APPLE__
|
||||
#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5
|
||||
bool m_gl_initialized;
|
||||
static EMultisampleState s_multisample;
|
||||
static bool s_compressed_textures_supported;
|
||||
|
|
|
@ -229,18 +229,30 @@ void show_error(wxWindow* parent, const wxString& message)
|
|||
msg.ShowModal();
|
||||
}
|
||||
|
||||
void show_error(wxWindow* parent, const char* message)
|
||||
{
|
||||
assert(message);
|
||||
show_error(parent, wxString::FromUTF8(message));
|
||||
}
|
||||
|
||||
void show_error_id(int id, const std::string& message)
|
||||
{
|
||||
auto *parent = id != 0 ? wxWindow::FindWindowById(id) : nullptr;
|
||||
show_error(parent, from_u8(message));
|
||||
show_error(parent, message);
|
||||
}
|
||||
|
||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title)
|
||||
{
|
||||
wxMessageDialog msg_wingow(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION);
|
||||
wxMessageDialog msg_wingow(parent, message, wxString(SLIC3R_APP_NAME " - ") + (title.empty() ? _(L("Notice")) : title), wxOK | wxICON_INFORMATION);
|
||||
msg_wingow.ShowModal();
|
||||
}
|
||||
|
||||
void show_info(wxWindow* parent, const char* message, const char* title)
|
||||
{
|
||||
assert(message);
|
||||
show_info(parent, wxString::FromUTF8(message), title ? wxString::FromUTF8(title) : wxString());
|
||||
}
|
||||
|
||||
void warning_catcher(wxWindow* parent, const wxString& message)
|
||||
{
|
||||
wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING);
|
||||
|
|
|
@ -39,8 +39,12 @@ extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_
|
|||
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0);
|
||||
|
||||
void show_error(wxWindow* parent, const wxString& message);
|
||||
void show_error(wxWindow* parent, const char* message);
|
||||
inline void show_error(wxWindow* parent, const std::string& message) { show_error(parent, message.c_str()); }
|
||||
void show_error_id(int id, const std::string& message); // For Perl
|
||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title);
|
||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title = wxString());
|
||||
void show_info(wxWindow* parent, const char* message, const char* title = nullptr);
|
||||
inline void show_info(wxWindow* parent, const std::string& message,const std::string& title = std::string()) { show_info(parent, message.c_str(), title.c_str()); }
|
||||
void warning_catcher(wxWindow* parent, const wxString& message);
|
||||
|
||||
// Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items.
|
||||
|
|
|
@ -187,8 +187,8 @@ bool GUI_App::on_init_inner()
|
|||
wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir));
|
||||
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
// SetAppName(SLIC3R_APP_KEY);
|
||||
SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
SetAppName(SLIC3R_APP_KEY);
|
||||
// SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
|
||||
// Enable this to get the default Win32 COMCTRL32 behavior of static boxes.
|
||||
|
@ -244,7 +244,7 @@ bool GUI_App::on_init_inner()
|
|||
try {
|
||||
preset_bundle->load_presets(*app_config);
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, from_u8(ex.what()));
|
||||
show_error(nullptr, ex.what());
|
||||
}
|
||||
|
||||
register_dpi_event();
|
||||
|
@ -332,7 +332,11 @@ unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
|||
bool GUI_App::dark_mode()
|
||||
{
|
||||
#if __APPLE__
|
||||
return mac_dark_mode();
|
||||
// The check for dark mode returns false positive on 10.12 and 10.13,
|
||||
// which allowed setting dark menu bar and dock area, which is
|
||||
// is detected as dark mode. We must run on at least 10.14 where the
|
||||
// proper dark mode was first introduced.
|
||||
return wxPlatformInfo::Get().CheckOSVersion(10, 14) && mac_dark_mode();
|
||||
#else
|
||||
const unsigned luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
return luma < 128;
|
||||
|
@ -754,7 +758,7 @@ Tab* GUI_App::get_tab(Preset::Type type)
|
|||
{
|
||||
for (Tab* tab: tabs_list)
|
||||
if (tab->type() == type)
|
||||
return tab->complited() ? tab : nullptr; // To avoid actions with no-completed Tab
|
||||
return tab->completed() ? tab : nullptr; // To avoid actions with no-completed Tab
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -793,7 +797,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
auto local_menu = new wxMenu();
|
||||
wxWindowID config_id_base = wxWindow::NewControlId(int(ConfigMenuCnt));
|
||||
|
||||
const auto config_wizard_name = _(ConfigWizard::name(true).wx_str());
|
||||
const auto config_wizard_name = _(ConfigWizard::name(true));
|
||||
const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name);
|
||||
// Cmd+, is standard on OS X - what about other operating systems?
|
||||
local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
|
||||
|
@ -819,7 +823,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
|
||||
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), wxString::Format(_(L("%s View Mode")), SLIC3R_APP_NAME));
|
||||
local_menu->AppendSeparator();
|
||||
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language")));
|
||||
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("&Language")));
|
||||
local_menu->AppendSeparator();
|
||||
local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer &firmware")), _(L("Upload a firmware image into an Arduino based printer")));
|
||||
// TODO: for when we're able to flash dictionaries
|
||||
|
@ -1241,7 +1245,7 @@ void GUI_App::check_updates(const bool verbose)
|
|||
}
|
||||
}
|
||||
catch (const std::exception & ex) {
|
||||
show_error(nullptr, from_u8(ex.what()));
|
||||
show_error(nullptr, ex.what());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,7 +77,9 @@ static int extruders_count()
|
|||
|
||||
static void take_snapshot(const wxString& snapshot_name)
|
||||
{
|
||||
wxGetApp().plater()->take_snapshot(snapshot_name);
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater)
|
||||
plater->take_snapshot(snapshot_name);
|
||||
}
|
||||
|
||||
ObjectList::ObjectList(wxWindow* parent) :
|
||||
|
@ -287,6 +289,7 @@ void ObjectList::create_objects_ctrl()
|
|||
GetColumn(colName)->SetWidth(20*em);
|
||||
GetColumn(colPrint)->SetWidth(3*em);
|
||||
GetColumn(colExtruder)->SetWidth(8*em);
|
||||
GetColumn(colEditing) ->SetWidth(7*em);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1541,7 +1544,8 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
|||
// If there are selected more then one instance but not all of them
|
||||
// don't add settings menu items
|
||||
const Selection& selection = scene_selection();
|
||||
if (selection.is_multiple_full_instance() && !selection.is_single_full_object())
|
||||
if (selection.is_multiple_full_instance() && !selection.is_single_full_object() ||
|
||||
selection.is_multiple_volume() || selection.is_mixed() ) // more than one volume(part) is selected on the scene
|
||||
return nullptr;
|
||||
|
||||
const auto sel_vol = get_selected_model_volume();
|
||||
|
@ -1560,7 +1564,11 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
|||
|
||||
// Add frequently settings
|
||||
const ItemType item_type = m_objects_model->GetItemType(GetSelection());
|
||||
const bool is_object_settings = item_type & itObject || item_type & itInstance || selection.is_single_full_object();
|
||||
if (item_type == itUndef && !selection.is_single_full_object())
|
||||
return nullptr;
|
||||
const bool is_object_settings = item_type & itObject || item_type & itInstance ||
|
||||
// multi-selection in ObjectList, but full_object in Selection
|
||||
(item_type == itUndef && selection.is_single_full_object());
|
||||
create_freq_settings_popupmenu(menu, is_object_settings);
|
||||
|
||||
if (mode == comAdvanced)
|
||||
|
@ -1577,11 +1585,14 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
|||
return menu->Append(menu_item);
|
||||
}
|
||||
|
||||
wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu)
|
||||
wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu, wxWindow* parent/* = nullptr*/)
|
||||
{
|
||||
return append_menu_item(menu, wxID_ANY, _(L("Change type")), "",
|
||||
[this](wxCommandEvent&) { change_part_type(); }, "", menu);
|
||||
|
||||
[this](wxCommandEvent&) { change_part_type(); }, "", menu,
|
||||
[this]() {
|
||||
wxDataViewItem item = GetSelection();
|
||||
return item.IsOk() || m_objects_model->GetItemType(item) == itVolume;
|
||||
}, parent);
|
||||
}
|
||||
|
||||
wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent)
|
||||
|
@ -1656,35 +1667,51 @@ void ObjectList::append_menu_item_reload_from_disk(wxMenu* menu) const
|
|||
[]() { return wxGetApp().plater()->can_reload_from_disk(); }, wxGetApp().plater());
|
||||
}
|
||||
|
||||
void ObjectList::append_menu_item_change_extruder(wxMenu* menu) const
|
||||
void ObjectList::append_menu_item_change_extruder(wxMenu* menu)
|
||||
{
|
||||
const wxString name = _(L("Change extruder"));
|
||||
const std::vector<wxString> names = {_(L("Change extruder")), _(L("Set extruder for selected items")) };
|
||||
// Delete old menu item
|
||||
const int item_id = menu->FindItem(name);
|
||||
if (item_id != wxNOT_FOUND)
|
||||
menu->Destroy(item_id);
|
||||
for (const wxString& name : names) {
|
||||
const int item_id = menu->FindItem(name);
|
||||
if (item_id != wxNOT_FOUND)
|
||||
menu->Destroy(item_id);
|
||||
}
|
||||
|
||||
const int extruders_cnt = extruders_count();
|
||||
const wxDataViewItem item = GetSelection();
|
||||
if (item && extruders_cnt > 1)
|
||||
{
|
||||
DynamicPrintConfig& config = get_item_config(item);
|
||||
if (extruders_cnt <= 1)
|
||||
return;
|
||||
|
||||
const int initial_extruder = !config.has("extruder") ? 0 :
|
||||
config.option<ConfigOptionInt>("extruder")->value;
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
if (sels.IsEmpty())
|
||||
return;
|
||||
|
||||
wxMenu* extruder_selection_menu = new wxMenu();
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
|
||||
wxMenu* extruder_selection_menu = new wxMenu();
|
||||
const wxString& name = sels.Count()==1 ? names[0] : names[1];
|
||||
|
||||
for (int i = 0; i <= extruders_cnt; i++)
|
||||
{
|
||||
const wxString& item_name = i == 0 ? _(L("Default")) : wxString::Format("%d", i);
|
||||
|
||||
append_menu_radio_item(extruder_selection_menu, wxID_ANY, item_name, "",
|
||||
[this, i](wxCommandEvent&) { set_extruder_for_selected_items(i); }, menu)->Check(i == initial_extruder);
|
||||
}
|
||||
|
||||
menu->AppendSubMenu(extruder_selection_menu, name, _(L("Select new extruder for the object/part")));
|
||||
int initial_extruder = -1; // negative value for multiple object/part selection
|
||||
if (sels.Count()==1) {
|
||||
DynamicPrintConfig& config = get_item_config(sels[0]);
|
||||
initial_extruder = !config.has("extruder") ? 0 :
|
||||
config.option<ConfigOptionInt>("extruder")->value;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= extruders_cnt; i++)
|
||||
{
|
||||
bool is_active_extruder = i == initial_extruder;
|
||||
int icon_idx = i == 0 ? 0 : i - 1;
|
||||
|
||||
const wxString& item_name = (i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i)) +
|
||||
(is_active_extruder ? " (" + _(L("active")) + ")" : "");
|
||||
|
||||
append_menu_item(extruder_selection_menu, wxID_ANY, item_name, "",
|
||||
[this, i](wxCommandEvent&) { set_extruder_for_selected_items(i); }, *icons[icon_idx], menu,
|
||||
[is_active_extruder]() { return !is_active_extruder; }, GUI::wxGetApp().plater());
|
||||
|
||||
}
|
||||
|
||||
menu->AppendSubMenu(extruder_selection_menu, name);
|
||||
}
|
||||
|
||||
void ObjectList::append_menu_item_delete(wxMenu* menu)
|
||||
|
@ -3159,7 +3186,9 @@ void ObjectList::update_selections()
|
|||
|
||||
for (auto obj_ins : objects_content_list) {
|
||||
if (obj_ins.first == glv_obj_idx) {
|
||||
if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end()) {
|
||||
if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end() &&
|
||||
!selection.is_from_single_instance() ) // a case when volumes of different types are selected
|
||||
{
|
||||
if (glv_ins_idx == 0 && (*m_objects)[glv_obj_idx]->instances.size() == 1)
|
||||
sels.Add(m_objects_model->GetItemById(glv_obj_idx));
|
||||
else
|
||||
|
@ -3385,7 +3414,7 @@ bool ObjectList::check_last_selection(wxString& msg_str)
|
|||
(type & itInstance && !(m_selection_mode & smInstance))
|
||||
)
|
||||
{
|
||||
// Inform user why selection isn't complited
|
||||
// Inform user why selection isn't completed
|
||||
const wxString item_type = m_selection_mode & smInstance ? _(L("Object or Instance")) :
|
||||
m_selection_mode & smVolume ? _(L("Part")) : _(L("Layer"));
|
||||
|
||||
|
@ -3905,7 +3934,9 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event)
|
|||
m_last_selected_column = -1;
|
||||
#endif //__WXMSW__
|
||||
|
||||
wxGetApp().plater()->set_current_canvas_as_dirty();
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater)
|
||||
plater->set_current_canvas_as_dirty();
|
||||
}
|
||||
|
||||
void ObjectList::show_multi_selection_menu()
|
||||
|
@ -3921,9 +3952,7 @@ void ObjectList::show_multi_selection_menu()
|
|||
wxMenu* menu = new wxMenu();
|
||||
|
||||
if (extruders_count() > 1)
|
||||
append_menu_item(menu, wxID_ANY, _(L("Set extruder for selected items")),
|
||||
_(L("Select extruder number for selected objects and/or parts")),
|
||||
[this](wxCommandEvent&) { extruder_selection(); }, "", menu);
|
||||
append_menu_item_change_extruder(menu);
|
||||
|
||||
append_menu_item(menu, wxID_ANY, _(L("Reload from disk")), _(L("Reload the selected volumes from disk")),
|
||||
[this](wxCommandEvent&) { wxGetApp().plater()->reload_from_disk(); }, "", menu, []() {
|
||||
|
|
|
@ -241,14 +241,14 @@ public:
|
|||
wxMenuItem* append_menu_item_split(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu, wxWindow* parent);
|
||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu, wxWindow* parent = nullptr);
|
||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent);
|
||||
wxMenuItem* append_menu_item_printable(wxMenu* menu, wxWindow* parent);
|
||||
void append_menu_items_osx(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu);
|
||||
void append_menu_item_export_stl(wxMenu* menu) const;
|
||||
void append_menu_item_reload_from_disk(wxMenu* menu) const;
|
||||
void append_menu_item_change_extruder(wxMenu* menu) const;
|
||||
void append_menu_item_change_extruder(wxMenu* menu);
|
||||
void append_menu_item_delete(wxMenu* menu);
|
||||
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
|
||||
void create_object_popupmenu(wxMenu *menu);
|
||||
|
|
|
@ -595,7 +595,9 @@ void Preview::update_view_type(bool slice_completed)
|
|||
void Preview::create_double_slider()
|
||||
{
|
||||
m_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100);
|
||||
m_slider->EnableTickManipulation(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF);
|
||||
bool sla_print_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA;
|
||||
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
|
||||
m_slider->SetDrawMode(sla_print_technology, sequential_print);
|
||||
|
||||
m_double_slider_sizer->Add(m_slider, 0, wxEXPAND, 0);
|
||||
|
||||
|
@ -709,7 +711,11 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
|
|||
|
||||
m_slider->SetTicksValues(ticks_info_from_model);
|
||||
|
||||
m_slider->EnableTickManipulation(wxGetApp().plater()->printer_technology() == ptFFF);
|
||||
bool sla_print_technology = wxGetApp().plater()->printer_technology() == ptSLA;
|
||||
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
|
||||
m_slider->SetDrawMode(sla_print_technology, sequential_print);
|
||||
|
||||
m_slider->SetExtruderColors(wxGetApp().plater()->get_extruder_colors_from_plater_config());
|
||||
}
|
||||
|
||||
void Preview::update_double_slider_mode()
|
||||
|
|
|
@ -112,6 +112,9 @@ int get_dpi_for_window(wxWindow *window)
|
|||
#elif defined __APPLE__
|
||||
// TODO
|
||||
return DPI_DEFAULT;
|
||||
#else // freebsd and others
|
||||
// TODO
|
||||
return DPI_DEFAULT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -138,7 +134,7 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
|
|||
}
|
||||
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, CommonGizmosData* common_data_ptr)
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: m_parent(parent)
|
||||
, m_group_id(-1)
|
||||
, m_state(Off)
|
||||
|
@ -149,7 +145,6 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u
|
|||
, m_dragging(false)
|
||||
, m_imgui(wxGetApp().imgui())
|
||||
, m_first_input_window_render(true)
|
||||
, m_c(common_data_ptr)
|
||||
{
|
||||
::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 4 * sizeof(float));
|
||||
::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 4 * sizeof(float));
|
||||
|
@ -306,88 +301,5 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* model_object)
|
||||
{
|
||||
recent_update = false;
|
||||
|
||||
if (m_model_object != model_object
|
||||
|| (model_object && m_model_object_id != model_object->id())) {
|
||||
m_model_object = model_object;
|
||||
m_print_object_idx = -1;
|
||||
m_mesh_raycaster.reset();
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = nullptr;
|
||||
m_mesh = nullptr;
|
||||
m_backend_mesh_transformed.clear();
|
||||
if (m_model_object) {
|
||||
m_active_instance = canvas.get_selection().get_instance_idx();
|
||||
m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius();
|
||||
}
|
||||
|
||||
recent_update = true;
|
||||
}
|
||||
|
||||
|
||||
if (! m_model_object || ! canvas.get_selection().is_from_single_instance())
|
||||
return false;
|
||||
|
||||
int old_po_idx = m_print_object_idx;
|
||||
|
||||
// First we need a pointer to the respective SLAPrintObject. The index into objects vector is
|
||||
// cached so we don't have todo it on each render. We only search for the po if needed:
|
||||
if (m_print_object_idx < 0 || (int)canvas.sla_print()->objects().size() != m_print_objects_count) {
|
||||
m_print_objects_count = canvas.sla_print()->objects().size();
|
||||
m_print_object_idx = -1;
|
||||
for (const SLAPrintObject* po : canvas.sla_print()->objects()) {
|
||||
++m_print_object_idx;
|
||||
if (po->model_object()->id() == m_model_object->id())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_mesh = nullptr;
|
||||
// Load either the model_object mesh, or one provided by the backend
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
// The backend mesh needs to be transformed and because a pointer to it is
|
||||
// saved, a copy is stored as a member (FIXME)
|
||||
if (m_print_object_idx >=0) {
|
||||
const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx];
|
||||
if (po->is_step_done(slaposDrillHoles)) {
|
||||
m_backend_mesh_transformed = po->get_mesh_to_print();
|
||||
m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse());
|
||||
m_mesh = &m_backend_mesh_transformed;
|
||||
m_has_drilled_mesh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_mesh) {
|
||||
m_mesh = &m_model_object->volumes.front()->mesh();
|
||||
m_backend_mesh_transformed.clear();
|
||||
m_has_drilled_mesh = false;
|
||||
}
|
||||
|
||||
m_model_object_id = m_model_object->id();
|
||||
|
||||
if (m_mesh != m_old_mesh) {
|
||||
wxBusyCursor wait;
|
||||
m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh));
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = m_mesh;
|
||||
m_clipping_plane_distance = 0.f;
|
||||
m_clipping_plane_distance_stash = 0.f;
|
||||
recent_update = true;
|
||||
return true;
|
||||
}
|
||||
if (! recent_update)
|
||||
recent_update = m_print_object_idx < 0 && old_po_idx >= 0;
|
||||
|
||||
return recent_update;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -30,7 +30,6 @@ static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|||
|
||||
|
||||
class ImGuiWrapper;
|
||||
class CommonGizmosData;
|
||||
class GLCanvas3D;
|
||||
class ClippingPlane;
|
||||
|
||||
|
@ -101,13 +100,11 @@ protected:
|
|||
mutable std::vector<Grabber> m_grabbers;
|
||||
ImGuiWrapper* m_imgui;
|
||||
bool m_first_input_window_render;
|
||||
CommonGizmosData* m_c = nullptr;
|
||||
|
||||
public:
|
||||
GLGizmoBase(GLCanvas3D& parent,
|
||||
const std::string& icon_filename,
|
||||
unsigned int sprite_id,
|
||||
CommonGizmosData* common_data = nullptr);
|
||||
unsigned int sprite_id);
|
||||
virtual ~GLGizmoBase() {}
|
||||
|
||||
bool init() { return on_init(); }
|
||||
|
@ -185,57 +182,6 @@ protected:
|
|||
// were not interpolated by alpha blending or multi sampling.
|
||||
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
class MeshRaycaster;
|
||||
class MeshClipper;
|
||||
|
||||
class CommonGizmosData {
|
||||
public:
|
||||
const TriangleMesh* mesh() const {
|
||||
return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh));
|
||||
}
|
||||
|
||||
bool update_from_backend(GLCanvas3D& canvas, ModelObject* model_object);
|
||||
|
||||
bool recent_update = false;
|
||||
|
||||
|
||||
|
||||
ModelObject* m_model_object = nullptr;
|
||||
const TriangleMesh* m_mesh;
|
||||
std::unique_ptr<MeshRaycaster> m_mesh_raycaster;
|
||||
std::unique_ptr<MeshClipper> m_object_clipper;
|
||||
std::unique_ptr<MeshClipper> m_supports_clipper;
|
||||
|
||||
//std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
||||
//std::unique_ptr<GLVolume> m_volume_with_cavity;
|
||||
|
||||
int m_active_instance = -1;
|
||||
float m_active_instance_bb_radius = 0;
|
||||
ObjectID m_model_object_id = 0;
|
||||
int m_print_object_idx = -1;
|
||||
int m_print_objects_count = -1;
|
||||
int m_old_timestamp = -1;
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
|
||||
void stash_clipping_plane() {
|
||||
m_clipping_plane_distance_stash = m_clipping_plane_distance;
|
||||
}
|
||||
|
||||
void unstash_clipping_plane() {
|
||||
m_clipping_plane_distance = m_clipping_plane_distance_stash;
|
||||
}
|
||||
|
||||
bool has_drilled_mesh() const { return m_has_drilled_mesh; }
|
||||
|
||||
private:
|
||||
const TriangleMesh* m_old_mesh;
|
||||
TriangleMesh m_backend_mesh_transformed;
|
||||
float m_clipping_plane_distance_stash = 0.f;
|
||||
bool m_has_drilled_mesh = false;
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, CommonGizmosData* cd)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id, cd)
|
||||
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
, m_quadric(nullptr)
|
||||
{
|
||||
m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
// using GLU_FILL does not work when the instance's transformation
|
||||
|
@ -58,19 +57,30 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&)
|
|||
{
|
||||
if (m_c->recent_update) {
|
||||
|
||||
if (m_state == On)
|
||||
m_c->build_AABB_if_needed();
|
||||
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
|
||||
// This is a temporary and not very nice hack, to make sure that
|
||||
// if the cp was moved by the data returned by backend, it will
|
||||
// remember its direction. FIXME: Refactor this mess and make
|
||||
// the clipping plane itself part of the shared data.
|
||||
if (! m_c->m_clipping_plane_was_moved && m_c->m_clipping_plane_distance == 0.25f)
|
||||
m_c->m_clipping_plane_was_moved = true;
|
||||
|
||||
|
||||
if (m_c->m_model_object) {
|
||||
reload_cache();
|
||||
if (m_c->has_drilled_mesh())
|
||||
m_holes_in_drilled_mesh = m_c->m_model_object->sla_drain_holes;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
else
|
||||
m_parent.toggle_model_objects_visibility(true, nullptr, -1);
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +252,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||
const sla::DrainHole& drain_hole = m_c->m_model_object->sla_drain_holes[i];
|
||||
const bool& point_selected = m_selected[i];
|
||||
|
||||
if (is_mesh_point_clipped((drain_hole.pos+HoleStickOutLength*drain_hole.normal).cast<double>()))
|
||||
if (is_mesh_point_clipped((drain_hole.pos+m_c->HoleStickOutLength*drain_hole.normal).cast<double>()))
|
||||
continue;
|
||||
|
||||
// First decide about the color of the point.
|
||||
|
@ -417,8 +427,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||
pos_and_normal.second(1)/scaling(1),
|
||||
pos_and_normal.second(2)/scaling(2));
|
||||
|
||||
m_c->m_model_object->sla_drain_holes.emplace_back(pos_and_normal.first + HoleStickOutLength * pos_and_normal.second/* normal_transformed.normalized()*/,
|
||||
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height+HoleStickOutLength);
|
||||
m_c->m_model_object->sla_drain_holes.emplace_back(pos_and_normal.first + m_c->HoleStickOutLength * pos_and_normal.second/* normal_transformed.normalized()*/,
|
||||
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height);
|
||||
m_selected.push_back(false);
|
||||
assert(m_selected.size() == m_c->m_model_object->sla_drain_holes.size());
|
||||
m_parent.set_as_dirty();
|
||||
|
@ -507,7 +517,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||
|
||||
if (action == SLAGizmoEventType::MouseWheelUp && control_down) {
|
||||
m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f);
|
||||
update_clipping_plane(true);
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
m_c->m_clipping_plane_was_moved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -545,7 +556,7 @@ void GLGizmoHollow::on_update(const UpdateData& data)
|
|||
std::pair<Vec3f, Vec3f> pos_and_normal;
|
||||
if (! unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
|
||||
return;
|
||||
m_c->m_model_object->sla_drain_holes[m_hover_id].pos = pos_and_normal.first + HoleStickOutLength * pos_and_normal.second;
|
||||
m_c->m_model_object->sla_drain_holes[m_hover_id].pos = pos_and_normal.first + m_c->HoleStickOutLength * pos_and_normal.second;
|
||||
m_c->m_model_object->sla_drain_holes[m_hover_id].normal = -pos_and_normal.second;
|
||||
}
|
||||
}
|
||||
|
@ -697,9 +708,9 @@ void GLGizmoHollow::on_render_input_window(float x, float y, float bottom_limit)
|
|||
double closing_d_max = opts[2].second->max;
|
||||
ConfigOptionMode closing_d_mode = opts[2].second->mode;
|
||||
|
||||
m_desc["offset"] = _(opts[0].second->label).ToUTF8() + wxString(":");
|
||||
m_desc["quality"] = _(opts[1].second->label).ToUTF8() + wxString(":");
|
||||
m_desc["closing_distance"] = _(opts[2].second->label).ToUTF8() + wxString(":");
|
||||
m_desc["offset"] = _(opts[0].second->label) + ":";
|
||||
m_desc["quality"] = _(opts[1].second->label) + ":";
|
||||
m_desc["closing_distance"] = _(opts[2].second->label) + ":";
|
||||
|
||||
|
||||
RENDER_AGAIN:
|
||||
|
@ -743,14 +754,16 @@ RENDER_AGAIN:
|
|||
}
|
||||
|
||||
m_imgui->disabled_begin(! m_enable_hollowing);
|
||||
|
||||
float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
m_imgui->text(m_desc.at("offset"));
|
||||
ImGui::SameLine(settings_sliders_left);
|
||||
ImGui::PushItemWidth(window_width - settings_sliders_left);
|
||||
ImGui::SliderFloat(" ", &offset, offset_min, offset_max, "%.1f");
|
||||
ImGui::SliderFloat(" ", &offset, offset_min, offset_max, "%.1f mm");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(_(opts[0].second->tooltip).ToUTF8());
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted((_utf8(opts[0].second->tooltip)).c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
bool slider_clicked = ImGui::IsItemClicked(); // someone clicked the slider
|
||||
|
@ -763,7 +776,9 @@ RENDER_AGAIN:
|
|||
ImGui::SliderFloat(" ", &quality, quality_min, quality_max, "%.1f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(_(opts[1].second->tooltip).ToUTF8());
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted((_utf8(opts[1].second->tooltip)).c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
slider_clicked |= ImGui::IsItemClicked();
|
||||
|
@ -774,10 +789,12 @@ RENDER_AGAIN:
|
|||
if (current_mode >= closing_d_mode) {
|
||||
m_imgui->text(m_desc.at("closing_distance"));
|
||||
ImGui::SameLine(settings_sliders_left);
|
||||
ImGui::SliderFloat(" ", &closing_d, closing_d_min, closing_d_max, "%.1f");
|
||||
ImGui::SliderFloat(" ", &closing_d, closing_d_min, closing_d_max, "%.1f mm");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(_(opts[2].second->tooltip).ToUTF8());
|
||||
ImGui::PushTextWrapPos(max_tooltip_width);
|
||||
ImGui::TextUnformatted((_utf8(opts[2].second->tooltip)).c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
slider_clicked |= ImGui::IsItemClicked();
|
||||
|
@ -823,7 +840,7 @@ RENDER_AGAIN:
|
|||
ImGui::PushItemWidth(window_width - diameter_slider_left);
|
||||
|
||||
float diam = 2.f * m_new_hole_radius;
|
||||
ImGui::SliderFloat("", &diam, 1.f, diameter_upper_cap, "%.1f");
|
||||
ImGui::SliderFloat("", &diam, 1.f, diameter_upper_cap, "%.1f mm");
|
||||
m_new_hole_radius = diam / 2.f;
|
||||
bool clicked = ImGui::IsItemClicked();
|
||||
bool edited = ImGui::IsItemEdited();
|
||||
|
@ -831,9 +848,9 @@ RENDER_AGAIN:
|
|||
|
||||
m_imgui->text(m_desc["hole_depth"]);
|
||||
ImGui::SameLine(diameter_slider_left);
|
||||
m_new_hole_height -= HoleStickOutLength;
|
||||
ImGui::SliderFloat(" ", &m_new_hole_height, 0.f, 10.f, "%.1f");
|
||||
m_new_hole_height += HoleStickOutLength;
|
||||
m_new_hole_height -= m_c->HoleStickOutLength;
|
||||
ImGui::SliderFloat(" ", &m_new_hole_height, 0.f, 10.f, "%.1f mm");
|
||||
m_new_hole_height += m_c->HoleStickOutLength;
|
||||
|
||||
clicked |= ImGui::IsItemClicked();
|
||||
edited |= ImGui::IsItemEdited();
|
||||
|
@ -897,8 +914,10 @@ RENDER_AGAIN:
|
|||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
update_clipping_plane(true);
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) {
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
m_c->m_clipping_plane_was_moved = true;
|
||||
}
|
||||
|
||||
// make sure supports are shown/hidden as appropriate
|
||||
if (m_imgui->checkbox(m_desc["show_supports"], m_show_supports)) {
|
||||
|
@ -981,7 +1000,9 @@ void GLGizmoHollow::on_set_state()
|
|||
//Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
||||
//m_c->update_from_backend(m_parent, m_c->m_model_object);
|
||||
m_c->unstash_clipping_plane();
|
||||
update_clipping_plane(m_c->m_clipping_plane_distance != 0.f);
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
|
||||
m_c->build_AABB_if_needed();
|
||||
|
||||
// we'll now reload support points:
|
||||
if (m_c->m_model_object)
|
||||
|
@ -1082,7 +1103,7 @@ void GLGizmoHollow::select_point(int i)
|
|||
|
||||
if (i == AllPoints) {
|
||||
m_new_hole_radius = m_c->m_model_object->sla_drain_holes[0].radius;
|
||||
m_new_hole_height = m_c->m_model_object->sla_drain_holes[0].height - HoleStickOutLength;
|
||||
m_new_hole_height = m_c->m_model_object->sla_drain_holes[0].height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1091,7 +1112,7 @@ void GLGizmoHollow::select_point(int i)
|
|||
m_selected[i] = true;
|
||||
m_selection_empty = false;
|
||||
m_new_hole_radius = m_c->m_model_object->sla_drain_holes[i].radius;
|
||||
m_new_hole_height = m_c->m_model_object->sla_drain_holes[i].height - HoleStickOutLength;
|
||||
m_new_hole_height = m_c->m_model_object->sla_drain_holes[i].height;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,6 +1149,13 @@ void GLGizmoHollow::update_clipping_plane(bool keep_normal) const
|
|||
}
|
||||
|
||||
|
||||
void GLGizmoHollow::on_set_hover_id()
|
||||
{
|
||||
if (int(m_c->m_model_object->sla_drain_holes.size()) <= m_hover_id)
|
||||
m_hover_id = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace GUI {
|
|||
class ClippingPlane;
|
||||
class MeshClipper;
|
||||
class MeshRaycaster;
|
||||
class CommonGizmosData;
|
||||
enum class SLAGizmoEventType : unsigned char;
|
||||
|
||||
class GLGizmoHollow : public GLGizmoBase
|
||||
|
@ -24,13 +25,11 @@ private:
|
|||
mutable double m_z_shift = 0.;
|
||||
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
||||
|
||||
const float HoleStickOutLength = 1.f;
|
||||
|
||||
GLUquadricObj* m_quadric;
|
||||
|
||||
|
||||
public:
|
||||
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, CommonGizmosData* cd);
|
||||
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
~GLGizmoHollow() override;
|
||||
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
|
@ -44,6 +43,7 @@ public:
|
|||
|
||||
bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); }
|
||||
void update_clipping_plane(bool keep_normal = false) const;
|
||||
void set_common_data_ptr(CommonGizmosData* ptr) { m_c = ptr; }
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
|
@ -74,6 +74,8 @@ private:
|
|||
|
||||
sla::DrainHoles m_holes_stash;
|
||||
|
||||
CommonGizmosData* m_c = nullptr;
|
||||
|
||||
//std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
|
@ -101,12 +103,7 @@ private:
|
|||
|
||||
protected:
|
||||
void on_set_state() override;
|
||||
void on_set_hover_id() override
|
||||
|
||||
{
|
||||
if (int(m_c->m_model_object->sla_drain_holes.size()) <= m_hover_id)
|
||||
m_hover_id = -1;
|
||||
}
|
||||
void on_set_hover_id() override;
|
||||
void on_start_dragging() override;
|
||||
void on_stop_dragging() override;
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
|
|
@ -22,12 +22,11 @@
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, CommonGizmosData* cd)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id, cd)
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
, m_quadric(nullptr)
|
||||
, m_its(nullptr)
|
||||
{
|
||||
m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
{
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
// using GLU_FILL does not work when the instance's transformation
|
||||
|
@ -64,19 +63,22 @@ bool GLGizmoSlaSupports::on_init()
|
|||
void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection)
|
||||
{
|
||||
if (m_c->recent_update) {
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
else
|
||||
m_parent.toggle_model_objects_visibility(true, nullptr, -1);
|
||||
if (m_state == On)
|
||||
m_c->build_AABB_if_needed();
|
||||
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
|
||||
disable_editing_mode();
|
||||
if (m_c->m_model_object)
|
||||
reload_cache();
|
||||
}
|
||||
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
|
||||
// If we triggered autogeneration before, check backend and fetch results if they are there
|
||||
if (m_c->m_model_object) {
|
||||
if (m_c->m_model_object->sla_points_status == sla::PointsStatus::Generating)
|
||||
|
@ -342,6 +344,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||
render_color[3] = 0.7f;
|
||||
glsafe(::glColor4fv(render_color));
|
||||
for (const sla::DrainHole& drain_hole : m_c->m_model_object->sla_drain_holes) {
|
||||
if (is_mesh_point_clipped((drain_hole.pos+m_c->HoleStickOutLength*drain_hole.normal).cast<double>()))
|
||||
continue;
|
||||
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2)));
|
||||
|
@ -587,7 +592,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
|
||||
if (action == SLAGizmoEventType::MouseWheelUp && control_down) {
|
||||
m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f);
|
||||
update_clipping_plane(true);
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
m_c->m_clipping_plane_was_moved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -913,8 +919,10 @@ RENDER_AGAIN:
|
|||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
update_clipping_plane(true);
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) {
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
m_c->m_clipping_plane_was_moved = true;
|
||||
}
|
||||
|
||||
|
||||
if (m_imgui->button("?")) {
|
||||
|
@ -999,7 +1007,9 @@ void GLGizmoSlaSupports::on_set_state()
|
|||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
||||
|
||||
m_c->unstash_clipping_plane();
|
||||
update_clipping_plane(m_c->m_clipping_plane_distance != 0.f);
|
||||
update_clipping_plane(m_c->m_clipping_plane_was_moved);
|
||||
|
||||
m_c->build_AABB_if_needed();
|
||||
|
||||
|
||||
// we'll now reload support points:
|
||||
|
@ -1007,9 +1017,10 @@ void GLGizmoSlaSupports::on_set_state()
|
|||
reload_cache();
|
||||
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
if (m_c->m_model_object /*&& ! m_c->m_cavity_mesh*/)
|
||||
if (m_c->m_model_object) {
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
|
||||
// Set default head diameter from config.
|
||||
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace GUI {
|
|||
class ClippingPlane;
|
||||
class MeshClipper;
|
||||
class MeshRaycaster;
|
||||
class CommonGizmosData;
|
||||
enum class SLAGizmoEventType : unsigned char;
|
||||
|
||||
class GLGizmoSlaSupports : public GLGizmoBase
|
||||
|
@ -69,7 +70,7 @@ private:
|
|||
};
|
||||
|
||||
public:
|
||||
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, CommonGizmosData* cd);
|
||||
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
~GLGizmoSlaSupports() override;
|
||||
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
|
@ -81,6 +82,7 @@ public:
|
|||
bool has_backend_supports() const;
|
||||
void reslice_SLA_supports(bool postpone_error_messages = false) const;
|
||||
void update_clipping_plane(bool keep_normal = false) const;
|
||||
void set_common_data_ptr(CommonGizmosData* ptr) { m_c = ptr; }
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
|
@ -116,6 +118,8 @@ private:
|
|||
bool m_selection_empty = true;
|
||||
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
|
||||
|
||||
CommonGizmosData* m_c = nullptr;
|
||||
|
||||
//mutable std::unique_ptr<MeshClipper> m_object_clipper;
|
||||
//mutable std::unique_ptr<MeshClipper> m_supports_clipper;
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <wx/glcanvas.h>
|
||||
|
@ -83,16 +85,18 @@ bool GLGizmosManager::init()
|
|||
return false;
|
||||
}
|
||||
|
||||
m_common_gizmos_data.reset(new CommonGizmosData());
|
||||
|
||||
// Order of gizmos in the vector must match order in EType!
|
||||
m_gizmos.emplace_back(new GLGizmoMove3D(m_parent, "move.svg", 0));
|
||||
m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, "scale.svg", 1));
|
||||
m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, "rotate.svg", 2));
|
||||
m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, "place.svg", 3));
|
||||
m_gizmos.emplace_back(new GLGizmoCut(m_parent, "cut.svg", 4));
|
||||
m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", 5, m_common_gizmos_data.get()));
|
||||
m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 6, m_common_gizmos_data.get()));
|
||||
m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", 5));
|
||||
m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 6));
|
||||
|
||||
m_common_gizmos_data.reset(new CommonGizmosData());
|
||||
dynamic_cast<GLGizmoHollow*>(m_gizmos[Hollow].get())->set_common_data_ptr(m_common_gizmos_data.get());
|
||||
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->set_common_data_ptr(m_common_gizmos_data.get());
|
||||
|
||||
for (auto& gizmo : m_gizmos) {
|
||||
if (! gizmo->init()) {
|
||||
|
@ -345,25 +349,18 @@ void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
|
|||
|
||||
void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
|
||||
{
|
||||
if (!m_enabled || m_gizmos.empty())
|
||||
if (! m_enabled
|
||||
|| m_gizmos.empty()
|
||||
|| wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
return;
|
||||
|
||||
m_common_gizmos_data->update_from_backend(m_parent, model_object);
|
||||
|
||||
auto* gizmo_supports = dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get());
|
||||
auto* gizmo_hollow = dynamic_cast<GLGizmoHollow*>(m_gizmos[Hollow].get());
|
||||
|
||||
|
||||
// Update common data for hollowing and sla support gizmos.
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) {
|
||||
if (m_common_gizmos_data->update_from_backend(m_parent, model_object)) {
|
||||
// FIXME: this is a hack to make that the clipping plane is
|
||||
// updated when the update set its position to zero. The clipping
|
||||
// plane itself should be common, including the update_function.
|
||||
// Then update_from_backend could do it itself.
|
||||
gizmo_supports->update_clipping_plane();
|
||||
gizmo_hollow->update_clipping_plane();
|
||||
}
|
||||
}
|
||||
|
||||
// note: sla support gizmo takes care of updating the common data.
|
||||
// following lines are thus dependent
|
||||
gizmo_supports->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
gizmo_hollow->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
}
|
||||
|
@ -1058,5 +1055,135 @@ bool GLGizmosManager::grabber_contains_mouse() const
|
|||
return (curr != nullptr) ? (curr->get_hover_id() != -1) : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CommonGizmosData::CommonGizmosData()
|
||||
{
|
||||
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* model_object)
|
||||
{
|
||||
recent_update = false;
|
||||
bool object_changed = false;
|
||||
|
||||
if (m_model_object != model_object
|
||||
|| (model_object && m_model_object_id != model_object->id())) {
|
||||
m_model_object = model_object;
|
||||
m_print_object_idx = -1;
|
||||
m_mesh_raycaster.reset();
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = nullptr;
|
||||
m_mesh = nullptr;
|
||||
m_backend_mesh_transformed.clear();
|
||||
|
||||
object_changed = true;
|
||||
recent_update = true;
|
||||
}
|
||||
|
||||
if (m_model_object) {
|
||||
int active_inst = canvas.get_selection().get_instance_idx();
|
||||
if (m_active_instance != active_inst) {
|
||||
m_active_instance = active_inst;
|
||||
m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius();
|
||||
recent_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (! m_model_object || ! canvas.get_selection().is_from_single_instance())
|
||||
return false;
|
||||
|
||||
int old_po_idx = m_print_object_idx;
|
||||
|
||||
// First we need a pointer to the respective SLAPrintObject. The index into objects vector is
|
||||
// cached so we don't have todo it on each render. We only search for the po if needed:
|
||||
if (m_print_object_idx < 0 || (int)canvas.sla_print()->objects().size() != m_print_objects_count) {
|
||||
m_print_objects_count = canvas.sla_print()->objects().size();
|
||||
m_print_object_idx = -1;
|
||||
for (const SLAPrintObject* po : canvas.sla_print()->objects()) {
|
||||
++m_print_object_idx;
|
||||
if (po->model_object()->id() == m_model_object->id())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool mesh_exchanged = false;
|
||||
m_mesh = nullptr;
|
||||
// Load either the model_object mesh, or one provided by the backend
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
// The backend mesh needs to be transformed and because a pointer to it is
|
||||
// saved, a copy is stored as a member (FIXME)
|
||||
if (m_print_object_idx >=0) {
|
||||
const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx];
|
||||
if (po->is_step_done(slaposDrillHoles)) {
|
||||
m_backend_mesh_transformed = po->get_mesh_to_print();
|
||||
m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse());
|
||||
m_mesh = &m_backend_mesh_transformed;
|
||||
m_has_drilled_mesh = true;
|
||||
mesh_exchanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_mesh) {
|
||||
m_mesh = &m_model_object->volumes.front()->mesh();
|
||||
m_backend_mesh_transformed.clear();
|
||||
m_has_drilled_mesh = false;
|
||||
}
|
||||
|
||||
m_model_object_id = m_model_object->id();
|
||||
|
||||
if (m_mesh != m_old_mesh) {
|
||||
// Update clipping plane position.
|
||||
float new_clp_pos = m_clipping_plane_distance;
|
||||
if (object_changed) {
|
||||
new_clp_pos = 0.f;
|
||||
m_clipping_plane_was_moved = false;
|
||||
} else {
|
||||
// After we got a drilled mesh, move the cp to 25%. This only applies when
|
||||
// the hollowing gizmo is active and hollowing is enabled
|
||||
if (m_clipping_plane_distance == 0.f && mesh_exchanged && m_has_drilled_mesh) {
|
||||
const DynamicPrintConfig& cfg =
|
||||
(m_model_object && m_model_object->config.has("hollowing_enable"))
|
||||
? m_model_object->config
|
||||
: wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
|
||||
if (cfg.has("hollowing_enable") && cfg.opt_bool("hollowing_enable")
|
||||
&& canvas.get_gizmos_manager().get_current_type() == GLGizmosManager::Hollow) {
|
||||
new_clp_pos = 0.25f;
|
||||
m_clipping_plane_was_moved = false; // so it uses current camera direction
|
||||
}
|
||||
}
|
||||
}
|
||||
m_clipping_plane_distance = new_clp_pos;
|
||||
m_clipping_plane_distance_stash = new_clp_pos;
|
||||
|
||||
m_schedule_aabb_calculation = true;
|
||||
recent_update = true;
|
||||
return true;
|
||||
}
|
||||
if (! recent_update)
|
||||
recent_update = m_print_object_idx < 0 && old_po_idx >= 0;
|
||||
|
||||
return recent_update;
|
||||
}
|
||||
|
||||
|
||||
void CommonGizmosData::build_AABB_if_needed()
|
||||
{
|
||||
if (! m_schedule_aabb_calculation)
|
||||
return;
|
||||
|
||||
wxBusyCursor wait;
|
||||
m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh));
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = m_mesh;
|
||||
m_schedule_aabb_calculation = false;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -227,6 +227,65 @@ private:
|
|||
bool grabber_contains_mouse() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MeshRaycaster;
|
||||
class MeshClipper;
|
||||
|
||||
// This class is only for sharing SLA related data between SLA gizmos
|
||||
// and its synchronization with backend data. It should not be misused
|
||||
// for anything else.
|
||||
class CommonGizmosData {
|
||||
public:
|
||||
CommonGizmosData();
|
||||
const TriangleMesh* mesh() const {
|
||||
return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh));
|
||||
}
|
||||
|
||||
bool update_from_backend(GLCanvas3D& canvas, ModelObject* model_object);
|
||||
bool recent_update = false;
|
||||
static constexpr float HoleStickOutLength = 1.f;
|
||||
|
||||
ModelObject* m_model_object = nullptr;
|
||||
const TriangleMesh* m_mesh;
|
||||
std::unique_ptr<MeshRaycaster> m_mesh_raycaster;
|
||||
std::unique_ptr<MeshClipper> m_object_clipper;
|
||||
std::unique_ptr<MeshClipper> m_supports_clipper;
|
||||
|
||||
//std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
||||
//std::unique_ptr<GLVolume> m_volume_with_cavity;
|
||||
|
||||
int m_active_instance = -1;
|
||||
float m_active_instance_bb_radius = 0;
|
||||
ObjectID m_model_object_id = 0;
|
||||
int m_print_object_idx = -1;
|
||||
int m_print_objects_count = -1;
|
||||
int m_old_timestamp = -1;
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
bool m_clipping_plane_was_moved = false;
|
||||
|
||||
void stash_clipping_plane() {
|
||||
m_clipping_plane_distance_stash = m_clipping_plane_distance;
|
||||
}
|
||||
|
||||
void unstash_clipping_plane() {
|
||||
m_clipping_plane_distance = m_clipping_plane_distance_stash;
|
||||
}
|
||||
|
||||
bool has_drilled_mesh() const { return m_has_drilled_mesh; }
|
||||
|
||||
void build_AABB_if_needed();
|
||||
|
||||
private:
|
||||
const TriangleMesh* m_old_mesh;
|
||||
TriangleMesh m_backend_mesh_transformed;
|
||||
float m_clipping_plane_distance_stash = 0.f;
|
||||
bool m_has_drilled_mesh = false;
|
||||
bool m_schedule_aabb_calculation = false;
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
@ -40,21 +40,25 @@ namespace I18N {
|
|||
inline wxString translate(const wchar_t *s) { return wxGetTranslation(s); }
|
||||
inline wxString translate(const std::string &s) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)); }
|
||||
inline wxString translate(const std::wstring &s) { return wxGetTranslation(s.c_str()); }
|
||||
inline wxString translate(const wxString &s) { return wxGetTranslation(s); }
|
||||
|
||||
inline wxString translate(const char *s, const char *plural, unsigned int n) { return wxGetTranslation(wxString(s, wxConvUTF8), wxString(plural, wxConvUTF8), n); }
|
||||
inline wxString translate(const wchar_t *s, const wchar_t *plural, unsigned int n) { return wxGetTranslation(s, plural, n); }
|
||||
inline wxString translate(const std::string &s, const std::string &plural, unsigned int n) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8), wxString(plural.c_str(), wxConvUTF8), n); }
|
||||
inline wxString translate(const std::wstring &s, const std::wstring &plural, unsigned int n) { return wxGetTranslation(s.c_str(), plural.c_str(), n); }
|
||||
inline wxString translate(const wxString &s, const wxString &plural, unsigned int n) { return wxGetTranslation(s, plural, n); }
|
||||
|
||||
inline std::string translate_utf8(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wchar_t *s) { return wxGetTranslation(s).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::string &s) { return wxGetTranslation(wxString(s.c_str(), wxConvUTF8)).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::wstring &s) { return wxGetTranslation(s.c_str()).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wxString &s) { return wxGetTranslation(s).ToUTF8().data(); }
|
||||
|
||||
inline std::string translate_utf8(const char *s, const char *plural, unsigned int n) { return translate(s, plural, n).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wchar_t *s, const wchar_t *plural, unsigned int n) { return translate(s, plural, n).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::string &s, const std::string &plural, unsigned int n) { return translate(s, plural, n).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::wstring &s, const std::wstring &plural, unsigned int n) { return translate(s, plural, n).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wxString &s, const wxString &plural, unsigned int n) { return translate(s, plural, n).ToUTF8().data(); }
|
||||
|
||||
#if wxCHECK_VERSION(3, 1, 1)
|
||||
#define _wxGetTranslation_ctx(S, CTX) wxGetTranslation((S), wxEmptyString, (CTX))
|
||||
|
@ -66,11 +70,13 @@ namespace I18N {
|
|||
inline wxString translate(const wchar_t *s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx); }
|
||||
inline wxString translate(const std::string &s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s.c_str(), wxConvUTF8), ctx); }
|
||||
inline wxString translate(const std::wstring &s, const char* ctx) { return _wxGetTranslation_ctx(s.c_str(), ctx); }
|
||||
inline wxString translate(const wxString &s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx); }
|
||||
|
||||
inline wxString translate_utf8(const char *s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s, wxConvUTF8), ctx).ToUTF8().data(); }
|
||||
inline wxString translate_utf8(const wchar_t *s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx).ToUTF8().data(); }
|
||||
inline wxString translate_utf8(const std::string &s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s.c_str(), wxConvUTF8), ctx).ToUTF8().data(); }
|
||||
inline wxString translate_utf8(const std::wstring &s, const char* ctx) { return _wxGetTranslation_ctx(s.c_str(), ctx).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const char *s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s, wxConvUTF8), ctx).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wchar_t *s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::string &s, const char* ctx) { return _wxGetTranslation_ctx(wxString(s.c_str(), wxConvUTF8), ctx).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const std::wstring &s, const char* ctx) { return _wxGetTranslation_ctx(s.c_str(), ctx).ToUTF8().data(); }
|
||||
inline std::string translate_utf8(const wxString &s, const char* ctx) { return _wxGetTranslation_ctx(s, ctx).ToUTF8().data(); }
|
||||
|
||||
#undef _wxGetTranslation_ctx
|
||||
} // namespace I18N
|
||||
|
|
|
@ -286,6 +286,12 @@ bool ImGuiWrapper::input_double(const std::string &label, const double &value, c
|
|||
return ImGui::InputDouble(label.c_str(), const_cast<double*>(&value), 0.0f, 0.0f, format.c_str());
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::input_double(const wxString &label, const double &value, const std::string &format)
|
||||
{
|
||||
auto label_utf8 = into_u8(label);
|
||||
return input_double(label_utf8, value, format);
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format)
|
||||
{
|
||||
bool value_changed = false;
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
bool button(const wxString &label);
|
||||
bool radio_button(const wxString &label, bool active);
|
||||
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
|
||||
bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f");
|
||||
bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f");
|
||||
bool checkbox(const wxString &label, bool &value);
|
||||
void text(const char *label);
|
||||
|
|
|
@ -158,7 +158,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ "Shift+A", L("Arrange selection") },
|
||||
{ "+", L("Add Instance of the selected object") },
|
||||
{ "-", L("Remove Instance of the selected object") },
|
||||
{ ctrl, L("Press to select multiple object\nor move multiple object with mouse") },
|
||||
{ ctrl, L("Press to select multiple objects\nor move multiple objects with mouse") },
|
||||
{ "Shift+", L("Press to activate selection rectangle") },
|
||||
{ alt, L("Press to activate deselection rectangle") },
|
||||
{ L("Arrow Up"), L("Move selection 10 mm in positive Y direction") },
|
||||
|
@ -192,7 +192,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
m_full_shortcuts.push_back(std::make_pair(_(L("Plater")), plater_shortcuts));
|
||||
|
||||
Shortcuts gizmos_shortcuts = {
|
||||
{ "Shift+", L("Press to to snap by 5% in Gizmo scale\nor to snap by 1mm in Gizmo move") },
|
||||
{ "Shift+", L("Press to snap by 5% in Gizmo scale\nor to snap by 1mm in Gizmo move") },
|
||||
{ "F", L("Scale selection to fit print volume\nin Gizmo scale") },
|
||||
{ ctrl, L("Press to activate one direction scaling in Gizmo scale") },
|
||||
{ alt, L("Press to scale (in Gizmo scale) or rotate (in Gizmo rotate)\nselected objects around their own center") },
|
||||
|
|
|
@ -143,6 +143,9 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
wxGetApp().persist_window_geometry(this, true);
|
||||
|
||||
update_ui_from_settings(); // FIXME (?)
|
||||
|
||||
if (m_plater != nullptr)
|
||||
m_plater->show_action_buttons(true);
|
||||
}
|
||||
|
||||
void MainFrame::update_title()
|
||||
|
@ -419,18 +422,19 @@ void MainFrame::init_menubar()
|
|||
m_plater->load_project(filename);
|
||||
else
|
||||
{
|
||||
wxMessageDialog msg(this, _(L("The selected project is no more available")), _(L("Error")));
|
||||
msg.ShowModal();
|
||||
|
||||
m_recent_projects.RemoveFileFromHistory(file_id);
|
||||
std::vector<std::string> recent_projects;
|
||||
size_t count = m_recent_projects.GetCount();
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
wxMessageDialog msg(this, _(L("The selected project is no longer available.\nDo you want to remove it from the recent projects list ?")), _(L("Error")), wxYES_NO | wxYES_DEFAULT);
|
||||
if (msg.ShowModal() == wxID_YES)
|
||||
{
|
||||
recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i)));
|
||||
m_recent_projects.RemoveFileFromHistory(file_id);
|
||||
std::vector<std::string> recent_projects;
|
||||
size_t count = m_recent_projects.GetCount();
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
recent_projects.push_back(into_u8(m_recent_projects.GetHistoryFile(i)));
|
||||
}
|
||||
wxGetApp().app_config->set_recent_projects(recent_projects);
|
||||
wxGetApp().app_config->save();
|
||||
}
|
||||
wxGetApp().app_config->set_recent_projects(recent_projects);
|
||||
wxGetApp().app_config->save();
|
||||
}
|
||||
}, wxID_FILE1, wxID_FILE9);
|
||||
|
||||
|
@ -1148,11 +1152,12 @@ void MainFrame::add_to_recent_projects(const wxString& filename)
|
|||
// Update the UI based on the current preferences.
|
||||
void MainFrame::update_ui_from_settings()
|
||||
{
|
||||
const bool bp_on = wxGetApp().app_config->get("background_processing") == "1";
|
||||
// const bool bp_on = wxGetApp().app_config->get("background_processing") == "1";
|
||||
// m_menu_item_reslice_now->Enable(!bp_on);
|
||||
m_plater->sidebar().show_reslice(!bp_on);
|
||||
m_plater->sidebar().show_export(bp_on);
|
||||
m_plater->sidebar().Layout();
|
||||
// m_plater->sidebar().show_reslice(!bp_on);
|
||||
// m_plater->sidebar().show_export(bp_on);
|
||||
// m_plater->sidebar().Layout();
|
||||
|
||||
if (m_plater)
|
||||
m_plater->update_ui_from_settings();
|
||||
for (auto tab: wxGetApp().tabs_list)
|
||||
|
|
|
@ -162,8 +162,8 @@ bool Mouse3DController::State::apply(Camera& camera)
|
|||
|
||||
if (has_rotation())
|
||||
{
|
||||
Vec3d rotation = (m_rotation_params.scale * m_rotation.queue.front()).cast<double>();
|
||||
camera.rotate_local_around_target(Vec3d(Geometry::deg2rad(rotation(0)), Geometry::deg2rad(-rotation(2)), Geometry::deg2rad(-rotation(1))));
|
||||
Vec3d rot = (m_rotation_params.scale * m_rotation.queue.front()).cast<double>() * (PI / 180.);
|
||||
camera.rotate_local_around_target(Vec3d(rot.x(), - rot.z(), rot.y()));
|
||||
m_rotation.queue.pop();
|
||||
ret = true;
|
||||
}
|
||||
|
|
|
@ -1185,6 +1185,26 @@ void ObjectDataViewModel::SetExtruder(const wxString& extruder, wxDataViewItem i
|
|||
SetValue(value, item, colExtruder);
|
||||
}
|
||||
|
||||
void ObjectDataViewModel::AddAllChildren(const wxDataViewItem& parent)
|
||||
{
|
||||
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)parent.GetID();
|
||||
if (!node || node->GetChildCount() == 0)
|
||||
return;
|
||||
|
||||
wxDataViewItemArray array;
|
||||
const size_t count = node->GetChildCount();
|
||||
for (size_t pos = 0; pos < count; pos++) {
|
||||
ObjectDataViewModelNode* child = node->GetChildren().Item(pos);
|
||||
array.Add(wxDataViewItem((void*)child));
|
||||
ItemAdded(parent, wxDataViewItem((void*)child));
|
||||
}
|
||||
|
||||
for (const auto item : array)
|
||||
AddAllChildren(item);
|
||||
|
||||
m_ctrl->Expand(parent);
|
||||
};
|
||||
|
||||
wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume_id,
|
||||
const int new_volume_id,
|
||||
const wxDataViewItem &parent)
|
||||
|
@ -1205,6 +1225,10 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume
|
|||
node_parent->Insert(deleted_node, new_volume_id+shift);
|
||||
ItemAdded(parent, wxDataViewItem(deleted_node));
|
||||
|
||||
// If some item has a children, just to add a deleted item is not enough on Linux
|
||||
// We should to add all its children separately
|
||||
AddAllChildren(wxDataViewItem(deleted_node));
|
||||
|
||||
//update volume_id value for child-nodes
|
||||
auto children = node_parent->GetChildren();
|
||||
int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id;
|
||||
|
@ -1227,6 +1251,10 @@ wxDataViewItem ObjectDataViewModel::ReorganizeObjects( const int current_id, co
|
|||
m_objects.emplace(m_objects.begin() + new_id, deleted_node);
|
||||
ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(deleted_node));
|
||||
|
||||
// If some item has a children, just to add a deleted item is not enough on Linux
|
||||
// We should to add all its children separately
|
||||
AddAllChildren(wxDataViewItem(deleted_node));
|
||||
|
||||
return wxDataViewItem(deleted_node);
|
||||
}
|
||||
|
||||
|
|
|
@ -504,8 +504,9 @@ public:
|
|||
void UpdateExtruderBitmap(wxDataViewItem item);
|
||||
|
||||
private:
|
||||
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
|
||||
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);
|
||||
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
|
||||
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);
|
||||
void AddAllChildren(const wxDataViewItem& parent);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -129,8 +129,14 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
|||
m_options.emplace(opt.opt_id, opt);
|
||||
|
||||
// Set sidetext width for a better alignment of options in line
|
||||
if (option_set.size() > 1)
|
||||
// "m_show_modified_btns==true" means that options groups are in tabs
|
||||
if (option_set.size() > 1 && m_show_modified_btns) {
|
||||
sidetext_width = Field::def_width_thinner();
|
||||
/* Temporary commented till UI-review will be completed
|
||||
if (m_show_modified_btns) // means that options groups are in tabs
|
||||
sublabel_width = Field::def_width();
|
||||
*/
|
||||
}
|
||||
|
||||
// add mode value for current line to m_options_mode
|
||||
if (!option_set.empty())
|
||||
|
@ -248,15 +254,16 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
|||
ConfigOptionDef option = opt.opt;
|
||||
wxSizer* sizer_tmp = sizer;
|
||||
// add label if any
|
||||
if (option.label != "") {
|
||||
if (!option.label.empty()) {
|
||||
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
|
||||
wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ?
|
||||
_CTX(option.label, "Layers") :
|
||||
_(option.label);
|
||||
label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, wxDefaultSize);
|
||||
label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, //wxDefaultSize);
|
||||
wxSize(sublabel_width != -1 ? sublabel_width * wxGetApp().em_unit() : -1, -1), wxALIGN_RIGHT);
|
||||
label->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
label->SetFont(wxGetApp().normal_font());
|
||||
sizer_tmp->Add(label, 0, /*wxALIGN_RIGHT |*/ wxALIGN_CENTER_VERTICAL, 0);
|
||||
sizer_tmp->Add(label, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
}
|
||||
|
||||
// add field
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
int sidetext_width{ -1 };
|
||||
int sublabel_width{ -1 };
|
||||
|
||||
/// Returns a copy of the pointer of the parent wxWindow.
|
||||
/// Accessor function is because users are not allowed to change the parent
|
||||
|
|
|
@ -262,6 +262,11 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
|||
m_em_unit(wxGetApp().em_unit())
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
#ifdef _WIN32
|
||||
// Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that
|
||||
// the index of the item inside CBN_EDITCHANGE may no more be valid.
|
||||
EnableTextChangedEvents(false);
|
||||
#endif /* _WIN32 */
|
||||
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) {
|
||||
auto selected_item = this->GetSelection();
|
||||
|
||||
|
@ -322,7 +327,7 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
|||
dialog.CenterOnParent();
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
colors->values[extruder_idx] = dialog.GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX);
|
||||
colors->values[extruder_idx] = dialog.GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
||||
|
||||
DynamicPrintConfig cfg_new = *cfg;
|
||||
cfg_new.set_key_value("extruder_colour", colors);
|
||||
|
@ -870,8 +875,8 @@ Sidebar::Sidebar(Plater *parent)
|
|||
(*btn)->Hide();
|
||||
};
|
||||
|
||||
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _(L("Send to printer")));
|
||||
init_scalable_btn(&p->btn_remove_device, "cross" , _(L("Remove device")));
|
||||
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _(L("Send to printer")) + "\tCtrl+Shift+G");
|
||||
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _(L("Remove device")));
|
||||
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _(L("Export to SD card / Flash drive")));
|
||||
|
||||
// regular buttons "Slice now" and "Export G-code"
|
||||
|
@ -1233,42 +1238,59 @@ void Sidebar::update_sliced_info_sizer()
|
|||
p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label);
|
||||
|
||||
p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume));
|
||||
p->sliced_info->SetTextAndShow(siFilament_g, wxString::Format("%.2f", ps.total_weight));
|
||||
|
||||
p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight));
|
||||
|
||||
new_label = _(L("Cost"));
|
||||
if (is_wipe_tower)
|
||||
new_label += wxString::Format(" :\n - %s\n - %s", _(L("objects")), _(L("wipe tower")));
|
||||
|
||||
info_text = is_wipe_tower ?
|
||||
info_text = ps.total_cost == 0.0 ? "N/A" :
|
||||
is_wipe_tower ?
|
||||
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_cost,
|
||||
(ps.total_cost - ps.total_wipe_tower_cost),
|
||||
ps.total_wipe_tower_cost) :
|
||||
wxString::Format("%.2f", ps.total_cost);
|
||||
p->sliced_info->SetTextAndShow(siCost, info_text, new_label);
|
||||
p->sliced_info->SetTextAndShow(siCost, info_text, new_label);
|
||||
|
||||
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
|
||||
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
|
||||
else {
|
||||
new_label = _(L("Estimated printing time")) +" :";
|
||||
info_text = "";
|
||||
if (ps.estimated_normal_print_time != "N/A") {
|
||||
new_label += wxString::Format("\n - %s", _(L("normal mode")));
|
||||
info_text += wxString::Format("\n%s", ps.estimated_normal_print_time);
|
||||
for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i)
|
||||
wxString str_color = _(L("Color"));
|
||||
wxString str_pause = _(L("Pause"));
|
||||
|
||||
auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGcodeType, std::string>>& times,
|
||||
wxString& new_label, wxString& info_text)
|
||||
{
|
||||
int color_change_count = 0;
|
||||
for (auto time : times)
|
||||
if (time.first == cgtColorChange)
|
||||
color_change_count++;
|
||||
|
||||
for (int i = (int)times.size() - 1; i >= 0; --i)
|
||||
{
|
||||
new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1);
|
||||
info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]);
|
||||
if (i == 0 || times[i - 1].first == cgtPausePrint)
|
||||
new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count);
|
||||
else if (times[i - 1].first == cgtColorChange)
|
||||
new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count--);
|
||||
|
||||
if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint)
|
||||
new_label += wxString::Format(" -> %s", str_pause);
|
||||
|
||||
info_text += wxString::Format("\n%s", times[i].second);
|
||||
}
|
||||
};
|
||||
|
||||
if (ps.estimated_normal_print_time != "N/A") {
|
||||
new_label += wxString::Format("\n - %s", _(L("normal mode")));
|
||||
info_text += wxString::Format("\n%s", ps.estimated_normal_print_time);
|
||||
fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
|
||||
}
|
||||
if (ps.estimated_silent_print_time != "N/A") {
|
||||
new_label += wxString::Format("\n - %s", _(L("stealth mode")));
|
||||
new_label += wxString::Format("\n - %s", _(L("stealth mode")));
|
||||
info_text += wxString::Format("\n%s", ps.estimated_silent_print_time);
|
||||
for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i)
|
||||
{
|
||||
new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1);
|
||||
info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]);
|
||||
}
|
||||
fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
|
||||
}
|
||||
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
|
||||
}
|
||||
|
@ -2248,7 +2270,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
|
||||
auto *nozzle_dmrs = config->opt<ConfigOptionFloats>("nozzle_diameter");
|
||||
|
||||
bool one_by_one = input_files.size() == 1 || nozzle_dmrs->values.size() <= 1;
|
||||
bool one_by_one = input_files.size() == 1 || printer_technology == ptSLA || nozzle_dmrs->values.size() <= 1;
|
||||
if (! one_by_one) {
|
||||
for (const auto &path : input_files) {
|
||||
if (std::regex_match(path.string(), pattern_bundle)) {
|
||||
|
@ -3067,10 +3089,10 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
||||
if (! postpone_error_messages && top_level_wnd && top_level_wnd->IsActive()) {
|
||||
// The error returned from the Print needs to be translated into the local language.
|
||||
GUI::show_error(this->q, _(err));
|
||||
GUI::show_error(this->q, err);
|
||||
} else {
|
||||
// Show the error message once the main window gets activated.
|
||||
this->delayed_error_message = _(err);
|
||||
this->delayed_error_message = err;
|
||||
}
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||
}
|
||||
|
@ -3260,7 +3282,7 @@ void Plater::priv::reload_from_disk()
|
|||
else
|
||||
missing_input_paths.push_back(volume->source.input_file);
|
||||
}
|
||||
else if (!object->input_file.empty() && !volume->name.empty())
|
||||
else if (!object->input_file.empty() && volume->is_model_part() && !volume->name.empty())
|
||||
missing_input_paths.push_back(volume->name);
|
||||
}
|
||||
|
||||
|
@ -3324,7 +3346,7 @@ void Plater::priv::reload_from_disk()
|
|||
const auto& path = input_paths[i].string();
|
||||
|
||||
wxBusyCursor wait;
|
||||
wxBusyInfo info(_(L("Reload from: ")) + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
||||
wxBusyInfo info(_(L("Reload from:")) + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
|
||||
|
||||
Model new_model;
|
||||
try
|
||||
|
@ -4039,7 +4061,7 @@ bool Plater::priv::complit_init_part_menu()
|
|||
part_menu.AppendSeparator();
|
||||
|
||||
auto obj_list = sidebar->obj_list();
|
||||
obj_list->append_menu_item_change_type(&part_menu);
|
||||
obj_list->append_menu_item_change_type(&part_menu, q);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4736,8 +4758,8 @@ void Plater::set_number_of_copies(/*size_t num*/)
|
|||
|
||||
ModelObject* model_object = p->model.objects[obj_idx];
|
||||
|
||||
const int num = wxGetNumberFromUser( " ", _("Enter the number of copies:"),
|
||||
_("Copies of the selected object"), model_object->instances.size(), 0, 1000, this );
|
||||
const int num = wxGetNumberFromUser( " ", _(L("Enter the number of copies:")),
|
||||
_(L("Copies of the selected object")), model_object->instances.size(), 0, 1000, this );
|
||||
if (num < 0)
|
||||
return;
|
||||
|
||||
|
@ -5187,8 +5209,10 @@ void Plater::drive_ejected_callback()
|
|||
if (RemovableDriveManager::get_instance().get_did_eject())
|
||||
{
|
||||
RemovableDriveManager::get_instance().set_did_eject(false);
|
||||
wxString message = "Unmounting successful. The device " + RemovableDriveManager::get_instance().get_ejected_name() + "(" + RemovableDriveManager::get_instance().get_ejected_path() + ")" + " can now be safely removed from the computer.";
|
||||
wxMessageBox(message);
|
||||
show_info(this,
|
||||
(boost::format(_utf8(L("Unmounting successful. The device %s(%s) can now be safely removed from the computer.")))
|
||||
% RemovableDriveManager::get_instance().get_ejected_name()
|
||||
% RemovableDriveManager::get_instance().get_ejected_path()).str());
|
||||
}
|
||||
p->show_action_buttons(false);
|
||||
}
|
||||
|
@ -5337,11 +5361,6 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto prin_host_opt = p->config->option<ConfigOptionString>("print_host");
|
||||
p->sidebar->show_send(prin_host_opt != nullptr && !prin_host_opt->value.empty());
|
||||
}
|
||||
|
||||
if (bed_shape_changed)
|
||||
p->set_bed_shape(p->config->option<ConfigOptionPoints>("bed_shape")->values,
|
||||
p->config->option<ConfigOptionString>("bed_custom_texture")->value,
|
||||
|
@ -5581,6 +5600,7 @@ void Plater::suppress_background_process(const bool stop_background_process)
|
|||
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
|
||||
|
||||
void Plater::update_object_menu() { p->update_object_menu(); }
|
||||
void Plater::show_action_buttons(const bool is_ready_to_slice) const { p->show_action_buttons(is_ready_to_slice); }
|
||||
|
||||
void Plater::copy_selection_to_clipboard()
|
||||
{
|
||||
|
|
|
@ -239,6 +239,7 @@ public:
|
|||
std::vector<std::string> get_colors_for_color_print() const;
|
||||
|
||||
void update_object_menu();
|
||||
void show_action_buttons(const bool is_ready_to_slice) const;
|
||||
|
||||
wxString get_project_filename(const wxString& extension = wxEmptyString) const;
|
||||
void set_project_filename(const wxString& filename);
|
||||
|
|
|
@ -313,9 +313,9 @@ std::string Preset::label() const
|
|||
return this->name + (this->is_dirty ? g_suffix_modified : "");
|
||||
}
|
||||
|
||||
bool is_compatible_with_print(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print)
|
||||
bool is_compatible_with_print(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print, const PresetWithVendorProfile &active_printer)
|
||||
{
|
||||
if (preset.vendor != nullptr && preset.vendor != active_print.vendor)
|
||||
if (preset.vendor != nullptr && preset.vendor != active_printer.vendor)
|
||||
// The current profile has a vendor assigned and it is different from the active print's vendor.
|
||||
return false;
|
||||
auto &condition = preset.preset.compatible_prints_condition();
|
||||
|
@ -374,12 +374,23 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
|||
if (type == TYPE_PRINTER) {
|
||||
const std::string &model = config.opt_string("printer_model");
|
||||
const std::string &variant = config.opt_string("printer_variant");
|
||||
if (model.empty() || variant.empty()) { return; }
|
||||
if (model.empty() || variant.empty())
|
||||
return;
|
||||
is_visible = app_config.get_variant(vendor->id, model, variant);
|
||||
} else if (type == TYPE_FILAMENT) {
|
||||
is_visible = app_config.has("filaments", name);
|
||||
} else if (type == TYPE_SLA_MATERIAL) {
|
||||
is_visible = app_config.has("sla_materials", name);
|
||||
} else if (type == TYPE_FILAMENT || type == TYPE_SLA_MATERIAL) {
|
||||
const char *section_name = (type == TYPE_FILAMENT) ? "filaments" : "sla_materials";
|
||||
if (app_config.has_section(section_name)) {
|
||||
// Check whether this profile is marked as "installed" in PrusaSlicer.ini,
|
||||
// or whether a profile is marked as "installed", which this profile may have been renamed from.
|
||||
const std::map<std::string, std::string> &installed = app_config.get_section(section_name);
|
||||
auto has = [&installed](const std::string &name) {
|
||||
auto it = installed.find(name);
|
||||
return it != installed.end() && ! it->second.empty();
|
||||
};
|
||||
is_visible = has(this->name);
|
||||
for (auto it = this->renamed_from.begin(); ! is_visible && it != this->renamed_from.end(); ++ it)
|
||||
is_visible = has(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,6 +491,7 @@ const std::vector<std::string>& Preset::sla_print_options()
|
|||
"support_head_penetration",
|
||||
"support_head_width",
|
||||
"support_pillar_diameter",
|
||||
"support_max_bridges_on_pillar",
|
||||
"support_pillar_connection_mode",
|
||||
"support_buildplate_only",
|
||||
"support_pillar_widening_factor",
|
||||
|
@ -557,6 +569,8 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
|||
"fast_tilt_time", "slow_tilt_time", "area_fill",
|
||||
"relative_correction",
|
||||
"absolute_correction",
|
||||
"elefant_foot_compensation",
|
||||
"elefant_foot_min_width",
|
||||
"gamma_correction",
|
||||
"min_exposure_time", "max_exposure_time",
|
||||
"min_initial_exposure_time", "max_initial_exposure_time",
|
||||
|
@ -683,19 +697,51 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string
|
|||
return this->load_preset(path, name, std::move(cfg), select);
|
||||
}
|
||||
|
||||
static bool profile_print_params_same(const DynamicPrintConfig &cfg1, const DynamicPrintConfig &cfg2)
|
||||
enum class ProfileHostParams
|
||||
{
|
||||
t_config_option_keys diff = cfg1.diff(cfg2);
|
||||
Same,
|
||||
Different,
|
||||
Anonymized,
|
||||
};
|
||||
|
||||
static ProfileHostParams profile_host_params_same_or_anonymized(const DynamicPrintConfig &cfg_old, const DynamicPrintConfig &cfg_new)
|
||||
{
|
||||
auto opt_print_host_old = cfg_old.option<ConfigOptionString>("print_host");
|
||||
auto opt_printhost_apikey_old = cfg_old.option<ConfigOptionString>("printhost_apikey");
|
||||
auto opt_printhost_cafile_old = cfg_old.option<ConfigOptionString>("printhost_cafile");
|
||||
|
||||
auto opt_print_host_new = cfg_new.option<ConfigOptionString>("print_host");
|
||||
auto opt_printhost_apikey_new = cfg_new.option<ConfigOptionString>("printhost_apikey");
|
||||
auto opt_printhost_cafile_new = cfg_new.option<ConfigOptionString>("printhost_cafile");
|
||||
|
||||
// If the new print host data is undefined, use the old data.
|
||||
bool new_print_host_undefined = (opt_print_host_new == nullptr || opt_print_host_new ->empty()) &&
|
||||
(opt_printhost_apikey_new == nullptr || opt_printhost_apikey_new ->empty()) &&
|
||||
(opt_printhost_cafile_new == nullptr || opt_printhost_cafile_new ->empty());
|
||||
if (new_print_host_undefined)
|
||||
return ProfileHostParams::Anonymized;
|
||||
|
||||
auto opt_same = [](const ConfigOptionString *l, const ConfigOptionString *r) {
|
||||
return ((l == nullptr || l->empty()) && (r == nullptr || r->empty())) ||
|
||||
(l != nullptr && r != nullptr && l->value == r->value);
|
||||
};
|
||||
return (opt_same(opt_print_host_old, opt_print_host_new) && opt_same(opt_printhost_apikey_old, opt_printhost_apikey_new) &&
|
||||
opt_same(opt_printhost_cafile_old, opt_printhost_cafile_new)) ? ProfileHostParams::Same : ProfileHostParams::Different;
|
||||
}
|
||||
|
||||
static bool profile_print_params_same(const DynamicPrintConfig &cfg_old, const DynamicPrintConfig &cfg_new)
|
||||
{
|
||||
t_config_option_keys diff = cfg_old.diff(cfg_new);
|
||||
// Following keys are used by the UI, not by the slicing core, therefore they are not important
|
||||
// when comparing profiles for equality. Ignore them.
|
||||
for (const char *key : { "compatible_prints", "compatible_prints_condition",
|
||||
"compatible_printers", "compatible_printers_condition", "inherits",
|
||||
"print_settings_id", "filament_settings_id", "sla_print_settings_id", "sla_material_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant", "default_print_profile", "default_filament_profile", "default_sla_print_profile", "default_sla_material_profile",
|
||||
"printhost_apikey", "printhost_cafile" })
|
||||
"print_host", "printhost_apikey", "printhost_cafile" })
|
||||
diff.erase(std::remove(diff.begin(), diff.end(), key), diff.end());
|
||||
// Preset with the same name as stored inside the config exists.
|
||||
return diff.empty();
|
||||
return diff.empty() && profile_host_params_same_or_anonymized(cfg_old, cfg_new) != ProfileHostParams::Different;
|
||||
}
|
||||
|
||||
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
|
||||
|
@ -724,11 +770,25 @@ Preset& PresetCollection::load_external_preset(
|
|||
it = this->find_preset_renamed(original_name);
|
||||
found = it != m_presets.end();
|
||||
}
|
||||
if (found && profile_print_params_same(it->config, cfg)) {
|
||||
// The preset exists and it matches the values stored inside config.
|
||||
if (select)
|
||||
this->select_preset(it - m_presets.begin());
|
||||
return *it;
|
||||
if (found) {
|
||||
if (profile_print_params_same(it->config, cfg)) {
|
||||
// The preset exists and it matches the values stored inside config.
|
||||
if (select)
|
||||
this->select_preset(it - m_presets.begin());
|
||||
return *it;
|
||||
}
|
||||
if (profile_host_params_same_or_anonymized(it->config, cfg) == ProfileHostParams::Anonymized) {
|
||||
// The project being loaded is anonymized. Replace the empty host keys of the loaded profile with the data from the original profile.
|
||||
// See "Octoprint Settings when Opening a .3MF file" GH issue #3244
|
||||
auto opt_update = [it, &cfg](const std::string &opt_key) {
|
||||
auto opt = it->config.option<ConfigOptionString>(opt_key);
|
||||
if (opt != nullptr)
|
||||
cfg.set_key_value(opt_key, opt->clone());
|
||||
};
|
||||
opt_update("print_host");
|
||||
opt_update("printhost_apikey");
|
||||
opt_update("printhost_cafile");
|
||||
}
|
||||
}
|
||||
// Update the "inherits" field.
|
||||
std::string &inherits = Preset::inherits(cfg);
|
||||
|
@ -994,7 +1054,7 @@ void PresetCollection::set_default_suppressed(bool default_suppressed)
|
|||
}
|
||||
}
|
||||
|
||||
size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool unselect_if_incompatible)
|
||||
size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType unselect_if_incompatible)
|
||||
{
|
||||
DynamicPrintConfig config;
|
||||
config.set_key_value("printer_preset", new ConfigOptionString(active_printer.preset.name));
|
||||
|
@ -1006,10 +1066,12 @@ size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfil
|
|||
Preset &preset_selected = m_presets[idx_preset];
|
||||
Preset &preset_edited = selected ? m_edited_preset : preset_selected;
|
||||
const PresetWithVendorProfile this_preset_with_vendor_profile = this->get_preset_with_vendor_profile(preset_edited);
|
||||
bool was_compatible = preset_edited.is_compatible;
|
||||
preset_edited.is_compatible = is_compatible_with_printer(this_preset_with_vendor_profile, active_printer, &config);
|
||||
if (active_print != nullptr)
|
||||
preset_edited.is_compatible &= is_compatible_with_print(this_preset_with_vendor_profile, *active_print);
|
||||
if (! preset_edited.is_compatible && selected && unselect_if_incompatible)
|
||||
preset_edited.is_compatible &= is_compatible_with_print(this_preset_with_vendor_profile, *active_print, active_printer);
|
||||
if (! preset_edited.is_compatible && selected &&
|
||||
(unselect_if_incompatible == PresetSelectCompatibleType::Always || (unselect_if_incompatible == PresetSelectCompatibleType::OnlyIfWasCompatible && was_compatible)))
|
||||
m_idx_selected = -1;
|
||||
if (selected)
|
||||
preset_selected.is_compatible = preset_edited.is_compatible;
|
||||
|
@ -1324,7 +1386,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
|
|||
const ConfigOption *other_opt = config_other.option(opt_key);
|
||||
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
|
||||
{
|
||||
if (opt_key == "bed_shape" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
|
||||
if (opt_key == "bed_shape" || opt_key == "thumbnails" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
|
||||
diff.emplace_back(opt_key);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -247,10 +247,19 @@ protected:
|
|||
static std::string remove_suffix_modified(const std::string &name);
|
||||
};
|
||||
|
||||
bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print);
|
||||
bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print, const PresetWithVendorProfile &active_printer);
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config);
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer);
|
||||
|
||||
enum class PresetSelectCompatibleType {
|
||||
// Never select a compatible preset if the newly selected profile is not compatible.
|
||||
Never,
|
||||
// Only select a compatible preset if the active profile used to be compatible, but it is no more.
|
||||
OnlyIfWasCompatible,
|
||||
// Always select a compatible preset if the active profile is no more compatible.
|
||||
Always
|
||||
};
|
||||
|
||||
// Collections of presets of the same type (one of the Print, Filament or Printer type).
|
||||
class PresetCollection
|
||||
{
|
||||
|
@ -412,13 +421,13 @@ public:
|
|||
|
||||
// For Print / Filament presets, disable those, which are not compatible with the printer.
|
||||
template<typename PreferedCondition>
|
||||
void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool select_other_if_incompatible, PreferedCondition prefered_condition)
|
||||
void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType select_other_if_incompatible, PreferedCondition prefered_condition)
|
||||
{
|
||||
if (this->update_compatible_internal(active_printer, active_print, select_other_if_incompatible) == (size_t)-1)
|
||||
// Find some other compatible preset, or the "-- default --" preset.
|
||||
this->select_preset(this->first_compatible_idx(prefered_condition));
|
||||
}
|
||||
void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool select_other_if_incompatible)
|
||||
void update_compatible(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType select_other_if_incompatible)
|
||||
{ this->update_compatible(active_printer, active_print, select_other_if_incompatible, [](const std::string&){return true;}); }
|
||||
|
||||
size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); }
|
||||
|
@ -515,7 +524,7 @@ private:
|
|||
std::deque<Preset>::const_iterator find_preset_renamed(const std::string &name) const
|
||||
{ return const_cast<PresetCollection*>(this)->find_preset_renamed(name); }
|
||||
|
||||
size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, bool unselect_if_incompatible);
|
||||
size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType unselect_if_incompatible);
|
||||
|
||||
static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false);
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_
|
|||
errors_cummulative += err.what();
|
||||
}
|
||||
this->update_multi_material_filament_presets();
|
||||
this->update_compatible(false);
|
||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||
if (! errors_cummulative.empty())
|
||||
throw std::runtime_error(errors_cummulative);
|
||||
|
||||
|
@ -424,7 +424,7 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr
|
|||
// or from the preferred_model_id suggestion passed in by ConfigWizard.
|
||||
// If the printer profile enumerated by the config are not visible, select an alternate preset.
|
||||
// Do not select alternate profiles for the print / filament profiles as those presets
|
||||
// will be selected by the following call of this->update_compatible(true).
|
||||
// will be selected by the following call of this->update_compatible(PresetSelectCompatibleType::Always).
|
||||
|
||||
const Preset *initial_printer = printers.find_preset(initial_printer_profile_name);
|
||||
const Preset *preferred_printer = printers.find_by_model_id(preferred_model_id);
|
||||
|
@ -457,7 +457,7 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr
|
|||
// Always try to select a compatible print and filament preset to the current printer preset,
|
||||
// as the application may have been closed with an active "external" preset, which does not
|
||||
// exist.
|
||||
this->update_compatible(true);
|
||||
this->update_compatible(PresetSelectCompatibleType::Always);
|
||||
this->update_multi_material_filament_presets();
|
||||
}
|
||||
|
||||
|
@ -889,7 +889,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
default: break;
|
||||
}
|
||||
|
||||
this->update_compatible(false);
|
||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||
}
|
||||
|
||||
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.
|
||||
|
@ -951,7 +951,7 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const
|
|||
for (size_t i = 1; i < std::min(tmp_bundle.filament_presets.size(), this->filament_presets.size()); ++ i)
|
||||
this->filament_presets[i] = load_one(this->filaments, tmp_bundle.filaments, tmp_bundle.filament_presets[i], false);
|
||||
|
||||
this->update_compatible(false);
|
||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||
}
|
||||
|
||||
// Process the Config Bundle loaded as a Boost property tree.
|
||||
|
@ -1351,7 +1351,7 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
|||
this->update_multi_material_filament_presets();
|
||||
for (size_t i = 0; i < std::min(this->filament_presets.size(), active_filaments.size()); ++ i)
|
||||
this->filament_presets[i] = filaments.find_preset(active_filaments[i], true)->name;
|
||||
this->update_compatible(false);
|
||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||
}
|
||||
|
||||
return presets_loaded;
|
||||
|
@ -1399,7 +1399,7 @@ void PresetBundle::update_multi_material_filament_presets()
|
|||
}
|
||||
}
|
||||
|
||||
void PresetBundle::update_compatible(bool select_other_if_incompatible)
|
||||
void PresetBundle::update_compatible(PresetSelectCompatibleType select_other_print_if_incompatible, PresetSelectCompatibleType select_other_filament_if_incompatible)
|
||||
{
|
||||
const Preset &printer_preset = this->printers.get_edited_preset();
|
||||
const PresetWithVendorProfile printer_preset_with_vendor_profile = this->printers.get_preset_with_vendor_profile(printer_preset);
|
||||
|
@ -1412,25 +1412,32 @@ void PresetBundle::update_compatible(bool select_other_if_incompatible)
|
|||
const std::string &prefered_print_profile = printer_preset.config.opt_string("default_print_profile");
|
||||
const std::vector<std::string> &prefered_filament_profiles = printer_preset.config.option<ConfigOptionStrings>("default_filament_profile")->values;
|
||||
prefered_print_profile.empty() ?
|
||||
this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible) :
|
||||
this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible,
|
||||
this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible) :
|
||||
this->prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible,
|
||||
[&prefered_print_profile](const std::string& profile_name) { return profile_name == prefered_print_profile; });
|
||||
const PresetWithVendorProfile print_preset_with_vendor_profile = this->prints.get_edited_preset_with_vendor_profile();
|
||||
// Remember whether the filament profiles were compatible before updating the filament compatibility.
|
||||
std::vector<char> filament_preset_was_compatible(this->filament_presets.size(), false);
|
||||
for (size_t idx = 0; idx < this->filament_presets.size(); ++ idx) {
|
||||
std::string &filament_name = this->filament_presets[idx];
|
||||
Preset *preset = this->filaments.find_preset(filament_name, false);
|
||||
filament_preset_was_compatible[idx] = preset != nullptr && preset->is_compatible;
|
||||
}
|
||||
prefered_filament_profiles.empty() ?
|
||||
this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_if_incompatible) :
|
||||
this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_if_incompatible,
|
||||
this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_filament_if_incompatible) :
|
||||
this->filaments.update_compatible(printer_preset_with_vendor_profile, &print_preset_with_vendor_profile, select_other_filament_if_incompatible,
|
||||
[&prefered_filament_profiles](const std::string& profile_name)
|
||||
{ return std::find(prefered_filament_profiles.begin(), prefered_filament_profiles.end(), profile_name) != prefered_filament_profiles.end(); });
|
||||
if (select_other_if_incompatible) {
|
||||
if (select_other_filament_if_incompatible != PresetSelectCompatibleType::Never) {
|
||||
// Verify validity of the current filament presets.
|
||||
if (this->filament_presets.size() == 1)
|
||||
this->filament_presets.front() = this->filaments.get_edited_preset().name;
|
||||
else
|
||||
{
|
||||
for (size_t idx = 0; idx < this->filament_presets.size(); ++idx) {
|
||||
if (this->filament_presets.size() == 1) {
|
||||
if (select_other_filament_if_incompatible == PresetSelectCompatibleType::Always || filament_preset_was_compatible.front())
|
||||
this->filament_presets.front() = this->filaments.get_edited_preset().name;
|
||||
} else {
|
||||
for (size_t idx = 0; idx < this->filament_presets.size(); ++ idx) {
|
||||
std::string &filament_name = this->filament_presets[idx];
|
||||
Preset *preset = this->filaments.find_preset(filament_name, false);
|
||||
if (preset == nullptr || !preset->is_compatible) {
|
||||
if (preset == nullptr || (! preset->is_compatible && (select_other_filament_if_incompatible == PresetSelectCompatibleType::Always || filament_preset_was_compatible[idx]))) {
|
||||
// Pick a compatible profile. If there are prefered_filament_profiles, use them.
|
||||
if (prefered_filament_profiles.empty())
|
||||
filament_name = this->filaments.first_compatible().name;
|
||||
|
@ -1453,13 +1460,13 @@ void PresetBundle::update_compatible(bool select_other_if_incompatible)
|
|||
const PresetWithVendorProfile sla_print_preset_with_vendor_profile = this->sla_prints.get_edited_preset_with_vendor_profile();
|
||||
const std::string &prefered_sla_print_profile = printer_preset.config.opt_string("default_sla_print_profile");
|
||||
(prefered_sla_print_profile.empty()) ?
|
||||
this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible) :
|
||||
this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_if_incompatible,
|
||||
this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible) :
|
||||
this->sla_prints.update_compatible(printer_preset_with_vendor_profile, nullptr, select_other_print_if_incompatible,
|
||||
[&prefered_sla_print_profile](const std::string& profile_name){ return profile_name == prefered_sla_print_profile; });
|
||||
const std::string &prefered_sla_material_profile = printer_preset.config.opt_string("default_sla_material_profile");
|
||||
prefered_sla_material_profile.empty() ?
|
||||
this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_if_incompatible) :
|
||||
this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_if_incompatible,
|
||||
this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_filament_if_incompatible) :
|
||||
this->sla_materials.update_compatible(printer_preset_with_vendor_profile, &sla_print_preset_with_vendor_profile, select_other_filament_if_incompatible,
|
||||
[&prefered_sla_material_profile](const std::string& profile_name){ return profile_name == prefered_sla_material_profile; });
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -127,7 +127,8 @@ public:
|
|||
// Also updates the is_visible flag of each preset.
|
||||
// If select_other_if_incompatible is true, then the print or filament preset is switched to some compatible
|
||||
// preset if the current print or filament preset is not compatible.
|
||||
void update_compatible(bool select_other_if_incompatible);
|
||||
void update_compatible(PresetSelectCompatibleType select_other_print_if_incompatible, PresetSelectCompatibleType select_other_filament_if_incompatible);
|
||||
void update_compatible(PresetSelectCompatibleType select_other_if_incompatible) { this->update_compatible(select_other_if_incompatible, select_other_if_incompatible); }
|
||||
|
||||
void load_default_preset_bitmaps();
|
||||
|
||||
|
|
|
@ -262,12 +262,16 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre
|
|||
int num_lines = std::min(num_perimeters * 2, 10);
|
||||
out += (boost::format(_utf8(L("Recommended object thin wall thickness for layer height %.2f and"))) % layer_height).str() + " ";
|
||||
// Start with the width of two closely spaced
|
||||
double width = external_perimeter_flow.width + external_perimeter_flow.spacing();
|
||||
for (int i = 2; i <= num_lines; thin_walls ? ++ i : i += 2) {
|
||||
if (i > 2)
|
||||
out += ", ";
|
||||
out += (boost::format(_utf8(L("%d lines: %.2f mm"))) % i % width).str() + " ";
|
||||
width += perimeter_flow.spacing() * (thin_walls ? 1.f : 2.f);
|
||||
try {
|
||||
double width = external_perimeter_flow.width + external_perimeter_flow.spacing();
|
||||
for (int i = 2; i <= num_lines; thin_walls ? ++ i : i += 2) {
|
||||
if (i > 2)
|
||||
out += ", ";
|
||||
out += (boost::format(_utf8(L("%d lines: %.2f mm"))) % i % width).str() + " ";
|
||||
width += perimeter_flow.spacing() * (thin_walls ? 1.f : 2.f);
|
||||
}
|
||||
} catch (const FlowErrorNegativeSpacing &) {
|
||||
out = _utf8(L("Recommended object thin wall thickness: Not available due to excessively small extrusion width."));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
|
@ -275,7 +275,7 @@ void PrintHostQueueDialog::on_error(Event &evt)
|
|||
|
||||
on_list_select();
|
||||
|
||||
GUI::show_error(nullptr, std::move(errormsg));
|
||||
GUI::show_error(nullptr, errormsg);
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_cancel(Event &evt)
|
||||
|
|