Merge branch 'master' into tm_colldetection_upgr
17
resources/icons/add.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#FFFFFF" d="M87.29,22.62H34.71c-1.39,0-3.14,0.69-4.16,1.63L9.81,43.46c-1.05,0.98-1.82,2.73-1.82,4.16v54.31
|
||||
c0,1.9,1.55,3.45,3.45,3.45h55.17c1.4,0,3.15-0.7,4.16-1.67l12.41-11.83c0.69-0.66,0.72-1.75,0.06-2.44s-1.75-0.71-2.44-0.06
|
||||
L70.05,99.63v-53.2c0.26-0.19,0.51-0.39,0.72-0.61L87.3,28.29v33.12c0,0.35-0.02,0.64-0.04,0.85c-0.51,0.55-0.62,1.39-0.22,2.06
|
||||
c0.49,0.82,1.55,1.08,2.37,0.59l0.25-0.15c0.67-0.4,1.09-1.1,1.09-3.35V26.07C90.74,24.17,89.2,22.62,87.29,22.62z M11.44,47.62
|
||||
L11.44,47.62h55.17v54.31H11.44V47.62z M68.26,43.46c-0.33,0.35-1.18,0.71-1.65,0.71H14.12L32.9,26.78
|
||||
c0.37-0.35,1.31-0.71,1.82-0.71h49.94L68.26,43.46z"/>
|
||||
<path id="_x2B__1_" fill="#ED6B21" d="M110.57,82.1c0,0.95-0.78,1.72-1.72,1.72h-4.31c-0.95,0-1.72,0.78-1.72,1.72v4.31
|
||||
c0,0.95-0.78,1.72-1.72,1.72h-4.31c-0.95,0-1.72-0.78-1.72-1.72v-4.31c0-0.95-0.78-1.72-1.72-1.72h-4.31
|
||||
c-0.95,0-1.72-0.78-1.72-1.72v-4.31c0-0.95,0.78-1.72,1.72-1.72h4.31c0.95,0,1.72-0.78,1.72-1.72v-4.31c0-0.95,0.78-1.72,1.72-1.72
|
||||
h4.31c0.95,0,1.72,0.78,1.72,1.72v4.31c0,0.95,0.78,1.72,1.72,1.72h4.31c0.95,0,1.72,0.78,1.72,1.72V82.1z M120.05,79.95
|
||||
c0-11.65-9.47-21.12-21.12-21.12S77.81,68.3,77.81,79.95s9.47,21.12,21.12,21.12S120.05,91.59,120.05,79.95z M116.6,79.95
|
||||
c0,9.74-7.93,17.67-17.67,17.67s-17.67-7.93-17.67-17.67s7.93-17.67,17.67-17.67S116.6,70.2,116.6,79.95z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
24
resources/icons/arrange.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="ARRANGE">
|
||||
<path fill="#FFFFFF" d="M113.85,14.27v99.36h-99.7V14.27H113.85 M115.85,8.27H12.15c-2.2,0-4,1.8-4,4v103.36c0,2.2,1.8,4,4,4h103.7
|
||||
c2.2,0,4-1.8,4-4V12.27C119.85,10.07,118.05,8.27,115.85,8.27L115.85,8.27z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M48.04,99.24c0,2.2-1.8,4-4,4H28.11c-2.2,0-4-1.8-4-4v-47c0-2.2,1.8-4,4-4h15.94c2.2,0,4,1.8,4,4
|
||||
L48.04,99.24L48.04,99.24z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M28.11,40.38c-2.2,0-4-1.8-4-4v-7.72c0-2.2,1.8-4,4-4h15.94c2.2,0,4,1.8,4,4v7.72c0,2.2-1.8,4-4,4H28.11z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M68,103.24c-2.2,0-4-1.8-4-4V83.67c0-2.2,1.8-4,4-4h31.89c2.2,0,4,1.8,4,4v15.57c0,2.2-1.8,4-4,4H68z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M103.89,59.95c0,2.2-1.8,4-4,4H68c-2.2,0-4-1.8-4-4V28.66c0-2.2,1.8-4,4-4h31.89c2.2,0,4,1.8,4,4V59.95z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
28
resources/icons/cut.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="cut">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M118.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S118.95,65.5,118.12,65.5z M98.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S98.95,65.5,98.12,65.5z M78.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S78.95,65.5,78.12,65.5z M58.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S58.95,65.5,58.12,65.5z M38.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S38.95,65.5,38.12,65.5z M18.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S18.95,65.5,18.12,65.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M108.79,51.6H19.21c-1.93,0-3.5-1.57-3.5-3.5V10.12c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5V48.1C112.29,50.03,110.71,51.6,108.79,51.6z M19.21,9.62c-0.27,0-0.5,0.23-0.5,0.5V48.1
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V10.12c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M108.79,121.38H19.21c-1.93,0-3.5-1.57-3.5-3.5V79.4c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5v38.49C112.29,119.81,110.71,121.38,108.79,121.38z M19.21,78.9c-0.27,0-0.5,0.23-0.5,0.5v38.49
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V79.4c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
31
resources/icons/delete_all.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="DELETE_ALL_1_">
|
||||
<path fill="#FFFFFF" d="M103.52,43.87l-13.31,69.97H37.79L24.48,43.87H103.52 M108.77,37.87H19.23c-1.1,0-1.83,0.88-1.63,1.96
|
||||
l14.84,78.04c0.21,1.08,1.27,1.96,2.37,1.96h58.36c1.1,0,2.17-0.88,2.37-1.96l14.84-78.04C110.6,38.75,109.87,37.87,108.77,37.87
|
||||
L108.77,37.87z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M89.38,22.97c-1.1,0-2-0.9-2-2v-10.9c0-1.1-0.9-2-2-2H42.62c-1.1,0-2,0.9-2,2v10.9c0,1.1-0.9,2-2,2H19.23
|
||||
c-1.1,0-2,0.9-2,2v3.45c0,1.1,0.9,2,2,2h89.54c1.1,0,2-0.9,2-2v-3.45c0-1.1-0.9-2-2-2H89.38z M79.59,20.97c0,1.1-0.9,2-2,2H50.41
|
||||
c-1.1,0-2-0.9-2-2v-3.45c0-1.1,0.9-2,2-2h27.18c1.1,0,2,0.9,2,2V20.97z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M93.17,73.5H34.83c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h58.34c0.83,0,1.5,0.67,1.5,1.5
|
||||
S94,73.5,93.17,73.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.14,89.45H37.96c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h52.18c0.83,0,1.5,0.67,1.5,1.5
|
||||
S90.97,89.45,90.14,89.45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M87.1,105.4H40.9c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h46.2c0.83,0,1.5,0.67,1.5,1.5
|
||||
S87.93,105.4,87.1,105.4z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M96.2,57.56H31.8c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h64.4c0.83,0,1.5,0.67,1.5,1.5
|
||||
S97.03,57.56,96.2,57.56z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
20
resources/icons/editor.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="editor">
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M118.68,8.83L92.1,37.03c-0.75,0.8-2.27,1.46-3.37,1.46H9.44"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="90.72" y1="118.69" x2="90.72" y2="38.81"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M119.88,91.51v-81.4c0-1.1-0.9-2-2-2H42.92c-1.1,0-2.66,0.61-3.47,1.36L9.59,37.13c-0.81,0.75-1.47,2.26-1.47,3.36v77.39
|
||||
c0,1.1,0.9,2,2,2h78.61c1.1,0,2.65-0.63,3.44-1.39l27.67-26.82"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/icons/gizmos.png
Normal file
After Width: | Height: | Size: 19 KiB |
50
resources/icons/instance_add.svg
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="ADD_INSTANCE">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.01,57.95c0-1.1-0.9-2-2-2H74c-1.1,0-2-0.9-2-2V41.94c0-1.1-0.9-2-2-2H58c-1.1,0-2,0.9-2,2v12.01
|
||||
c0,1.1-0.9,2-2,2H41.99c-1.1,0-2,0.9-2,2v12.01c0,1.1,0.9,2,2,2H54c1.1,0,2,0.9,2,2v12.01c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2
|
||||
V73.95c0-1.1,0.9-2,2-2h12.01c1.1,0,2-0.9,2-2V57.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M67.06,119.73c-2.1,0-3.87-1.64-3.99-3.77c-0.13-2.21,1.56-4.1,3.76-4.23c1.85-0.11,3.71-0.32,5.53-0.64
|
||||
c2.17-0.38,4.25,1.07,4.63,3.25s-1.07,4.25-3.25,4.63c-2.12,0.37-4.29,0.63-6.45,0.75C67.22,119.73,67.14,119.73,67.06,119.73z
|
||||
M55.05,119.05c-0.23,0-0.46-0.02-0.69-0.06c-2.13-0.37-4.26-0.87-6.32-1.49c-2.12-0.63-3.32-2.86-2.69-4.98s2.86-3.32,4.98-2.69
|
||||
c1.77,0.53,3.59,0.96,5.41,1.27c2.18,0.38,3.63,2.45,3.25,4.63C58.65,117.68,56.96,119.05,55.05,119.05z M84.58,115.58
|
||||
c-1.55,0-3.02-0.9-3.67-2.41c-0.88-2.03,0.06-4.38,2.08-5.26c1.69-0.73,3.36-1.57,4.96-2.5c1.91-1.11,4.36-0.46,5.47,1.46
|
||||
c1.11,1.91,0.46,4.36-1.46,5.47c-1.87,1.08-3.82,2.07-5.8,2.92C85.65,115.47,85.11,115.58,84.58,115.58z M38.12,112.91
|
||||
c-0.68,0-1.37-0.17-2-0.54c-1.87-1.08-3.69-2.28-5.43-3.57c-1.77-1.32-2.14-3.82-0.82-5.6c1.32-1.77,3.82-2.14,5.6-0.82
|
||||
c1.49,1.11,3.05,2.13,4.65,3.06c1.91,1.1,2.57,3.55,1.47,5.46C40.84,112.2,39.5,112.91,38.12,112.91z M99.61,105.67
|
||||
c-1.06,0-2.12-0.42-2.91-1.25c-1.52-1.61-1.45-4.14,0.16-5.66c1.35-1.27,2.63-2.64,3.82-4.05c1.42-1.69,3.94-1.91,5.64-0.49
|
||||
c1.69,1.42,1.91,3.94,0.49,5.64c-1.39,1.65-2.88,3.24-4.45,4.72C101.58,105.3,100.59,105.67,99.61,105.67z M24.32,101.35
|
||||
c-1.14,0-2.27-0.48-3.06-1.42c-1.39-1.65-2.7-3.4-3.89-5.2c-1.22-1.84-0.71-4.32,1.13-5.54c1.84-1.22,4.32-0.71,5.54,1.13
|
||||
c1.02,1.54,2.14,3.04,3.33,4.46c1.42,1.69,1.21,4.21-0.48,5.64C26.14,101.04,25.23,101.35,24.32,101.35z M110.36,91.23
|
||||
c-0.6,0-1.22-0.14-1.79-0.43c-1.97-0.99-2.77-3.4-1.78-5.37c0.83-1.65,1.57-3.37,2.2-5.11c0.75-2.08,3.05-3.15,5.13-2.39
|
||||
c2.08,0.75,3.15,3.05,2.39,5.13c-0.74,2.03-1.61,4.04-2.58,5.97C113.24,90.42,111.83,91.23,110.36,91.23z M15.28,85.78
|
||||
c-1.63,0-3.16-1-3.76-2.63c-0.74-2.03-1.37-4.12-1.87-6.22c-0.51-2.15,0.82-4.31,2.97-4.82s4.31,0.82,4.82,2.97
|
||||
c0.43,1.8,0.97,3.59,1.6,5.32c0.76,2.08-0.31,4.37-2.38,5.13C16.2,85.7,15.73,85.78,15.28,85.78z M115.53,73.97
|
||||
c-0.15,0-0.31-0.01-0.46-0.03c-2.19-0.25-3.77-2.24-3.52-4.43c0.21-1.83,0.32-3.7,0.32-5.56v-0.21c0-2.21,1.79-4,4-4s4,1.79,4,4
|
||||
v0.15c0,2.22-0.12,4.4-0.37,6.53C119.26,72.47,117.53,73.97,115.53,73.97z M12.13,68.05c-2.21,0-4-1.79-4-4h4l-4-0.05
|
||||
c0-2.18,0.12-4.33,0.36-6.42c0.25-2.19,2.24-3.76,4.43-3.52c2.2,0.25,3.77,2.23,3.52,4.43c-0.21,1.8-0.31,3.64-0.31,5.46v0.1
|
||||
C16.13,66.26,14.34,68.05,12.13,68.05z M114.43,55.8c-1.81,0-3.45-1.23-3.89-3.07c-0.43-1.8-0.98-3.59-1.61-5.32
|
||||
c-0.76-2.07,0.3-4.37,2.37-5.14c2.07-0.76,4.37,0.3,5.14,2.37c0.74,2.02,1.38,4.11,1.88,6.22c0.52,2.15-0.81,4.31-2.95,4.82
|
||||
C115.06,55.76,114.74,55.8,114.43,55.8z M15.21,50.31c-0.45,0-0.91-0.08-1.36-0.24c-2.08-0.75-3.15-3.04-2.4-5.12
|
||||
c0.73-2.03,1.6-4.04,2.56-5.97C15,37,17.4,36.2,19.38,37.19c1.98,0.99,2.77,3.39,1.79,5.37c-0.83,1.65-1.57,3.37-2.19,5.11
|
||||
C18.38,49.3,16.85,50.31,15.21,50.31z M107.24,39.3c-1.29,0-2.57-0.63-3.34-1.79c-1.02-1.54-2.15-3.04-3.34-4.45
|
||||
c-1.43-1.69-1.22-4.21,0.47-5.64s4.21-1.22,5.64,0.47c1.39,1.65,2.71,3.39,3.9,5.19c1.22,1.84,0.72,4.32-1.12,5.54
|
||||
C108.77,39.08,108,39.3,107.24,39.3z M24.19,34.7c-0.91,0-1.82-0.31-2.56-0.93c-1.69-1.42-1.92-3.94-0.5-5.63
|
||||
c1.38-1.66,2.88-3.25,4.44-4.73c1.6-1.52,4.13-1.45,5.65,0.15s1.45,4.13-0.15,5.65c-1.34,1.27-2.62,2.64-3.81,4.06
|
||||
C26.47,34.21,25.33,34.7,24.19,34.7z M94.83,26.24c-0.83,0-1.66-0.26-2.38-0.79c-1.49-1.1-3.05-2.13-4.66-3.05
|
||||
c-1.92-1.1-2.58-3.54-1.48-5.46c1.1-1.91,3.54-2.58,5.46-1.48c1.87,1.07,3.7,2.27,5.44,3.56c1.78,1.31,2.15,3.82,0.83,5.6
|
||||
C97.27,25.68,96.06,26.24,94.83,26.24z M37.95,23.09c-1.38,0-2.72-0.71-3.46-1.99c-1.11-1.91-0.46-4.36,1.44-5.47
|
||||
c1.86-1.08,3.81-2.07,5.79-2.93c2.03-0.88,4.38,0.05,5.26,2.07c0.88,2.03-0.05,4.38-2.07,5.26c-1.69,0.74-3.36,1.58-4.96,2.51
|
||||
C39.33,22.92,38.64,23.09,37.95,23.09z M78.72,18.21c-0.38,0-0.76-0.05-1.13-0.17c-1.77-0.52-3.59-0.95-5.42-1.26
|
||||
c-2.18-0.37-3.64-2.44-3.26-4.62s2.45-3.64,4.62-3.26c2.13,0.37,4.26,0.86,6.33,1.47c2.12,0.63,3.33,2.85,2.7,4.97
|
||||
C82.04,17.08,80.45,18.21,78.72,18.21z M54.84,16.89c-1.9,0-3.59-1.36-3.93-3.3c-0.39-2.17,1.06-4.25,3.24-4.64
|
||||
c2.12-0.38,4.29-0.63,6.45-0.76c2.19-0.14,4.1,1.55,4.23,3.75c0.13,2.21-1.55,4.1-3.75,4.23c-1.85,0.11-3.71,0.33-5.52,0.66
|
||||
C55.31,16.87,55.07,16.89,54.84,16.89z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
49
resources/icons/instance_remove.svg
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="REMOVE_INSTANCE">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.01,57.95c0-1.1-0.9-2-2-2H41.99c-1.1,0-2,0.9-2,2v12.01c0,1.1,0.9,2,2,2h44.02c1.1,0,2-0.9,2-2V57.95z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M67.06,119.73c-2.1,0-3.87-1.64-3.99-3.77c-0.13-2.21,1.56-4.1,3.76-4.23c1.85-0.11,3.71-0.32,5.53-0.64
|
||||
c2.17-0.38,4.25,1.07,4.63,3.25s-1.07,4.25-3.25,4.63c-2.12,0.37-4.29,0.63-6.45,0.75C67.22,119.73,67.14,119.73,67.06,119.73z
|
||||
M55.05,119.05c-0.23,0-0.46-0.02-0.69-0.06c-2.13-0.37-4.26-0.87-6.32-1.49c-2.12-0.63-3.32-2.86-2.69-4.98s2.86-3.32,4.98-2.69
|
||||
c1.77,0.53,3.59,0.96,5.41,1.27c2.18,0.38,3.63,2.45,3.25,4.63C58.65,117.68,56.96,119.05,55.05,119.05z M84.58,115.58
|
||||
c-1.55,0-3.02-0.9-3.67-2.41c-0.88-2.03,0.06-4.38,2.08-5.26c1.69-0.73,3.36-1.57,4.96-2.5c1.91-1.11,4.36-0.46,5.47,1.46
|
||||
c1.11,1.91,0.46,4.36-1.46,5.47c-1.87,1.08-3.82,2.07-5.8,2.92C85.65,115.47,85.11,115.58,84.58,115.58z M38.12,112.91
|
||||
c-0.68,0-1.37-0.17-2-0.54c-1.87-1.08-3.69-2.28-5.43-3.57c-1.77-1.32-2.14-3.82-0.82-5.6c1.32-1.77,3.82-2.14,5.6-0.82
|
||||
c1.49,1.11,3.05,2.13,4.65,3.06c1.91,1.1,2.57,3.55,1.47,5.46C40.84,112.2,39.5,112.91,38.12,112.91z M99.61,105.67
|
||||
c-1.06,0-2.12-0.42-2.91-1.25c-1.52-1.61-1.45-4.14,0.16-5.66c1.35-1.27,2.63-2.64,3.82-4.05c1.42-1.69,3.94-1.91,5.64-0.49
|
||||
c1.69,1.42,1.91,3.94,0.49,5.64c-1.39,1.65-2.88,3.24-4.45,4.72C101.58,105.3,100.59,105.67,99.61,105.67z M24.32,101.35
|
||||
c-1.14,0-2.27-0.48-3.06-1.42c-1.39-1.65-2.7-3.4-3.89-5.2c-1.22-1.84-0.71-4.32,1.13-5.54c1.84-1.22,4.32-0.71,5.54,1.13
|
||||
c1.02,1.54,2.14,3.04,3.33,4.46c1.42,1.69,1.21,4.21-0.48,5.64C26.14,101.04,25.23,101.35,24.32,101.35z M110.36,91.23
|
||||
c-0.6,0-1.22-0.14-1.79-0.43c-1.97-0.99-2.77-3.4-1.78-5.37c0.83-1.65,1.57-3.37,2.2-5.11c0.75-2.08,3.05-3.15,5.13-2.39
|
||||
c2.08,0.75,3.15,3.05,2.39,5.13c-0.74,2.03-1.61,4.04-2.58,5.97C113.24,90.42,111.83,91.23,110.36,91.23z M15.28,85.78
|
||||
c-1.63,0-3.16-1-3.76-2.63c-0.74-2.03-1.37-4.12-1.87-6.22c-0.51-2.15,0.82-4.31,2.97-4.82s4.31,0.82,4.82,2.97
|
||||
c0.43,1.8,0.97,3.59,1.6,5.32c0.76,2.08-0.31,4.37-2.38,5.13C16.2,85.7,15.73,85.78,15.28,85.78z M115.53,73.97
|
||||
c-0.15,0-0.31-0.01-0.46-0.03c-2.19-0.25-3.77-2.24-3.52-4.43c0.21-1.83,0.32-3.7,0.32-5.56v-0.21c0-2.21,1.79-4,4-4s4,1.79,4,4
|
||||
v0.15c0,2.22-0.12,4.4-0.37,6.53C119.26,72.47,117.53,73.97,115.53,73.97z M12.13,68.05c-2.21,0-4-1.79-4-4h4l-4-0.05
|
||||
c0-2.18,0.12-4.33,0.36-6.42c0.25-2.19,2.24-3.76,4.43-3.52c2.2,0.25,3.77,2.23,3.52,4.43c-0.21,1.8-0.31,3.64-0.31,5.46v0.1
|
||||
C16.13,66.26,14.34,68.05,12.13,68.05z M114.43,55.8c-1.81,0-3.45-1.23-3.89-3.07c-0.43-1.8-0.98-3.59-1.61-5.32
|
||||
c-0.76-2.07,0.3-4.37,2.37-5.14c2.07-0.76,4.37,0.3,5.14,2.37c0.74,2.02,1.38,4.11,1.88,6.22c0.52,2.15-0.81,4.31-2.95,4.82
|
||||
C115.06,55.76,114.74,55.8,114.43,55.8z M15.21,50.31c-0.45,0-0.91-0.08-1.36-0.24c-2.08-0.75-3.15-3.04-2.4-5.12
|
||||
c0.73-2.03,1.6-4.04,2.56-5.97C15,37,17.4,36.2,19.38,37.19c1.98,0.99,2.77,3.39,1.79,5.37c-0.83,1.65-1.57,3.37-2.19,5.11
|
||||
C18.38,49.3,16.85,50.31,15.21,50.31z M107.24,39.3c-1.29,0-2.57-0.63-3.34-1.79c-1.02-1.54-2.15-3.04-3.34-4.45
|
||||
c-1.43-1.69-1.22-4.21,0.47-5.64s4.21-1.22,5.64,0.47c1.39,1.65,2.71,3.39,3.9,5.19c1.22,1.84,0.72,4.32-1.12,5.54
|
||||
C108.77,39.08,108,39.3,107.24,39.3z M24.19,34.7c-0.91,0-1.82-0.31-2.56-0.93c-1.69-1.42-1.92-3.94-0.5-5.63
|
||||
c1.38-1.66,2.88-3.25,4.44-4.73c1.6-1.52,4.13-1.45,5.65,0.15s1.45,4.13-0.15,5.65c-1.34,1.27-2.62,2.64-3.81,4.06
|
||||
C26.47,34.21,25.33,34.7,24.19,34.7z M94.83,26.24c-0.83,0-1.66-0.26-2.38-0.79c-1.49-1.1-3.05-2.13-4.66-3.05
|
||||
c-1.92-1.1-2.58-3.54-1.48-5.46c1.1-1.91,3.54-2.58,5.46-1.48c1.87,1.07,3.7,2.27,5.44,3.56c1.78,1.31,2.15,3.82,0.83,5.6
|
||||
C97.27,25.68,96.06,26.24,94.83,26.24z M37.95,23.09c-1.38,0-2.72-0.71-3.46-1.99c-1.11-1.91-0.46-4.36,1.44-5.47
|
||||
c1.86-1.08,3.81-2.07,5.79-2.93c2.03-0.88,4.38,0.05,5.26,2.07c0.88,2.03-0.05,4.38-2.07,5.26c-1.69,0.74-3.36,1.58-4.96,2.51
|
||||
C39.33,22.92,38.64,23.09,37.95,23.09z M78.72,18.21c-0.38,0-0.76-0.05-1.13-0.17c-1.77-0.52-3.59-0.95-5.42-1.26
|
||||
c-2.18-0.37-3.64-2.44-3.26-4.62s2.45-3.64,4.62-3.26c2.13,0.37,4.26,0.86,6.33,1.47c2.12,0.63,3.33,2.85,2.7,4.97
|
||||
C82.04,17.08,80.45,18.21,78.72,18.21z M54.84,16.89c-1.9,0-3.59-1.36-3.93-3.3c-0.39-2.17,1.06-4.25,3.24-4.64
|
||||
c2.12-0.38,4.29-0.63,6.45-0.76c2.19-0.14,4.1,1.55,4.23,3.75c0.13,2.21-1.55,4.1-3.75,4.23c-1.85,0.11-3.71,0.33-5.52,0.66
|
||||
C55.31,16.87,55.07,16.89,54.84,16.89z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
25
resources/icons/layers.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="7.98" y="105" fill="#FFFFFF" width="112.04" height="15"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="85.67" fill="#FFFFFF" width="112.04" height="13"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="66.33" fill="#FFFFFF" width="112.04" height="11"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="47" fill="#ED6B21" width="112.04" height="9"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="27.67" fill="#ED6B21" width="112.04" height="7"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="8.33" fill="#ED6B21" width="112.04" height="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 841 B |
42
resources/icons/move.svg
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="move">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M83.47,86.79H44.53c-1.83,0-3.32-1.49-3.32-3.32V44.53c0-1.83,1.49-3.32,3.32-3.32h38.94
|
||||
c1.83,0,3.32,1.49,3.32,3.32v38.94C86.79,85.3,85.3,86.79,83.47,86.79z M44.53,44.21c-0.17,0-0.32,0.15-0.32,0.32v38.94
|
||||
c0,0.17,0.15,0.32,0.32,0.32h38.94c0.17,0,0.32-0.15,0.32-0.32V44.53c0-0.17-0.15-0.32-0.32-0.32H44.53z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M76.81,28.66H51.19c-1.06,0-1.9-0.46-2.31-1.25c-0.4-0.8-0.28-1.74,0.35-2.6L61.72,7.7
|
||||
c0.57-0.78,1.4-1.22,2.28-1.22c0,0,0,0,0,0c0.89,0,1.72,0.45,2.28,1.22l12.48,17.1c0.63,0.86,0.75,1.81,0.35,2.6
|
||||
C78.71,28.2,77.87,28.66,76.81,28.66z M52.33,25.66l23.34,0L64,9.67L52.33,25.66z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M26.44,79.35c-0.54,0-1.1-0.2-1.63-0.58L7.7,66.28c-0.78-0.57-1.22-1.4-1.22-2.28s0.45-1.72,1.22-2.29
|
||||
l17.1-12.48c0.86-0.62,1.81-0.75,2.6-0.35s1.25,1.25,1.25,2.31v25.61c0,1.06-0.46,1.9-1.25,2.31
|
||||
C27.1,79.27,26.77,79.35,26.44,79.35z M9.67,64l15.99,11.67l0-23.34L9.67,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M64,121.52c-0.89,0-1.72-0.45-2.28-1.22l-12.48-17.1c-0.63-0.86-0.75-1.81-0.35-2.6s1.25-1.25,2.31-1.25
|
||||
h25.61c1.06,0,1.9,0.46,2.31,1.25c0.4,0.8,0.28,1.74-0.35,2.6l-12.48,17.1C65.72,121.07,64.89,121.52,64,121.52L64,121.52z
|
||||
M52.33,102.34L64,118.33l11.67-15.99L52.33,102.34z M76.87,102.34L76.87,102.34L76.87,102.34z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M101.56,79.35c-0.34,0-0.67-0.08-0.97-0.23c-0.8-0.41-1.25-1.25-1.25-2.31V51.19
|
||||
c0-1.06,0.46-1.9,1.25-2.31c0.8-0.41,1.75-0.28,2.6,0.35l17.1,12.48c0.78,0.57,1.22,1.4,1.22,2.29s-0.45,1.72-1.22,2.28
|
||||
l-17.1,12.48C102.67,79.15,102.1,79.35,101.56,79.35z M102.34,52.33l0,23.34L118.33,64L102.34,52.33z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
32
resources/icons/place.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="place">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M101.56,93.65c-0.28,0-0.57-0.04-0.85-0.1L37.65,77.82c-0.9-0.22-1.67-0.79-2.15-1.59s-0.62-1.74-0.4-2.65
|
||||
l15.72-63.06c0.47-1.87,2.37-3.02,4.24-2.55l63.06,15.72c1.87,0.47,3.02,2.37,2.55,4.24l-15.72,63.06h0
|
||||
c-0.23,0.91-0.79,1.67-1.59,2.15C102.8,93.47,102.18,93.65,101.56,93.65z M54.21,10.87c-0.22,0-0.43,0.15-0.49,0.38L38.01,74.31
|
||||
c-0.04,0.17,0.02,0.31,0.06,0.38c0.04,0.07,0.13,0.19,0.31,0.23l63.06,15.72c0.17,0.04,0.31-0.02,0.38-0.06
|
||||
c0.07-0.04,0.19-0.13,0.23-0.3c0,0,0,0,0,0l15.72-63.06c0.07-0.26-0.1-0.54-0.37-0.61L54.33,10.88
|
||||
C54.29,10.87,54.25,10.87,54.21,10.87z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M118.02,120.54H9.98c-1.93,0-3.5-1.57-3.5-3.5v-4c0-1.93,1.57-3.5,3.5-3.5h108.04c1.93,0,3.5,1.57,3.5,3.5
|
||||
v4C121.52,118.97,119.95,120.54,118.02,120.54z M9.98,112.54c-0.27,0-0.5,0.23-0.5,0.5v4c0,0.27,0.23,0.5,0.5,0.5h108.04
|
||||
c0.27,0,0.5-0.23,0.5-0.5v-4c0-0.27-0.23-0.5-0.5-0.5H9.98z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M15.99,103.92c-0.08,0-0.15,0-0.23-0.01c-0.92-0.09-1.69-0.72-2.11-1.73L7.42,87.2
|
||||
c-0.41-0.98-0.33-1.97,0.22-2.71c0.55-0.74,1.48-1.11,2.53-1L25.29,85c1.06,0.11,1.89,0.65,2.28,1.48
|
||||
c0.39,0.84,0.27,1.82-0.32,2.71l-9.08,13.43C17.61,103.46,16.82,103.92,15.99,103.92z M10.4,86.52l5.72,13.77l8.36-12.35
|
||||
L10.4,86.52z M24.81,87.43L24.81,87.43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M17.54,85.9c-0.83,0-1.5-0.67-1.5-1.5c0-8.88,8.1-24.47,17.34-25.5c0.82-0.09,1.56,0.5,1.66,1.33
|
||||
c0.09,0.82-0.5,1.56-1.33,1.66c-6.94,0.77-14.67,14.08-14.67,22.52C19.04,85.22,18.37,85.9,17.54,85.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
48
resources/icons/preview.svg
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="preview">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,121.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,121.23,91.11,121.38,90.72,121.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,111.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,111.23,91.11,111.38,90.72,111.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,101.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12l-29.16,28.57C91.49,101.23,91.11,101.38,90.72,101.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,91.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,90.95C91.49,91.23,91.11,91.38,90.72,91.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,81.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,80.95C91.49,81.23,91.11,81.38,90.72,81.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,71.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,70.95C91.49,71.23,91.11,71.38,90.72,71.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M90.72,61.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,60.95C91.49,61.23,91.11,61.38,90.72,61.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,51.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,50.95C91.49,51.23,91.11,51.38,90.72,51.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M88.72,41.38H9.18c-1.68,0-2.22-0.95-2.37-1.36s-0.37-1.48,0.89-2.59L38.43,10.5
|
||||
c1.1-0.96,3.03-1.69,4.49-1.69h75.85c1.65,0,2.22,0.94,2.38,1.34s0.42,1.47-0.75,2.63c0,0,0,0,0,0L93.2,39.55
|
||||
C92.14,40.59,90.21,41.38,88.72,41.38z M11.17,38.38h77.55c0.71,0,1.87-0.47,2.37-0.97l26.01-25.6H42.92
|
||||
c-0.74,0-1.96,0.46-2.51,0.95L11.17,38.38z M118.89,11.82C118.89,11.82,118.89,11.82,118.89,11.82
|
||||
C118.89,11.82,118.89,11.82,118.89,11.82z M119.34,11.71L119.34,11.71L119.34,11.71z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
44
resources/icons/remove.svg
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#FFFFFF" d="M38.11,44.25H25.75c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72H38.1c0.95,0,1.72-0.77,1.72-1.72
|
||||
C39.83,45.02,39.06,44.25,38.11,44.25z M45.89,45.97c0,0.95,0.77,1.72,1.72,1.72h12.35c0.95,0,1.72-0.77,1.72-1.72
|
||||
s-0.77-1.72-1.72-1.72H47.61C46.66,44.25,45.89,45.02,45.89,45.97z M68.11,43.6c-0.33,0.28-0.52,0.65-0.59,1.04
|
||||
c-0.59,0.27-1,0.87-1,1.56v5.6c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-5.34c0.12-0.06,0.24-0.13,0.35-0.22
|
||||
c0.13-0.11,0.25-0.23,0.36-0.34l8.27-8.77c0.65-0.69,0.62-1.78-0.07-2.43s-1.78-0.62-2.43,0.07l-8.27,8.78
|
||||
C68.16,43.56,68.14,43.58,68.11,43.6z M68.25,76.84c-0.95,0-1.72,0.77-1.72,1.72V89.1c0,0.95,0.77,1.72,1.72,1.72
|
||||
c0.95,0,1.72-0.77,1.72-1.72V78.56C69.97,77.61,69.2,76.84,68.25,76.84z M69.97,59.91c0-0.95-0.77-1.72-1.72-1.72
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v10.54c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72V59.91z M88.92,56.35
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v3.4c0,0.34-0.02,0.63-0.04,0.85c-0.51,0.55-0.62,1.38-0.22,2.06c0.32,0.54,0.89,0.84,1.48,0.84
|
||||
c0.3,0,0.6-0.08,0.88-0.24l0.25-0.15c0.67-0.4,1.09-1.1,1.09-3.35v-3.4C90.64,57.12,89.87,56.35,88.92,56.35z M41.81,26.17h11.3
|
||||
c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3c-0.95,0-1.72,0.77-1.72,1.72S40.86,26.17,41.81,26.17z M87.2,22.73h-5.39
|
||||
c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h2.75l-1.58,1.68c-0.65,0.69-0.62,1.78,0.07,2.43c0.33,0.31,0.76,0.47,1.18,0.47
|
||||
c0.46,0,0.91-0.18,1.25-0.54l1.72-1.82v0.99c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-3.21
|
||||
C90.64,24.27,89.09,22.73,87.2,22.73z M61.81,26.17h11.3c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3
|
||||
c-0.95,0-1.72,0.77-1.72,1.72S60.86,26.17,61.81,26.17z M9.71,67.54c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72
|
||||
s-1.72,0.77-1.72,1.72v11.3C7.99,66.77,8.76,67.54,9.71,67.54z M24.65,33.86c0.42,0,0.84-0.15,1.17-0.46l7.04-6.52
|
||||
c0.14-0.13,0.46-0.34,0.9-0.51c0.89-0.34,1.34-1.33,1-2.22s-1.33-1.34-2.22-1c-0.8,0.3-1.52,0.73-2.03,1.2l-7.04,6.52
|
||||
c-0.7,0.65-0.74,1.74-0.09,2.43C23.73,33.68,24.19,33.86,24.65,33.86z M70.35,99.28l-0.37,0.36v-2.43c0-0.95-0.77-1.72-1.72-1.72
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v4.72H61.3c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h5.23c1.4,0,3.15-0.7,4.16-1.66l2.03-1.94
|
||||
c0.69-0.66,0.71-1.75,0.06-2.43C72.13,98.65,71.03,98.63,70.35,99.28z M52.6,101.93H41.3c-0.95,0-1.72,0.77-1.72,1.72
|
||||
s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S53.55,101.93,52.6,101.93z M88.92,36.35c-0.95,0-1.72,0.77-1.72,1.72v11.3
|
||||
c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-11.3C90.64,37.12,89.87,36.35,88.92,36.35z M32.61,101.93H21.3
|
||||
c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S33.56,101.93,32.61,101.93z M9.71,87.54
|
||||
c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v11.3C7.99,86.77,8.76,87.54,9.71,87.54z
|
||||
M12.61,101.93h-1.18v-7.42c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v7.42c0,1.9,1.54,3.44,3.44,3.44h1.18
|
||||
c0.95,0,1.72-0.77,1.72-1.72S13.56,101.93,12.61,101.93z M19.53,36.88c-0.65-0.7-1.74-0.74-2.43-0.09l-7.3,6.76
|
||||
c-0.55,0.51-0.93,1.15-1.16,1.6C8.22,46,8.56,47.03,9.41,47.46c0.25,0.12,0.51,0.18,0.77,0.18h0.01c0.14,0.04,0.29,0.07,0.45,0.07
|
||||
h5.6c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-2.13l5.33-4.94C20.14,38.66,20.18,37.57,19.53,36.88z M80.7,89.4l-4.05,3.86
|
||||
c-0.69,0.66-0.71,1.75-0.06,2.43c0.34,0.35,0.79,0.53,1.25,0.53c0.43,0,0.86-0.16,1.19-0.48l4.05-3.86
|
||||
c0.69-0.66,0.71-1.75,0.06-2.43C82.48,88.77,81.39,88.75,80.7,89.4z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M98.82,101.06c-11.63,0-21.09-9.46-21.09-21.09s9.46-21.09,21.09-21.09s21.09,9.46,21.09,21.09
|
||||
S110.45,101.06,98.82,101.06z M98.82,62.32c-9.73,0-17.65,7.92-17.65,17.65s7.92,17.65,17.65,17.65s17.65-7.92,17.65-17.65
|
||||
S108.55,62.32,98.82,62.32z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M110.44,81.84c0,1.1-0.9,2-2,2H89.2c-1.1,0-2-0.9-2-2v-3.75c0-1.1,0.9-2,2-2h19.25c1.1,0,2,0.9,2,2
|
||||
L110.44,81.84L110.44,81.84z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
25
resources/icons/rotate.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="rotate">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M66.98,120.65c-0.9,0-1.79-0.34-2.47-1.02L25.27,80.4c-0.66-0.66-1.02-1.54-1.02-2.47s0.36-1.82,1.02-2.47
|
||||
L64.5,36.22c1.37-1.36,3.58-1.36,4.95,0l39.23,39.23c1.36,1.36,1.36,3.58,0,4.95l-39.23,39.23
|
||||
C68.77,120.31,67.88,120.65,66.98,120.65z M66.98,38.19c-0.13,0-0.26,0.05-0.35,0.14L27.39,77.57c-0.13,0.12-0.14,0.28-0.14,0.35
|
||||
s0.02,0.23,0.14,0.35l39.23,39.23c0.19,0.19,0.52,0.19,0.71,0l39.23-39.23c0.19-0.19,0.19-0.52,0-0.71L67.33,38.34
|
||||
C67.24,38.24,67.11,38.19,66.98,38.19z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M11.27,78.49c-0.65,0-1.25-0.43-1.44-1.08c-1.45-5.02-2.19-10.21-2.19-15.41
|
||||
c0-30.59,24.89-55.48,55.48-55.48c15.38,0,29.68,6.15,40.27,17.33c0.57,0.6,0.54,1.55-0.06,2.12c-0.6,0.57-1.55,0.54-2.12-0.06
|
||||
C91.2,15.34,77.67,9.52,63.12,9.52c-28.94,0-52.48,23.54-52.48,52.48c0,4.92,0.7,9.82,2.07,14.58c0.23,0.8-0.23,1.63-1.03,1.86
|
||||
C11.55,78.47,11.41,78.49,11.27,78.49z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M117.27,42.19c-0.22,0-0.44-0.02-0.67-0.07l-23.34-4.67c-1.07-0.21-1.84-0.84-2.11-1.73
|
||||
c-0.27-0.88,0.02-1.83,0.8-2.61l18.98-18.98c0.77-0.77,1.73-1.07,2.61-0.8c0.88,0.27,1.51,1.04,1.73,2.11v0l4.67,23.34
|
||||
c0.2,1.01-0.06,1.97-0.71,2.62C118.72,41.92,118.03,42.19,117.27,42.19z M94.64,34.66l22.29,4.47l-4.45-22.3L94.64,34.66z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
38
resources/icons/scale.svg
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="scale">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M118.05,121.55H57.99c-1.93,0-3.5-1.57-3.5-3.5V57.99c0-1.93,1.57-3.5,3.5-3.5h60.06
|
||||
c1.93,0,3.5,1.57,3.5,3.5v60.06C121.55,119.98,119.98,121.55,118.05,121.55z M57.99,57.49c-0.27,0-0.5,0.23-0.5,0.5v60.06
|
||||
c0,0.27,0.23,0.5,0.5,0.5h60.06c0.27,0,0.5-0.23,0.5-0.5V57.99c0-0.27-0.23-0.5-0.5-0.5H57.99z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M43.54,121.55h-10.5c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10.5c0.83,0,1.5,0.67,1.5,1.5
|
||||
S44.37,121.55,43.54,121.55z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M18.35,121.55h-8.4c-1.93,0-3.5-1.57-3.5-3.5v-10.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v10.5
|
||||
c0,0.27,0.23,0.5,0.5,0.5h8.4c0.83,0,1.5,0.67,1.5,1.5S19.18,121.55,18.35,121.55z M7.95,94.36c-0.83,0-1.5-0.67-1.5-1.5V70.82
|
||||
c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v22.04C9.45,93.69,8.78,94.36,7.95,94.36z M7.95,57.63c-0.83,0-1.5-0.67-1.5-1.5V34.1
|
||||
c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v22.04C9.45,56.96,8.78,57.63,7.95,57.63z M7.95,20.91c-0.83,0-1.5-0.67-1.5-1.5V9.95
|
||||
c0-1.93,1.57-3.5,3.5-3.5h9.44c0.83,0,1.5,0.67,1.5,1.5s-0.67,1.5-1.5,1.5H9.95c-0.27,0-0.5,0.23-0.5,0.5v9.46
|
||||
C9.45,20.24,8.78,20.91,7.95,20.91z M120.05,19.83c-0.83,0-1.5-0.67-1.5-1.5V9.95c0-0.27-0.23-0.5-0.5-0.5h-10.52
|
||||
c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10.52c1.93,0,3.5,1.57,3.5,3.5v8.38C121.55,19.16,120.88,19.83,120.05,19.83z
|
||||
M92.84,9.45H70.81c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h22.04c0.83,0,1.5,0.67,1.5,1.5S93.67,9.45,92.84,9.45z
|
||||
M56.12,9.45H34.08c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h22.04c0.83,0,1.5,0.67,1.5,1.5S56.94,9.45,56.12,9.45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M120.05,45.04c-0.83,0-1.5-0.67-1.5-1.5v-10.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v10.5
|
||||
C121.55,44.37,120.88,45.04,120.05,45.04z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M49.38,44.41c0.78-0.78,0.78-2.05,0-2.83l-9.27-9.27c-0.78-0.78-0.78-2.05,0-2.83l4.95-4.95
|
||||
c0.78-0.78,0.51-1.41-0.59-1.41H25.13c-1.1,0-2,0.9-2,2v19.34c0,1.1,0.64,1.36,1.41,0.59l4.95-4.95c0.78-0.78,2.05-0.78,2.83,0
|
||||
l9.27,9.27c0.78,0.78,2.05,0.78,2.83,0L49.38,44.41z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
42
resources/icons/sla_supports.svg
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="SLA_supports">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M117.02,121.54H11.12c-1.93,0-3.5-1.57-3.5-3.5v-3.99c0-1.93,1.57-3.5,3.5-3.5h105.9
|
||||
c1.93,0,3.5,1.57,3.5,3.5v3.99C120.52,119.97,118.95,121.54,117.02,121.54z M11.12,113.55c-0.27,0-0.5,0.23-0.5,0.5v3.99
|
||||
c0,0.27,0.23,0.5,0.5,0.5h105.9c0.27,0,0.5-0.23,0.5-0.5v-3.99c0-0.27-0.23-0.5-0.5-0.5H11.12z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M32.08,108.06c-0.83,0-1.5-0.67-1.5-1.5v-18.8c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v18.8
|
||||
C33.58,107.39,32.9,108.06,32.08,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M48.02,108.06c-0.83,0-1.5-0.67-1.5-1.5v-8.14c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v8.14
|
||||
C49.52,107.39,48.85,108.06,48.02,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.04,108.06c-0.83,0-1.5-0.67-1.5-1.5V93.09c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v13.47
|
||||
C89.54,107.39,88.87,108.06,88.04,108.06z"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" d="M70.36,95.12l-6.29,4.2l-14.45-9.63l-2.5,2.6l15.96,10.64c0.3,0.2,0.64,0.3,0.99,0.3s0.69-0.1,0.99-0.3
|
||||
l7.9-5.27L70.36,95.12z"/>
|
||||
<polygon fill="#FFFFFF" points="88.97,86.99 86.35,84.46 77.91,90.09 80.5,92.63 "/>
|
||||
<path fill="#FFFFFF" d="M103.99,35.1L65.05,9.14c-0.6-0.4-1.37-0.4-1.97,0L24.14,35.1c-0.49,0.33-0.79,0.88-0.79,1.48v38.91
|
||||
c0,0.59,0.3,1.15,0.79,1.48l15.47,10.32l2.5-2.6L26.9,74.54V37.53l37.16-24.78l37.16,24.78v37.01l-7.32,4.88l2.61,2.53l7.46-4.98
|
||||
c0.49-0.33,0.79-0.88,0.79-1.48V36.58C104.78,35.99,104.49,35.43,103.99,35.1z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M96.16,108.06c-0.83,0-1.5-0.67-1.5-1.5V87.93L79,73.22c-0.6-0.57-0.63-1.52-0.07-2.12
|
||||
c0.57-0.6,1.52-0.63,2.12-0.07l16.13,15.15c0.3,0.28,0.47,0.68,0.47,1.09v19.27C97.66,107.39,96.99,108.06,96.16,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M40.08,108.06c-0.83,0-1.5-0.67-1.5-1.5V93.29c0-0.39,0.15-0.76,0.41-1.04l16.13-16.91
|
||||
c0.57-0.6,1.52-0.62,2.12-0.05c0.6,0.57,0.62,1.52,0.05,2.12L41.58,93.89v12.67C41.58,107.39,40.91,108.06,40.08,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M80.13,108.06c-0.83,0-1.5-0.67-1.5-1.5v-7.65L62.94,83.19c-0.59-0.59-0.58-1.54,0-2.12
|
||||
c0.59-0.58,1.54-0.59,2.12,0l16.13,16.15c0.28,0.28,0.44,0.66,0.44,1.06v8.27C81.63,107.39,80.96,108.06,80.13,108.06z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
19
resources/icons/split_objects.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="OBJECTS">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M34.63,91.95h-17.3c-4.96,0-9-4.04-9-9V17.28c0-4.96,4.04-9,9-9H83c4.96,0,9,4.04,9,9v17.3
|
||||
c0,1.66-1.34,3-3,3s-3-1.34-3-3v-17.3c0-1.65-1.35-3-3-3H17.32c-1.65,0-3,1.35-3,3v65.67c0,1.65,1.35,3,3,3h17.3
|
||||
c1.66,0,3,1.34,3,3S36.28,91.95,34.63,91.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M114.89,42.35H47.57c-2.85,0-5.18,2.33-5.18,5.18v67.32c0,2.85,2.33,5.18,5.18,5.18h67.32
|
||||
c2.85,0,5.18-2.33,5.18-5.18V47.52C120.07,44.68,117.74,42.35,114.89,42.35z M101.82,94.28c0,12.63-6.35,18.27-20.89,18.27
|
||||
s-20.42-5.64-20.42-18.27v-25.9c0-12.95,5.64-18.27,20.42-18.27c14.77,0,20.89,5.32,20.89,18.27V94.28z"/>
|
||||
<path fill="#ED6B21" d="M80.93,59.8c-7.94,0-9.45,3.58-9.45,9.14v24.78c0,5.8,1.51,9.13,9.45,9.13s9.93-3.33,9.93-9.13V68.94
|
||||
C90.86,63.38,89.43,59.8,80.93,59.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
18
resources/icons/split_parts.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, 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 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="PARTS">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M34.63,91.95h-17.3c-4.96,0-9-4.04-9-9V17.28c0-4.96,4.04-9,9-9H83c4.96,0,9,4.04,9,9v17.3
|
||||
c0,1.66-1.34,3-3,3s-3-1.34-3-3v-17.3c0-1.65-1.35-3-3-3H17.32c-1.65,0-3,1.35-3,3v65.67c0,1.65,1.35,3,3,3h17.3
|
||||
c1.66,0,3,1.34,3,3S36.28,91.95,34.63,91.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M114.91,42.32H47.57c-2.85,0-5.18,2.33-5.18,5.18v67.34c0,2.85,2.33,5.18,5.18,5.18h67.34
|
||||
c2.85,0,5.18-2.33,5.18-5.18V47.5C120.09,44.65,117.76,42.32,114.91,42.32z M99.95,74.39c0,12.84-7.27,18.81-22.04,18.81h-4.28
|
||||
v19.05H62.25V50.09h15.66c15.02,0,22.04,5.41,22.04,18.57C99.95,68.66,99.95,74.39,99.95,74.39z"/>
|
||||
<path fill="#ED6B21" d="M78.07,60.26h-4.52v22.2h4.36c8.08,0,10.74-2.74,10.74-8.64v-4.6C88.65,63.33,86.71,60.26,78.07,60.26z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-01-17 13:39+0100\n"
|
||||
"PO-Revision-Date: 2019-02-19 14:42+0100\n"
|
||||
"PO-Revision-Date: 2019-02-26 10:38+0100\n"
|
||||
"Last-Translator: Oleksandra Iushchenko <yusanka@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: uk\n"
|
||||
@ -51,6 +51,12 @@ msgstr "Відстань координат 0,0 G-коду від нижньог
|
||||
msgid "Circular"
|
||||
msgstr "Круговий"
|
||||
|
||||
msgid "Switch to %s mode"
|
||||
msgstr "Перейти до режиму %s"
|
||||
|
||||
msgid "Current mode is %s"
|
||||
msgstr "Поточний режим - %s"
|
||||
|
||||
#: src/slic3r/GUI/BedShapeDialog.cpp:69 src/slic3r/GUI/ConfigWizard.cpp:92
|
||||
#: src/slic3r/GUI/ConfigWizard.cpp:456 src/slic3r/GUI/ConfigWizard.cpp:470
|
||||
#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:204
|
||||
@ -730,11 +736,11 @@ msgstr "Преференції застосування"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:616
|
||||
msgid "Simple"
|
||||
msgstr ""
|
||||
msgstr "Простий"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:616
|
||||
msgid "Simple View Mode"
|
||||
msgstr ""
|
||||
msgstr "Простий режим перегляду"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:617 src/slic3r/GUI/GUI_ObjectList.cpp:39
|
||||
#: src/slic3r/GUI/Tab.cpp:948 src/slic3r/GUI/Tab.cpp:962
|
||||
@ -747,23 +753,23 @@ msgstr "Розширений"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:617
|
||||
msgid "Advanced View Mode"
|
||||
msgstr ""
|
||||
msgstr "Розширений режим перегляду"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:618
|
||||
msgid "Expert"
|
||||
msgstr ""
|
||||
msgstr "Експерт"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:618
|
||||
msgid "Expert View Mode"
|
||||
msgstr ""
|
||||
msgstr "Режим перегляду Експерт"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:620
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
msgstr "Режим"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:620
|
||||
msgid "Slic3r View Mode"
|
||||
msgstr ""
|
||||
msgstr "Режим перегляду Slic3r'у"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:622
|
||||
msgid "Change Application &Language"
|
||||
@ -1752,7 +1758,7 @@ msgstr "Вид"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:445
|
||||
msgid "&Help"
|
||||
msgstr "Доромога"
|
||||
msgstr "Допомога"
|
||||
|
||||
#: src/slic3r/GUI/MainFrame.cpp:472
|
||||
msgid "Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):"
|
||||
@ -5064,11 +5070,11 @@ msgstr "Вертикальна відстань між об'єктом та ін
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1923
|
||||
msgid "soluble"
|
||||
msgstr ""
|
||||
msgstr "розчинний"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1924
|
||||
msgid "detachable"
|
||||
msgstr ""
|
||||
msgstr "відривний"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1929
|
||||
msgid "Enforce support for the first"
|
||||
@ -5672,7 +5678,7 @@ msgstr ""
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:3050
|
||||
msgid "Help"
|
||||
msgstr ""
|
||||
msgstr "Допомога"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:3051
|
||||
msgid "Show this help."
|
||||
|
@ -1,11 +1,12 @@
|
||||
#version 110
|
||||
|
||||
attribute vec4 v_position;
|
||||
attribute vec2 v_tex_coords;
|
||||
|
||||
varying vec2 tex_coords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ftransform();
|
||||
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * v_position;
|
||||
tex_coords = v_tex_coords;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
|
||||
remove_definitions(-D_UNICODE -DUNICODE)
|
||||
@ -68,18 +70,31 @@ set(AVRDUDE_SOURCES
|
||||
)
|
||||
if (MSVC)
|
||||
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
||||
windows/utf8.c
|
||||
windows/unistd.cpp
|
||||
windows/getopt.c
|
||||
)
|
||||
endif()
|
||||
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||
|
||||
set(STANDALONE_SOURCES
|
||||
main-standalone.c
|
||||
add_executable(avrdude-conf-gen conf-generate.cpp)
|
||||
|
||||
# Config file embedding
|
||||
add_custom_command(
|
||||
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||
COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf > avrdude-slic3r.conf.h
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
add_executable(avrdude-slic3r ${STANDALONE_SOURCES})
|
||||
|
||||
add_custom_target(gen_conf_h
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h
|
||||
)
|
||||
|
||||
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||
add_dependencies(avrdude gen_conf_h)
|
||||
|
||||
add_executable(avrdude-slic3r main-standalone.cpp)
|
||||
target_link_libraries(avrdude-slic3r avrdude)
|
||||
set_target_properties(avrdude-slic3r PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
if (WIN32)
|
||||
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
|
||||
|
@ -158,8 +158,10 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
if (stk500_getsync(pgm) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
424
src/avrdude/avrdude-slic3r.conf
Normal file
@ -0,0 +1,424 @@
|
||||
|
||||
#
|
||||
# This is a basic minimal config file embedded into the avrdude-slic3r binary
|
||||
# so that it can work in a standalone manner.
|
||||
#
|
||||
# Only the bits useful for Prusa3D devices were copied over from avrdude.conf
|
||||
# If needed, more configuration can still be loaded into avrdude-slic3r
|
||||
# via the -C command-line option.
|
||||
#
|
||||
|
||||
|
||||
programmer
|
||||
id = "wiring";
|
||||
desc = "Wiring";
|
||||
type = "wiring";
|
||||
connection_type = serial;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "arduino";
|
||||
desc = "Arduino";
|
||||
type = "arduino";
|
||||
connection_type = serial;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "avr109";
|
||||
desc = "Atmel AppNote AVR109 Boot Loader";
|
||||
type = "butterfly";
|
||||
connection_type = serial;
|
||||
;
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ATmega2560
|
||||
#------------------------------------------------------------
|
||||
|
||||
part
|
||||
id = "m2560";
|
||||
desc = "ATmega2560";
|
||||
signature = 0x1e 0x98 0x01;
|
||||
has_jtag = yes;
|
||||
stk500_devcode = 0xB2;
|
||||
# avr910_devcode = 0x43;
|
||||
chip_erase_delay = 9000;
|
||||
pagel = 0xD7;
|
||||
bs2 = 0xA0;
|
||||
reset = dedicated;
|
||||
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
|
||||
"x x x x x x x x x x x x x x x x";
|
||||
|
||||
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x x x x x x x x x";
|
||||
|
||||
timeout = 200;
|
||||
stabdelay = 100;
|
||||
cmdexedelay = 25;
|
||||
synchloops = 32;
|
||||
bytedelay = 0;
|
||||
pollindex = 3;
|
||||
pollvalue = 0x53;
|
||||
predelay = 1;
|
||||
postdelay = 1;
|
||||
pollmethod = 1;
|
||||
|
||||
pp_controlstack =
|
||||
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
|
||||
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
|
||||
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
|
||||
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02;
|
||||
hventerstabdelay = 100;
|
||||
progmodedelay = 0;
|
||||
latchcycles = 5;
|
||||
togglevtg = 1;
|
||||
poweroffdelay = 15;
|
||||
resetdelayms = 1;
|
||||
resetdelayus = 0;
|
||||
hvleavestabdelay = 15;
|
||||
chiperasepulsewidth = 0;
|
||||
chiperasepolltimeout = 10;
|
||||
programfusepulsewidth = 0;
|
||||
programfusepolltimeout = 5;
|
||||
programlockpulsewidth = 0;
|
||||
programlockpolltimeout = 5;
|
||||
|
||||
idr = 0x31;
|
||||
spmcr = 0x57;
|
||||
rampz = 0x3b;
|
||||
allowfullpagebitstream = no;
|
||||
|
||||
ocdrev = 4;
|
||||
|
||||
memory "eeprom"
|
||||
paged = no; /* leave this "no" */
|
||||
page_size = 8; /* for parallel programming */
|
||||
size = 4096;
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
readback_p1 = 0x00;
|
||||
readback_p2 = 0x00;
|
||||
read = " 1 0 1 0 0 0 0 0",
|
||||
" x x x x a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
write = " 1 1 0 0 0 0 0 0",
|
||||
" x x x x a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
loadpage_lo = " 1 1 0 0 0 0 0 1",
|
||||
" 0 0 0 0 0 0 0 0",
|
||||
" 0 0 0 0 0 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
writepage = " 1 1 0 0 0 0 1 0",
|
||||
" 0 0 x x a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 0 0 0",
|
||||
" x x x x x x x x";
|
||||
|
||||
mode = 0x41;
|
||||
delay = 10;
|
||||
blocksize = 8;
|
||||
readsize = 256;
|
||||
;
|
||||
|
||||
memory "flash"
|
||||
paged = yes;
|
||||
size = 262144;
|
||||
page_size = 256;
|
||||
num_pages = 1024;
|
||||
min_write_delay = 4500;
|
||||
max_write_delay = 4500;
|
||||
readback_p1 = 0x00;
|
||||
readback_p2 = 0x00;
|
||||
read_lo = " 0 0 1 0 0 0 0 0",
|
||||
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
read_hi = " 0 0 1 0 1 0 0 0",
|
||||
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
loadpage_lo = " 0 1 0 0 0 0 0 0",
|
||||
" x x x x x x x x",
|
||||
" x a6 a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
loadpage_hi = " 0 1 0 0 1 0 0 0",
|
||||
" x x x x x x x x",
|
||||
" x a6 a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
writepage = " 0 1 0 0 1 1 0 0",
|
||||
"a15 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 x x x x x x x",
|
||||
" x x x x x x x x";
|
||||
|
||||
load_ext_addr = " 0 1 0 0 1 1 0 1",
|
||||
" 0 0 0 0 0 0 0 0",
|
||||
" 0 0 0 0 0 0 0 a16",
|
||||
" 0 0 0 0 0 0 0 0";
|
||||
|
||||
mode = 0x41;
|
||||
delay = 10;
|
||||
blocksize = 256;
|
||||
readsize = 256;
|
||||
;
|
||||
|
||||
memory "lfuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
|
||||
"x x x x x x x x i i i i i i i i";
|
||||
|
||||
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "hfuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
|
||||
"x x x x x x x x i i i i i i i i";
|
||||
|
||||
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "efuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
|
||||
"x x x x x x x x x x x x x i i i";
|
||||
|
||||
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "lock"
|
||||
size = 1;
|
||||
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x x x o o o o o o";
|
||||
|
||||
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
|
||||
"x x x x x x x x 1 1 i i i i i i";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
|
||||
"0 0 0 0 0 0 0 0 o o o o o o o o";
|
||||
;
|
||||
|
||||
memory "signature"
|
||||
size = 3;
|
||||
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
|
||||
"x x x x x x a1 a0 o o o o o o o o";
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ATmega32u4
|
||||
#------------------------------------------------------------
|
||||
|
||||
part
|
||||
id = "m32u4";
|
||||
desc = "ATmega32U4";
|
||||
signature = 0x1e 0x95 0x87;
|
||||
usbpid = 0x2ff4;
|
||||
has_jtag = yes;
|
||||
# stk500_devcode = 0xB2;
|
||||
# avr910_devcode = 0x43;
|
||||
chip_erase_delay = 9000;
|
||||
pagel = 0xD7;
|
||||
bs2 = 0xA0;
|
||||
reset = dedicated;
|
||||
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
|
||||
"x x x x x x x x x x x x x x x x";
|
||||
|
||||
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x x x x x x x x x";
|
||||
|
||||
timeout = 200;
|
||||
stabdelay = 100;
|
||||
cmdexedelay = 25;
|
||||
synchloops = 32;
|
||||
bytedelay = 0;
|
||||
pollindex = 3;
|
||||
pollvalue = 0x53;
|
||||
predelay = 1;
|
||||
postdelay = 1;
|
||||
pollmethod = 1;
|
||||
|
||||
pp_controlstack =
|
||||
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
|
||||
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
|
||||
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
|
||||
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
|
||||
hventerstabdelay = 100;
|
||||
progmodedelay = 0;
|
||||
latchcycles = 5;
|
||||
togglevtg = 1;
|
||||
poweroffdelay = 15;
|
||||
resetdelayms = 1;
|
||||
resetdelayus = 0;
|
||||
hvleavestabdelay = 15;
|
||||
chiperasepulsewidth = 0;
|
||||
chiperasepolltimeout = 10;
|
||||
programfusepulsewidth = 0;
|
||||
programfusepolltimeout = 5;
|
||||
programlockpulsewidth = 0;
|
||||
programlockpolltimeout = 5;
|
||||
|
||||
idr = 0x31;
|
||||
spmcr = 0x57;
|
||||
rampz = 0x3b;
|
||||
allowfullpagebitstream = no;
|
||||
|
||||
ocdrev = 3;
|
||||
|
||||
memory "eeprom"
|
||||
paged = no; /* leave this "no" */
|
||||
page_size = 4; /* for parallel programming */
|
||||
size = 1024;
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
readback_p1 = 0x00;
|
||||
readback_p2 = 0x00;
|
||||
read = " 1 0 1 0 0 0 0 0",
|
||||
" x x x x x a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
write = " 1 1 0 0 0 0 0 0",
|
||||
" x x x x x a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
loadpage_lo = " 1 1 0 0 0 0 0 1",
|
||||
" 0 0 0 0 0 0 0 0",
|
||||
" 0 0 0 0 0 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
writepage = " 1 1 0 0 0 0 1 0",
|
||||
" 0 0 x x x a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 0 0 0",
|
||||
" x x x x x x x x";
|
||||
|
||||
mode = 0x41;
|
||||
delay = 20;
|
||||
blocksize = 4;
|
||||
readsize = 256;
|
||||
;
|
||||
|
||||
memory "flash"
|
||||
paged = yes;
|
||||
size = 32768;
|
||||
page_size = 128;
|
||||
num_pages = 256;
|
||||
min_write_delay = 4500;
|
||||
max_write_delay = 4500;
|
||||
readback_p1 = 0x00;
|
||||
readback_p2 = 0x00;
|
||||
read_lo = " 0 0 1 0 0 0 0 0",
|
||||
" 0 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
read_hi = " 0 0 1 0 1 0 0 0",
|
||||
" 0 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 a6 a5 a4 a3 a2 a1 a0",
|
||||
" o o o o o o o o";
|
||||
|
||||
loadpage_lo = " 0 1 0 0 0 0 0 0",
|
||||
" x x x x x x x x",
|
||||
" x x a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
loadpage_hi = " 0 1 0 0 1 0 0 0",
|
||||
" x x x x x x x x",
|
||||
" x x a5 a4 a3 a2 a1 a0",
|
||||
" i i i i i i i i";
|
||||
|
||||
writepage = " 0 1 0 0 1 1 0 0",
|
||||
" a15 a14 a13 a12 a11 a10 a9 a8",
|
||||
" a7 a6 x x x x x x",
|
||||
" x x x x x x x x";
|
||||
|
||||
mode = 0x41;
|
||||
delay = 6;
|
||||
blocksize = 128;
|
||||
readsize = 256;
|
||||
;
|
||||
|
||||
memory "lfuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
|
||||
"x x x x x x x x i i i i i i i i";
|
||||
|
||||
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "hfuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
|
||||
"x x x x x x x x i i i i i i i i";
|
||||
|
||||
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "efuse"
|
||||
size = 1;
|
||||
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
|
||||
"x x x x x x x x x x x x i i i i";
|
||||
|
||||
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
|
||||
"x x x x x x x x o o o o o o o o";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "lock"
|
||||
size = 1;
|
||||
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
|
||||
"x x x x x x x x x x o o o o o o";
|
||||
|
||||
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
|
||||
"x x x x x x x x 1 1 i i i i i i";
|
||||
min_write_delay = 9000;
|
||||
max_write_delay = 9000;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
|
||||
"0 0 0 0 0 0 0 0 o o o o o o o o";
|
||||
;
|
||||
|
||||
memory "signature"
|
||||
size = 3;
|
||||
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
|
||||
"x x x x x x a1 a0 o o o o o o o o";
|
||||
;
|
||||
;
|
||||
|
||||
|
1188
src/avrdude/avrdude-slic3r.conf.h
Normal file
@ -42,7 +42,6 @@ static void avrdude_oom_handler(const char *context, void *user_p)
|
||||
|
||||
struct AvrDude::priv
|
||||
{
|
||||
std::string sys_config;
|
||||
std::deque<std::vector<std::string>> args;
|
||||
bool cancelled = false;
|
||||
int exit_code = 0;
|
||||
@ -54,8 +53,6 @@ struct AvrDude::priv
|
||||
|
||||
std::thread avrdude_thread;
|
||||
|
||||
priv(std::string &&sys_config) : sys_config(sys_config) {}
|
||||
|
||||
void set_handlers();
|
||||
void unset_handlers();
|
||||
int run_one(const std::vector<std::string> &args);
|
||||
@ -110,7 +107,7 @@ int AvrDude::priv::run_one(const std::vector<std::string> &args) {
|
||||
|
||||
message_fn(command_line.c_str(), command_line.size());
|
||||
|
||||
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), sys_config.c_str());
|
||||
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data());
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -130,7 +127,7 @@ int AvrDude::priv::run() {
|
||||
|
||||
// Public
|
||||
|
||||
AvrDude::AvrDude(std::string sys_config) : p(new priv(std::move(sys_config))) {}
|
||||
AvrDude::AvrDude() : p(new priv()) {}
|
||||
|
||||
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}
|
||||
|
||||
|
@ -22,8 +22,7 @@ public:
|
||||
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
|
||||
typedef std::function<void()> CompleteFn;
|
||||
|
||||
// Main c-tor, sys_config is the location of avrdude's main configuration file
|
||||
AvrDude(std::string sys_config);
|
||||
AvrDude();
|
||||
AvrDude(AvrDude &&);
|
||||
AvrDude(const AvrDude &) = delete;
|
||||
AvrDude &operator=(AvrDude &&) = delete;
|
||||
|
@ -55,7 +55,7 @@ void avrdude_cancel();
|
||||
#define MSG_TRACE (4) /* displayed with -vvvv, show trace commuication */
|
||||
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
|
||||
|
||||
int avrdude_main(int argc, char * argv [], const char *sys_config);
|
||||
int avrdude_main(int argc, char * argv []);
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
|
||||
|
41
src/avrdude/conf-generate.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* filename = argv[1];
|
||||
const char* symbol = argv[2];
|
||||
|
||||
size_t size = 0;
|
||||
std::fstream file(filename);
|
||||
if (!file.good()) {
|
||||
std::cerr << "Cannot read file: " << filename << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl;
|
||||
std::cout << "unsigned char " << symbol << "[] = {";
|
||||
|
||||
char c;
|
||||
std::cout << std::hex;
|
||||
std::cout.fill('0');
|
||||
for (file.get(c); !file.eof(); size++, file.get(c)) {
|
||||
if (size % 12 == 0) { std::cout << "\n "; }
|
||||
std::cout << "0x" << std::setw(2) << (unsigned)c << ", ";
|
||||
}
|
||||
|
||||
std::cout << "\n 0, 0\n};\n";
|
||||
|
||||
std::cout << std::dec;
|
||||
std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl;
|
||||
std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -32,6 +32,8 @@
|
||||
|
||||
#include "config_gram.h"
|
||||
|
||||
#include "avrdude-slic3r.conf.h" // Embedded config file
|
||||
|
||||
char default_programmer[MAX_STR_CONST];
|
||||
char default_parallel[PATH_MAX];
|
||||
char default_serial[PATH_MAX];
|
||||
@ -325,7 +327,7 @@ int read_config(const char * file)
|
||||
FILE * f;
|
||||
int r;
|
||||
|
||||
f = fopen(file, "r");
|
||||
f = fopen_utf8(file, "r");
|
||||
if (f == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
|
||||
progname, file, strerror(errno));
|
||||
@ -347,3 +349,33 @@ int read_config(const char * file)
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
extern YY_BUFFER_STATE yy_scan_bytes(char *base, size_t size);
|
||||
extern void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||
|
||||
int read_config_builtin()
|
||||
{
|
||||
int r;
|
||||
|
||||
lineno = 1;
|
||||
infile = "(builtin)";
|
||||
|
||||
// Note: Can't use yy_scan_buffer, it's buggy (?), leads to fread from a null FILE*
|
||||
// and so unfortunatelly we have to use the copying variant here
|
||||
YY_BUFFER_STATE buffer = yy_scan_bytes(avrdude_slic3r_conf, avrdude_slic3r_conf_size);
|
||||
if (buffer == NULL) {
|
||||
avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = yyparse();
|
||||
yy_delete_buffer(buffer);
|
||||
|
||||
#ifdef HAVE_YYLEX_DESTROY
|
||||
/* reset lexer and free any allocated memory */
|
||||
yylex_destroy();
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -40,6 +40,9 @@
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
||||
#if defined(WIN32NATIVE)
|
||||
#include "windows/utf8.h"
|
||||
#endif
|
||||
|
||||
#define IHEX_MAXDATA 256
|
||||
|
||||
@ -102,21 +105,25 @@ static int fmt_autodetect(char * fname, unsigned section);
|
||||
|
||||
|
||||
|
||||
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
|
||||
FILE *fopen_utf8(const char *filename, const char *mode)
|
||||
{
|
||||
FILE *file;
|
||||
// On Windows we need to convert the filename to UTF-16
|
||||
#if defined(WIN32NATIVE)
|
||||
static wchar_t fname_buffer[PATH_MAX];
|
||||
static wchar_t mode_buffer[MAX_MODE_LEN];
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
|
||||
if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
|
||||
|
||||
file = _wfopen(fname_buffer, mode_buffer);
|
||||
return _wfopen(fname_buffer, mode_buffer);
|
||||
#else
|
||||
file = fopen(filename, mode);
|
||||
return fopen(filename, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
|
||||
{
|
||||
FILE *file = fopen_utf8(filename, mode);
|
||||
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
|
@ -1527,8 +1527,10 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1579,8 +1581,10 @@ static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1631,8 +1635,10 @@ static int jtagmkII_open_pdi(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1684,8 +1690,10 @@ static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1737,8 +1745,10 @@ static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1790,8 +1800,10 @@ static int jtagmkII_dragon_open_pdi(PROGRAMMER * pgm, char * port)
|
||||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0)
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_PDI) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -3370,6 +3382,8 @@ static int jtagmkII_open32(PROGRAMMER * pgm, char * port)
|
||||
status = jtagmkII_getsync(pgm, -1);
|
||||
if(status < 0) return -1;
|
||||
|
||||
// FIXME: Error handling is bad here: memory leak in resp (?) and port not closed
|
||||
|
||||
// AVR32 "special"
|
||||
buf[0] = CMND_SET_PARAMETER;
|
||||
buf[1] = 0x2D;
|
||||
|
@ -820,6 +820,8 @@ extern "C" {
|
||||
|
||||
char * fmtstr(FILEFMT format);
|
||||
|
||||
FILE *fopen_utf8(const char *filename, const char *mode);
|
||||
|
||||
int fileio(int op, char * filename, FILEFMT format,
|
||||
struct avrpart * p, char * memtype, int size, unsigned section);
|
||||
|
||||
@ -939,6 +941,7 @@ int init_config(void);
|
||||
void cleanup_config(void);
|
||||
|
||||
int read_config(const char * file);
|
||||
int read_config_builtin();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
#include "avrdude.h"
|
||||
|
||||
|
||||
static const char* SYS_CONFIG = "/etc/avrdude-slic3r.conf";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return avrdude_main(argc, argv, SYS_CONFIG);
|
||||
}
|
54
src/avrdude/main-standalone.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
extern "C" {
|
||||
#include "avrdude.h"
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "windows/utf8.h"
|
||||
}
|
||||
|
||||
struct ArgvUtf8 : std::vector<char*>
|
||||
{
|
||||
int argc;
|
||||
|
||||
ArgvUtf8(int argc_w, wchar_t *argv_w[]) : std::vector<char*>(argc_w + 1, nullptr), argc(0)
|
||||
{
|
||||
for (int i = 0; i < argc_w; i++) {
|
||||
char *arg_utf8 = ::wstr_to_utf8(argv_w[i], -1);
|
||||
if (arg_utf8 != nullptr) {
|
||||
operator[](i) = arg_utf8;
|
||||
argc = i + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~ArgvUtf8()
|
||||
{
|
||||
for (char *arg : *this) {
|
||||
if (arg != nullptr) {
|
||||
::free(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int wmain(int argc_w, wchar_t *argv_w[])
|
||||
{
|
||||
ArgvUtf8 argv_utf8(argc_w, argv_w);
|
||||
return ::avrdude_main(argv_utf8.argc, &argv_utf8[0]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return ::avrdude_main(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
@ -426,7 +426,7 @@ static int cleanup_main(int status)
|
||||
/*
|
||||
* main routine
|
||||
*/
|
||||
int avrdude_main(int argc, char * argv [], const char *sys_config)
|
||||
int avrdude_main(int argc, char * argv [])
|
||||
{
|
||||
int rc; /* general return code checking */
|
||||
int exitrc; /* exit code for main() */
|
||||
@ -807,13 +807,15 @@ int avrdude_main(int argc, char * argv [], const char *sys_config)
|
||||
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
|
||||
"%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
|
||||
progname, version, __DATE__, __TIME__, progbuf, progbuf);
|
||||
avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
|
||||
progbuf, sys_config);
|
||||
// avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
|
||||
// progbuf, sys_config);
|
||||
|
||||
rc = read_config(sys_config);
|
||||
// rc = read_config(sys_config);
|
||||
rc = read_config_builtin();
|
||||
if (rc) {
|
||||
avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
|
||||
progname, sys_config);
|
||||
// avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
|
||||
// progname, sys_config);
|
||||
avrdude_message(MSG_INFO, "%s: error reading built-in configuration file\n", progname);
|
||||
return cleanup_main(1);
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
||||
long serial_recv_timeout = 5000; /* ms */
|
||||
long serial_recv_timeout = 4000; /* ms */
|
||||
#define MAX_ZERO_READS 512
|
||||
|
||||
struct baud_mapping {
|
||||
@ -150,6 +150,68 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Timeout read & write variants
|
||||
// Additionally to the regular -1 on I/O error, they return -2 on timeout
|
||||
ssize_t read_timeout(int fd, void *buf, size_t count, long timeout)
|
||||
{
|
||||
struct timeval tm, tm2;
|
||||
fd_set rfds;
|
||||
int nfds;
|
||||
|
||||
tm.tv_sec = timeout / 1000L;
|
||||
tm.tv_usec = (timeout % 1000L) * 1000;
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
tm2 = tm;
|
||||
nfds = select(fd + 1, &rfds, NULL, NULL, &tm2);
|
||||
|
||||
if (nfds == 0) {
|
||||
return -2;
|
||||
} else if (nfds == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return read(fd, buf, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t write_timeout(int fd, const void *buf, size_t count, long timeout)
|
||||
{
|
||||
struct timeval tm, tm2;
|
||||
fd_set wfds;
|
||||
int nfds;
|
||||
|
||||
tm.tv_sec = timeout / 1000L;
|
||||
tm.tv_usec = (timeout % 1000L) * 1000;
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(fd, &wfds);
|
||||
tm2 = tm;
|
||||
nfds = select(fd + 1, NULL, &wfds, NULL, &tm2);
|
||||
|
||||
if (nfds == 0) {
|
||||
return -2;
|
||||
} else if (nfds == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return write(fd, buf, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given a port description of the form <host>:<port>, open a TCP
|
||||
* connection to the specified destination, which is assumed to be a
|
||||
@ -314,6 +376,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
int rc;
|
||||
const unsigned char * p = buf;
|
||||
size_t len = buflen;
|
||||
unsigned zero_writes = 0;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
@ -341,14 +404,25 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
|
||||
while (len) {
|
||||
RETURN_IF_CANCEL();
|
||||
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
||||
progname, strerror(errno));
|
||||
rc = write_timeout(fd->ifd, p, (len > 1024) ? 1024 : len, serial_recv_timeout);
|
||||
if (rc == -2) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding\n", progname);
|
||||
return -1;
|
||||
} else if (rc == -1) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
} else if (rc == 0) {
|
||||
zero_writes++;
|
||||
if (zero_writes > MAX_ZERO_READS) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_send(): programmer is not responding (too many zero writes)\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
zero_writes = 0;
|
||||
p += rc;
|
||||
len -= rc;
|
||||
}
|
||||
p += rc;
|
||||
len -= rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -357,51 +431,21 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
|
||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
struct timeval timeout, to2;
|
||||
fd_set rfds;
|
||||
int nfds;
|
||||
int rc;
|
||||
unsigned char * p = buf;
|
||||
size_t len = 0;
|
||||
unsigned zero_reads = 0;
|
||||
|
||||
timeout.tv_sec = serial_recv_timeout / 1000L;
|
||||
timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
|
||||
to2 = timeout;
|
||||
|
||||
while (len < buflen) {
|
||||
reselect:
|
||||
RETURN_IF_CANCEL();
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd->ifd, &rfds);
|
||||
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||
// FIXME: The timeout has different behaviour on Linux vs other Unices
|
||||
// On Linux, the timeout is modified by subtracting the time spent,
|
||||
// on OS X (for example), it is not modified.
|
||||
// POSIX recommends re-initializing it before selecting.
|
||||
if (nfds == 0) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
rc = read_timeout(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, serial_recv_timeout);
|
||||
|
||||
if (rc == -2) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
|
||||
return -1;
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): programmer is not responding,reselecting\n",
|
||||
progname);
|
||||
goto reselect;
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n",
|
||||
progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
} else if (rc == -1) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
} else if (rc == 0) {
|
||||
zero_reads++;
|
||||
@ -445,49 +489,26 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||
|
||||
static int ser_drain(union filedescriptor *fd, int display)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set rfds;
|
||||
int nfds;
|
||||
int rc;
|
||||
unsigned char buf;
|
||||
unsigned zero_reads = 0;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 250000;
|
||||
|
||||
if (display) {
|
||||
avrdude_message(MSG_INFO, "drain>");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd->ifd, &rfds);
|
||||
|
||||
reselect:
|
||||
RETURN_IF_CANCEL();
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
||||
if (nfds == 0) {
|
||||
|
||||
rc = read_timeout(fd->ifd, &buf, 1, 250); // Note: timeout needs to be kept low to not timeout in programmers
|
||||
if (rc == -2) {
|
||||
if (display) {
|
||||
avrdude_message(MSG_INFO, "<drain\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
if (errno == EINTR) {
|
||||
goto reselect;
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n",
|
||||
progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = read(fd->ifd, &buf, 1);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
||||
progname, strerror(errno));
|
||||
break;
|
||||
} else if (rc == -1) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
} else if (rc == 0) {
|
||||
zero_reads++;
|
||||
|
@ -34,16 +34,63 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h> /* for isprint */
|
||||
#include <errno.h> /* ENOTTY */
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
#include "windows/utf8.h"
|
||||
|
||||
long serial_recv_timeout = 5000; /* ms */
|
||||
|
||||
#define W32SERBUFSIZE 1024
|
||||
|
||||
|
||||
// Get last error message string in UTF-8
|
||||
// Always return a valid null-terminated string
|
||||
// The returned string should be freed by the caller
|
||||
char* last_error_string(int wsa)
|
||||
{
|
||||
LPWSTR wbuffer = NULL;
|
||||
|
||||
(void)wsa;
|
||||
|
||||
DWORD wbuffer_len = FormatMessageW(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
#ifdef HAVE_LIBWS2_32
|
||||
wsa ? WSAGetLastError() : GetLastError(),
|
||||
#else
|
||||
GetLastError(),
|
||||
#endif
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&wbuffer,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (wbuffer_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *res = wstr_to_utf8(wbuffer, wbuffer_len);
|
||||
|
||||
LocalFree(wbuffer);
|
||||
|
||||
if (res == NULL) {
|
||||
// If we get here, conversion to UTF-8 failed
|
||||
res = strdup("(could not get error message)");
|
||||
if (res == NULL) {
|
||||
avrdude_oom("last_error_string(): out of memory\n");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
struct baud_mapping {
|
||||
long baud;
|
||||
DWORD speed;
|
||||
@ -95,6 +142,7 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
||||
// ctmo.ReadIntervalTimeout = timeout;
|
||||
// ctmo.ReadTotalTimeoutMultiplier = timeout;
|
||||
ctmo.ReadTotalTimeoutConstant = timeout;
|
||||
ctmo.WriteTotalTimeoutConstant = timeout;
|
||||
|
||||
return SetCommTimeouts(hComPort, &ctmo);
|
||||
}
|
||||
@ -129,7 +177,6 @@ static int
|
||||
net_open(const char *port, union filedescriptor *fdp)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
char *hstr, *pstr, *end;
|
||||
unsigned int pnum;
|
||||
@ -175,18 +222,10 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||
free(hstr);
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, (char *)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
const char *error = last_error_string(1);
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, error);
|
||||
free(error);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -196,18 +235,9 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname, (char *)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
const char *error = last_error_string(1);
|
||||
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -221,7 +251,6 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||
|
||||
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
||||
char *newname = 0;
|
||||
|
||||
@ -261,19 +290,9 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
|
||||
progname, port, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
const char *error = last_error_string(0);
|
||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -346,14 +365,13 @@ static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
|
||||
#ifdef HAVE_LIBWS2_32
|
||||
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
int rc;
|
||||
const unsigned char *p = buf;
|
||||
size_t len = buflen;
|
||||
|
||||
if (fd->ifd < 0) {
|
||||
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
@ -382,19 +400,10 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
while (len) {
|
||||
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
|
||||
if (rc < 0) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, (char *)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
const char *error = last_error_string(1);
|
||||
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
p += rc;
|
||||
len -= rc;
|
||||
@ -423,8 +432,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n",
|
||||
progname);
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -449,18 +457,18 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
}
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
}
|
||||
|
||||
|
||||
serial_w32SetTimeOut(hComPort,500);
|
||||
|
||||
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
||||
progname, "sorry no info avail"); // TODO
|
||||
if (!WriteFile(hComPort, buf, buflen, &written, NULL)) {
|
||||
const char *error = last_error_string(0);
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (written != buflen) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n",
|
||||
progname);
|
||||
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -471,7 +479,6 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||
#ifdef HAVE_LIBWS2_32
|
||||
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
struct timeval timeout, to2;
|
||||
fd_set rfds;
|
||||
int nfds;
|
||||
@ -481,7 +488,7 @@ static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||
|
||||
if (fd->ifd < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout.tv_sec = serial_recv_timeout / 1000L;
|
||||
@ -504,37 +511,19 @@ reselect:
|
||||
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
|
||||
goto reselect;
|
||||
} else {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, (char *)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
const char *error = last_error_string(1);
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
|
||||
if (rc < 0) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, (char *)lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
exit(1);
|
||||
const char *error = last_error_string(1);
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
p += rc;
|
||||
len += rc;
|
||||
@ -579,37 +568,24 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||
RETURN_IF_CANCEL();
|
||||
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
|
||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n",
|
||||
progname);
|
||||
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
|
||||
|
||||
|
||||
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
||||
progname, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
const char *error = last_error_string(0);
|
||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* time out detected */
|
||||
if (read == 0) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
||||
progname);
|
||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -664,20 +640,9 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||
|
||||
readres=ReadFile(hComPort, buf, 1, &read, NULL);
|
||||
if (!readres) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL );
|
||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
||||
progname, (char*)lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
const char *error = last_error_string(0);
|
||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
|
||||
free(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -669,11 +669,15 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
|
||||
|
||||
// MIB510 init
|
||||
if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 &&
|
||||
mib510_isp(pgm, 1) != 0)
|
||||
mib510_isp(pgm, 1) != 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
if (stk500_getsync(pgm) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1695,8 +1695,10 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
if (pgm->bitclock != 0.0) {
|
||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1753,8 +1755,10 @@ static int stk600_open(PROGRAMMER * pgm, char * port)
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
if (pgm->bitclock != 0.0) {
|
||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
45
src/avrdude/windows/utf8.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include "utf8.h"
|
||||
|
||||
|
||||
char* wstr_to_utf8(LPWSTR wstr, int len)
|
||||
{
|
||||
char *res = NULL;
|
||||
|
||||
int res_size = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
||||
if (res_size > 0) {
|
||||
// Note: WideCharToMultiByte doesn't null-terminate if real (ie. > 0) buffer length is passed
|
||||
res = malloc(len != - 1 ? res_size + 1 : res_size);
|
||||
if (res == NULL) { return NULL; }
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, wstr, len, res, res_size, NULL, NULL) == res_size) {
|
||||
if (len != -1) { res[res_size] = '\0'; }
|
||||
} else {
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
LPWSTR utf8_to_wstr(const char *str, int len)
|
||||
{
|
||||
LPWSTR res = NULL;
|
||||
|
||||
int res_size = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
|
||||
if (res_size > 0) {
|
||||
// Note: MultiByteToWideChar doesn't null-terminate if real (ie. > 0) buffer length is passed
|
||||
res = malloc(len != - 1 ? res_size + 1 : res_size);
|
||||
|
||||
if (res == NULL) { return NULL; }
|
||||
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, str, len, res, res_size) == res_size) {
|
||||
if (len != -1) { res[res_size] = L'\0'; }
|
||||
} else {
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
10
src/avrdude/windows/utf8.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef SLIC3R_AVRDUDE_UTF8_H
|
||||
#define SLIC3R_AVRDUDE_UTF8_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
extern char* wstr_to_utf8(LPWSTR wstr, int len);
|
||||
extern LPWSTR utf8_to_wstr(const char *str, int len);
|
||||
|
||||
|
||||
#endif // SLIC3R_AVRDUDE_UTF8_H
|
@ -192,8 +192,10 @@ static int wiring_open(PROGRAMMER * pgm, char * port)
|
||||
/* drain any extraneous input */
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
if (stk500v2_getsync(pgm) < 0)
|
||||
if (stk500v2_getsync(pgm) < 0) {
|
||||
serial_close(&pgm->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,14 +42,20 @@ public:
|
||||
bool bridge;
|
||||
|
||||
Flow(float _w, float _h, float _nd, bool _bridge = false) :
|
||||
width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {};
|
||||
width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {}
|
||||
|
||||
float spacing() const;
|
||||
float spacing(const Flow &other) const;
|
||||
double mm3_per_mm() const;
|
||||
coord_t scaled_width() const { return coord_t(scale_(this->width)); };
|
||||
coord_t scaled_spacing() const { return coord_t(scale_(this->spacing())); };
|
||||
coord_t scaled_spacing(const Flow &other) const { return coord_t(scale_(this->spacing(other))); };
|
||||
coord_t scaled_width() const { return coord_t(scale_(this->width)); }
|
||||
coord_t scaled_spacing() const { return coord_t(scale_(this->spacing())); }
|
||||
coord_t scaled_spacing(const Flow &other) const { return coord_t(scale_(this->spacing(other))); }
|
||||
|
||||
// Elephant foot compensation spacing to be used to detect narrow parts, where the elephant foot compensation cannot be applied.
|
||||
// To be used on frExternalPerimeter only.
|
||||
// Enable some perimeter squish (see INSET_OVERLAP_TOLERANCE).
|
||||
// Here an overlap of 0.2x external perimeter spacing is allowed for by the elephant foot compensation.
|
||||
coord_t scaled_elephant_foot_spacing() const { return coord_t(0.5f * float(this->scaled_width() + 0.6f * this->scaled_spacing())); }
|
||||
|
||||
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio);
|
||||
// Create a flow from the spacing of extrusion lines.
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "3mf.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
@ -1749,6 +1751,11 @@ namespace Slic3r {
|
||||
bool _3MF_Exporter::_add_model_file_to_archive(mz_zip_archive& archive, Model& model)
|
||||
{
|
||||
std::stringstream stream;
|
||||
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
|
||||
// Conversion of a floating-point value to text and back is exact as long as at least max_digits10 were used (9 for float, 17 for double).
|
||||
// It is guaranteed to produce the same floating-point value, even though the intermediate text representation is not exact.
|
||||
// The default value of std::stream precision is 6 digits only!
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n";
|
||||
stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "</" << METADATA_TAG << ">\n";
|
||||
@ -1864,7 +1871,7 @@ namespace Slic3r {
|
||||
for (int i = 0; i < stl.stats.shared_vertices; ++i)
|
||||
{
|
||||
stream << " <" << VERTEX_TAG << " ";
|
||||
Vec3d v = matrix * stl.v_shared[i].cast<double>();
|
||||
Vec3f v = (matrix * stl.v_shared[i].cast<double>()).cast<float>();
|
||||
stream << "x=\"" << v(0) << "\" ";
|
||||
stream << "y=\"" << v(1) << "\" ";
|
||||
stream << "z=\"" << v(2) << "\" />\n";
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <limits>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -856,6 +857,11 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
return false;
|
||||
|
||||
std::stringstream stream;
|
||||
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
|
||||
// Conversion of a floating-point value to text and back is exact as long as at least max_digits10 were used (9 for float, 17 for double).
|
||||
// It is guaranteed to produce the same floating-point value, even though the intermediate text representation is not exact.
|
||||
// The default value of std::stream precision is 6 digits only!
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<amf unit=\"millimeter\">\n";
|
||||
stream << "<metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>\n";
|
||||
@ -927,7 +933,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||
for (size_t i = 0; i < stl.stats.shared_vertices; ++i) {
|
||||
stream << " <vertex>\n";
|
||||
stream << " <coordinates>\n";
|
||||
Vec3d v = matrix * stl.v_shared[i].cast<double>();
|
||||
Vec3f v = (matrix * stl.v_shared[i].cast<double>()).cast<float>();
|
||||
stream << " <x>" << v(0) << "</x>\n";
|
||||
stream << " <y>" << v(1) << "</y>\n";
|
||||
stream << " <z>" << v(2) << "</z>\n";
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "libslic3r.h"
|
||||
#include "GCode.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
@ -574,6 +575,16 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
// resets analyzer
|
||||
m_analyzer.reset();
|
||||
|
||||
// send extruder offset data to analyzer
|
||||
GCodeAnalyzer::ExtruderOffsetsMap extruder_offsets;
|
||||
for (unsigned int extruder_id : print.extruders())
|
||||
{
|
||||
Vec2d offset = print.config().extruder_offset.get_at(extruder_id);
|
||||
if (!offset.isApprox(Vec2d::Zero()))
|
||||
extruder_offsets[extruder_id] = offset;
|
||||
}
|
||||
m_analyzer.set_extruder_offsets(extruder_offsets);
|
||||
|
||||
// resets analyzer's tracking data
|
||||
m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
|
||||
m_last_width = GCodeAnalyzer::Default_Width;
|
||||
@ -843,7 +854,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
for (unsigned int extruder_id : print.extruders()) {
|
||||
const Vec2d &extruder_offset = print.config().extruder_offset.get_at(extruder_id);
|
||||
Polygon s(outer_skirt);
|
||||
s.translate(Point::new_scale(- extruder_offset(0), - extruder_offset(1)));
|
||||
s.translate(Point::new_scale(-extruder_offset(0), -extruder_offset(1)));
|
||||
skirts.emplace_back(std::move(s));
|
||||
}
|
||||
m_ooze_prevention.enable = true;
|
||||
@ -2488,6 +2499,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
// adds analyzer tags and updates analyzer's tracking data
|
||||
if (m_enable_analyzer)
|
||||
{
|
||||
// PrusaMultiMaterial::Writer may generate GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines without updating m_last_height and m_last_width
|
||||
// so, if the last role was erWipeTower we force export of GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines
|
||||
bool last_was_wipe_tower = (m_last_analyzer_extrusion_role == erWipeTower);
|
||||
|
||||
if (path.role() != m_last_analyzer_extrusion_role)
|
||||
{
|
||||
m_last_analyzer_extrusion_role = path.role();
|
||||
@ -2505,7 +2520,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
if (m_last_width != path.width)
|
||||
if (last_was_wipe_tower || (m_last_width != path.width))
|
||||
{
|
||||
m_last_width = path.width;
|
||||
|
||||
@ -2514,7 +2529,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
if (m_last_height != path.height)
|
||||
if (last_was_wipe_tower || (m_last_height != path.height))
|
||||
{
|
||||
m_last_height = path.height;
|
||||
|
||||
|
@ -101,6 +101,11 @@ GCodeAnalyzer::GCodeAnalyzer()
|
||||
reset();
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::set_extruder_offsets(const GCodeAnalyzer::ExtruderOffsetsMap& extruder_offsets)
|
||||
{
|
||||
m_extruder_offsets = extruder_offsets;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::reset()
|
||||
{
|
||||
_set_units(Millimeters);
|
||||
@ -118,6 +123,7 @@ void GCodeAnalyzer::reset()
|
||||
_reset_axes_position();
|
||||
|
||||
m_moves_map.clear();
|
||||
m_extruder_offsets.clear();
|
||||
}
|
||||
|
||||
const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
||||
@ -654,7 +660,15 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
||||
it = m_moves_map.insert(TypeToMovesMap::value_type(type, GCodeMovesList())).first;
|
||||
|
||||
// store move
|
||||
it->second.emplace_back(type, _get_extrusion_role(), _get_extruder_id(), _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), _get_start_position(), _get_end_position(), _get_delta_extrusion(), _get_cp_color_id());
|
||||
Vec3d extruder_offset = Vec3d::Zero();
|
||||
unsigned int extruder_id = _get_extruder_id();
|
||||
ExtruderOffsetsMap::iterator extr_it = m_extruder_offsets.find(extruder_id);
|
||||
if (extr_it != m_extruder_offsets.end())
|
||||
extruder_offset = Vec3d(extr_it->second(0), extr_it->second(1), 0.0);
|
||||
|
||||
Vec3d start_position = _get_start_position() + extruder_offset;
|
||||
Vec3d end_position = _get_end_position() + extruder_offset;
|
||||
it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_cp_color_id());
|
||||
}
|
||||
|
||||
bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
|
||||
typedef std::vector<GCodeMove> GCodeMovesList;
|
||||
typedef std::map<GCodeMove::EType, GCodeMovesList> TypeToMovesMap;
|
||||
typedef std::map<unsigned int, Vec2d> ExtruderOffsetsMap;
|
||||
|
||||
private:
|
||||
struct State
|
||||
@ -104,6 +105,7 @@ private:
|
||||
State m_state;
|
||||
GCodeReader m_parser;
|
||||
TypeToMovesMap m_moves_map;
|
||||
ExtruderOffsetsMap m_extruder_offsets;
|
||||
|
||||
// The output of process_layer()
|
||||
std::string m_process_output;
|
||||
@ -111,6 +113,8 @@ private:
|
||||
public:
|
||||
GCodeAnalyzer();
|
||||
|
||||
void set_extruder_offsets(const ExtruderOffsetsMap& extruder_offsets);
|
||||
|
||||
// Reinitialize the analyzer
|
||||
void reset();
|
||||
|
||||
|
@ -242,6 +242,7 @@ public:
|
||||
|
||||
void set_scaling_factor(const Vec3d& scaling_factor);
|
||||
void set_scaling_factor(Axis axis, double scaling_factor);
|
||||
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
|
||||
|
||||
const Vec3d& get_mirror() const { return m_mirror; }
|
||||
double get_mirror(Axis axis) const { return m_mirror(axis); }
|
||||
|
@ -65,6 +65,7 @@ void Layer::make_slices()
|
||||
this->slices.expolygons.push_back(std::move(slices[i]));
|
||||
}
|
||||
|
||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
||||
void Layer::merge_slices()
|
||||
{
|
||||
if (m_regions.size() == 1) {
|
||||
@ -78,6 +79,24 @@ void Layer::merge_slices()
|
||||
}
|
||||
}
|
||||
|
||||
ExPolygons Layer::merged(float offset_scaled) const
|
||||
{
|
||||
assert(offset_scaled >= 0.f);
|
||||
// If no offset is set, apply EPSILON offset before union, and revert it afterwards.
|
||||
float offset_scaled2 = 0;
|
||||
if (offset_scaled == 0.f) {
|
||||
offset_scaled = float( EPSILON);
|
||||
offset_scaled2 = float(- EPSILON);
|
||||
}
|
||||
Polygons polygons;
|
||||
for (LayerRegion *layerm : m_regions)
|
||||
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
|
||||
ExPolygons out = union_ex(polygons);
|
||||
if (offset_scaled2 != 0.f)
|
||||
out = offset_ex(out, offset_scaled2);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Here the perimeters are created cummulatively for all layer regions sharing the same parameters influencing the perimeters.
|
||||
// The perimeter paths and the thin fills (ExtrusionEntityCollection) are assigned to the first compatible layer region.
|
||||
// The resulting fill surface is split back among the originating regions.
|
||||
@ -86,13 +105,14 @@ void Layer::make_perimeters()
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
|
||||
|
||||
// keep track of regions whose perimeters we have already generated
|
||||
std::set<size_t> done;
|
||||
std::vector<unsigned char> done(m_regions.size(), false);
|
||||
|
||||
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) {
|
||||
size_t region_id = layerm - m_regions.begin();
|
||||
if (done.find(region_id) != done.end()) continue;
|
||||
if (done[region_id])
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||
done.insert(region_id);
|
||||
done[region_id] = true;
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||
|
||||
// find compatible regions
|
||||
@ -112,7 +132,7 @@ void Layer::make_perimeters()
|
||||
&& config.thin_walls == other_config.thin_walls
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||
layerms.push_back(other_layerm);
|
||||
done.insert(it - m_regions.begin());
|
||||
done[it - m_regions.begin()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,15 +144,13 @@ void Layer::make_perimeters()
|
||||
SurfaceCollection new_slices;
|
||||
{
|
||||
// group slices (surfaces) according to number of extra perimeters
|
||||
std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||
for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
|
||||
slices[s->extra_perimeters].push_back(*s);
|
||||
}
|
||||
}
|
||||
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegion *layerm : layerms)
|
||||
for (Surface &surface : layerm->slices.surfaces)
|
||||
slices[surface.extra_perimeters].emplace_back(surface);
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it)
|
||||
new_slices.append(union_ex(it->second, true), it->second.front());
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||
}
|
||||
|
||||
// make perimeters
|
||||
|
@ -63,7 +63,12 @@ public:
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
|
||||
void process_external_surfaces(const Layer* lower_layer);
|
||||
double infill_area_threshold() const;
|
||||
double infill_area_threshold() const;
|
||||
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
|
||||
void trim_surfaces(const Polygons &trimming_polygons);
|
||||
// Single elephant foot compensation step, used by the elephant foor compensation at the 1st layer.
|
||||
// Trim surfaces by trimming polygons (shrunk by an elephant foot compensation step), but don't shrink narrow parts so much that no perimeter would fit.
|
||||
void elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons);
|
||||
|
||||
void export_region_slices_to_svg(const char *path) const;
|
||||
void export_region_fill_surfaces_to_svg(const char *path) const;
|
||||
@ -117,7 +122,10 @@ public:
|
||||
// Test whether whether there are any slices assigned to this layer.
|
||||
bool empty() const;
|
||||
void make_slices();
|
||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
||||
void merge_slices();
|
||||
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
|
||||
ExPolygons merged(float offset) const;
|
||||
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
||||
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true;
|
||||
return false;
|
||||
|
@ -74,7 +74,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
// Cummulative sum of polygons over all the regions.
|
||||
g.lower_slices = &this->layer()->lower_layer->slices;
|
||||
|
||||
g.layer_id = this->layer()->id();
|
||||
g.layer_id = (int)this->layer()->id();
|
||||
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
||||
g.overhang_flow = this->region()->flow(frPerimeter, -1, true, false, -1, *this->layer()->object());
|
||||
g.solid_infill_flow = this->flow(frSolidInfill);
|
||||
@ -385,6 +385,28 @@ double LayerRegion::infill_area_threshold() const
|
||||
return ss*ss;
|
||||
}
|
||||
|
||||
void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#endif /* NDEBUG */
|
||||
this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stInternal);
|
||||
}
|
||||
|
||||
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#endif /* NDEBUG */
|
||||
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
|
||||
Polygons slices_polygons = to_polygons(slices_expolygons);
|
||||
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
|
||||
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
||||
this->slices.set(std::move(union_ex(tmp)), stInternal);
|
||||
}
|
||||
|
||||
void LayerRegion::export_region_slices_to_svg(const char *path) const
|
||||
{
|
||||
BoundingBox bbox;
|
||||
|
@ -592,6 +592,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
|
||||
this->input_file = rhs.input_file;
|
||||
this->config = rhs.config;
|
||||
this->sla_support_points = rhs.sla_support_points;
|
||||
this->sla_points_status = rhs.sla_points_status;
|
||||
this->layer_height_ranges = rhs.layer_height_ranges;
|
||||
this->layer_height_profile = rhs.layer_height_profile;
|
||||
this->origin_translation = rhs.origin_translation;
|
||||
@ -625,6 +626,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
|
||||
this->input_file = std::move(rhs.input_file);
|
||||
this->config = std::move(rhs.config);
|
||||
this->sla_support_points = std::move(rhs.sla_support_points);
|
||||
this->sla_points_status = std::move(rhs.sla_points_status);
|
||||
this->layer_height_ranges = std::move(rhs.layer_height_ranges);
|
||||
this->layer_height_profile = std::move(rhs.layer_height_profile);
|
||||
this->origin_translation = std::move(rhs.origin_translation);
|
||||
@ -1130,6 +1132,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
||||
if (keep_upper) {
|
||||
upper->set_model(nullptr);
|
||||
upper->sla_support_points.clear();
|
||||
upper->sla_points_status = sla::PointsStatus::None;
|
||||
upper->clear_volumes();
|
||||
upper->input_file = "";
|
||||
}
|
||||
@ -1137,6 +1140,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
||||
if (keep_lower) {
|
||||
lower->set_model(nullptr);
|
||||
lower->sla_support_points.clear();
|
||||
lower->sla_points_status = sla::PointsStatus::None;
|
||||
lower->clear_volumes();
|
||||
lower->input_file = "";
|
||||
}
|
||||
|
@ -180,6 +180,9 @@ public:
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
// The format is (x, y, z, point_size, supports_island)
|
||||
std::vector<sla::SupportPoint> sla_support_points;
|
||||
// To keep track of where the points came from (used for synchronization between
|
||||
// the SLA gizmo and the backend).
|
||||
sla::PointsStatus sla_points_status = sla::PointsStatus::None;
|
||||
|
||||
/* This vector accumulates the total translation applied to the object by the
|
||||
center_around_origin() method. Callers might want to apply the same translation
|
||||
|
@ -523,6 +523,9 @@ exit_for_rearrange_regions:
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
for (PrintObject *object : m_objects)
|
||||
object->update_slicing_parameters();
|
||||
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
@ -1098,6 +1101,12 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
||||
}
|
||||
}
|
||||
|
||||
// Update SlicingParameters for each object where the SlicingParameters is not valid.
|
||||
// If it is not valid, then it is ensured that PrintObject.m_slicing_params is not in use
|
||||
// (posSlicing and posSupportMaterial was invalidated).
|
||||
for (PrintObject *object : m_objects)
|
||||
object->update_slicing_parameters();
|
||||
|
||||
#ifdef _DEBUG
|
||||
check_model_ids_equal(m_model, model);
|
||||
#endif /* _DEBUG */
|
||||
@ -1202,13 +1211,13 @@ std::string Print::validate() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
|
||||
const SlicingParameters &slicing_params0 = m_objects.front()->slicing_parameters();
|
||||
size_t tallest_object_idx = 0;
|
||||
if (has_custom_layering)
|
||||
PrintObject::update_layer_height_profile(*m_objects.front()->model_object(), slicing_params0, layer_height_profiles.front());
|
||||
for (size_t i = 1; i < m_objects.size(); ++ i) {
|
||||
const PrintObject *object = m_objects[i];
|
||||
const SlicingParameters slicing_params = object->slicing_parameters();
|
||||
const PrintObject *object = m_objects[i];
|
||||
const SlicingParameters &slicing_params = object->slicing_parameters();
|
||||
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
|
||||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
|
||||
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
const LayerPtrs& layers() const { return m_layers; }
|
||||
const SupportLayerPtrs& support_layers() const { return m_support_layers; }
|
||||
const Transform3d& trafo() const { return m_trafo; }
|
||||
const Points& copies() const { return m_copies; }
|
||||
const Points& copies() const { return m_copies; }
|
||||
|
||||
// since the object is aligned to origin, bounding box coincides with size
|
||||
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); }
|
||||
@ -131,7 +131,7 @@ public:
|
||||
// by the interactive layer height editor and by the printing process itself.
|
||||
// The slicing parameters are dependent on various configuration values
|
||||
// (layer height, first layer height, raft settings, print nozzle diameter etc).
|
||||
SlicingParameters slicing_parameters() const;
|
||||
const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
|
||||
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object);
|
||||
|
||||
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
||||
@ -161,6 +161,8 @@ protected:
|
||||
bool invalidate_all_steps();
|
||||
// Invalidate steps based on a set of parameters changed.
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
// If ! m_slicing_params.valid, recalculate.
|
||||
void update_slicing_parameters();
|
||||
|
||||
static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders);
|
||||
static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders);
|
||||
@ -195,11 +197,13 @@ private:
|
||||
// for external callers)
|
||||
Point m_copies_shift;
|
||||
|
||||
SlicingParameters m_slicing_params;
|
||||
LayerPtrs m_layers;
|
||||
SupportLayerPtrs m_support_layers;
|
||||
|
||||
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
||||
std::vector<ExPolygons> _slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const;
|
||||
std::vector<ExPolygons> _slice_volume(const std::vector<float> &z, const ModelVolume &volume) const;
|
||||
};
|
||||
|
||||
struct WipeTowerData
|
||||
|
@ -59,6 +59,41 @@ void PrintConfigDef::init_common_params()
|
||||
def->cli = "max-print-height=f";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionFloat(200.0);
|
||||
|
||||
def = this->add("slice_closing_radius", coFloat);
|
||||
def->label = L("Slice gap closing radius");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
|
||||
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
|
||||
def->sidetext = L("mm");
|
||||
def->cli = "slice-closing-radius=f";
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionFloat(0.049);
|
||||
|
||||
def = this->add("print_host", coString);
|
||||
def->label = L("Hostname, IP or URL");
|
||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
||||
"the hostname, IP address or URL of the printer host instance.");
|
||||
def->cli = "print-host=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("printhost_apikey", coString);
|
||||
def->label = L("API Key / Password");
|
||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
||||
"the API Key or the password required for authentication.");
|
||||
def->cli = "printhost-apikey=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("printhost_cafile", coString);
|
||||
def->label = "HTTPS CA File";
|
||||
def->tooltip = "Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. "
|
||||
"If left blank, the default OS CA certificate repository is used.";
|
||||
def->cli = "printhost-cafile=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
}
|
||||
|
||||
void PrintConfigDef::init_fff_params()
|
||||
@ -1320,30 +1355,6 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionEnum<PrintHostType>(htOctoPrint);
|
||||
|
||||
def = this->add("printhost_apikey", coString);
|
||||
def->label = L("API Key / Password");
|
||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
||||
"the API Key or the password required for authentication.");
|
||||
def->cli = "printhost-apikey=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("printhost_cafile", coString);
|
||||
def->label = "HTTPS CA File";
|
||||
def->tooltip = "Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. "
|
||||
"If left blank, the default OS CA certificate repository is used.";
|
||||
def->cli = "printhost-cafile=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("print_host", coString);
|
||||
def->label = L("Hostname, IP or URL");
|
||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
||||
"the hostname, IP address or URL of the printer host instance.");
|
||||
def->cli = "print-host=s";
|
||||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionString("");
|
||||
|
||||
def = this->add("only_retract_when_crossing_perimeters", coBool);
|
||||
def->label = L("Only retract when crossing perimeters");
|
||||
def->tooltip = L("Disables retraction when the travel path does not exceed the upper layer's perimeters "
|
||||
|
@ -38,7 +38,7 @@ enum GCodeFlavor {
|
||||
};
|
||||
|
||||
enum PrintHostType {
|
||||
htOctoPrint, htDuet, htSL1,
|
||||
htOctoPrint, htDuet
|
||||
};
|
||||
|
||||
enum InfillPattern {
|
||||
@ -384,6 +384,7 @@ public:
|
||||
ConfigOptionEnum<SeamPosition> seam_position;
|
||||
// ConfigOptionFloat seam_preferred_direction;
|
||||
// ConfigOptionFloat seam_preferred_direction_jitter;
|
||||
ConfigOptionFloat slice_closing_radius;
|
||||
ConfigOptionBool support_material;
|
||||
// Automatic supports (generated based on support_material_threshold).
|
||||
ConfigOptionBool support_material_auto;
|
||||
@ -425,6 +426,7 @@ protected:
|
||||
OPT_PTR(layer_height);
|
||||
OPT_PTR(raft_layers);
|
||||
OPT_PTR(seam_position);
|
||||
OPT_PTR(slice_closing_radius);
|
||||
// OPT_PTR(seam_preferred_direction);
|
||||
// OPT_PTR(seam_preferred_direction_jitter);
|
||||
OPT_PTR(support_material);
|
||||
@ -963,6 +965,8 @@ public:
|
||||
//Number of the layers needed for the exposure time fade [3;20]
|
||||
ConfigOptionInt faded_layers /*= 10*/;
|
||||
|
||||
ConfigOptionFloat slice_closing_radius;
|
||||
|
||||
// Enabling or disabling support creation
|
||||
ConfigOptionBool supports_enable;
|
||||
|
||||
@ -1036,6 +1040,7 @@ protected:
|
||||
{
|
||||
OPT_PTR(layer_height);
|
||||
OPT_PTR(faded_layers);
|
||||
OPT_PTR(slice_closing_radius);
|
||||
OPT_PTR(supports_enable);
|
||||
OPT_PTR(support_head_front_diameter);
|
||||
OPT_PTR(support_head_penetration);
|
||||
|
@ -157,8 +157,6 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
||||
"expTimeFirst = " + expt_first_str + "\n"
|
||||
"numFade = " + cnt_fade_layers + "\n"
|
||||
"layerHeight = " + layerh_str + "\n"
|
||||
"expTime = "+expt_str+" + resinType = generic+layerHeight = "
|
||||
+layerh_str+" + printer = DWARF3\n"
|
||||
"usedMaterial = " + used_material + "\n"
|
||||
"numSlow = " + cnt_slow_layers + "\n"
|
||||
"numFast = " + cnt_fast_layers + "\n";
|
||||
|
@ -104,7 +104,7 @@ void PrintObject::slice()
|
||||
return;
|
||||
m_print->set_status(10, "Processing triangulated mesh");
|
||||
std::vector<coordf_t> layer_height_profile;
|
||||
this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), layer_height_profile);
|
||||
this->update_layer_height_profile(*this->model_object(), m_slicing_params, layer_height_profile);
|
||||
m_print->throw_if_canceled();
|
||||
this->_slice(layer_height_profile);
|
||||
m_print->throw_if_canceled();
|
||||
@ -453,7 +453,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
} else if (
|
||||
opt_key == "layer_height"
|
||||
|| opt_key == "first_layer_height"
|
||||
|| opt_key == "raft_layers") {
|
||||
|| opt_key == "raft_layers"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
steps.emplace_back(posSlice);
|
||||
}
|
||||
else if (
|
||||
@ -567,8 +568,11 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
||||
} else if (step == posSlice) {
|
||||
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posSupportMaterial });
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
} else if (step == posSupportMaterial)
|
||||
this->m_slicing_params.valid = false;
|
||||
} else if (step == posSupportMaterial) {
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
this->m_slicing_params.valid = false;
|
||||
}
|
||||
|
||||
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
||||
// It also decides about what the wipe_into_infill / wipe_into_object features will do,
|
||||
@ -806,7 +810,7 @@ void PrintObject::process_external_surfaces()
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||
m_layers[layer_idx]->get_region(region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1359,11 +1363,11 @@ PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegion
|
||||
return config;
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters() const
|
||||
void PrintObject::update_slicing_parameters()
|
||||
{
|
||||
return SlicingParameters::create_from_config(
|
||||
this->print()->config(), m_config,
|
||||
unscale<double>(this->size(2)), this->object_extruders());
|
||||
if (! m_slicing_params.valid)
|
||||
m_slicing_params = SlicingParameters::create_from_config(
|
||||
this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders());
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object)
|
||||
@ -1450,23 +1454,21 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
tbb_init = new tbb::task_scheduler_init(1);
|
||||
#endif
|
||||
|
||||
SlicingParameters slicing_params = this->slicing_parameters();
|
||||
|
||||
// 1) Initialize layers and their slice heights.
|
||||
std::vector<float> slice_zs;
|
||||
{
|
||||
this->clear_layers();
|
||||
// Object layers (pairs of bottom/top Z coordinate), without the raft.
|
||||
std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, layer_height_profile);
|
||||
std::vector<coordf_t> object_layers = generate_object_layers(m_slicing_params, layer_height_profile);
|
||||
// Reserve object layers for the raft. Last layer of the raft is the contact layer.
|
||||
int id = int(slicing_params.raft_layers());
|
||||
int id = int(m_slicing_params.raft_layers());
|
||||
slice_zs.reserve(object_layers.size());
|
||||
Layer *prev = nullptr;
|
||||
for (size_t i_layer = 0; i_layer < object_layers.size(); i_layer += 2) {
|
||||
coordf_t lo = object_layers[i_layer];
|
||||
coordf_t hi = object_layers[i_layer + 1];
|
||||
coordf_t slice_z = 0.5 * (lo + hi);
|
||||
Layer *layer = this->add_layer(id ++, hi - lo, hi + slicing_params.object_print_z_min, slice_z);
|
||||
Layer *layer = this->add_layer(id ++, hi - lo, hi + m_slicing_params.object_print_z_min, slice_z);
|
||||
slice_zs.push_back(float(slice_z));
|
||||
if (prev != nullptr) {
|
||||
prev->upper_layer = layer;
|
||||
@ -1478,46 +1480,151 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
prev = layer;
|
||||
}
|
||||
}
|
||||
|
||||
// Count model parts and modifier meshes, check whether the model parts are of the same region.
|
||||
int single_volume_region = -2; // not set yet
|
||||
size_t num_volumes = 0;
|
||||
size_t num_modifiers = 0;
|
||||
std::vector<int> map_volume_to_region(this->model_object()->volumes.size());
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
for (int volume_id : this->region_volumes[region_id]) {
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
map_volume_to_region[volume_id] = region_id;
|
||||
if (single_volume_region == -2)
|
||||
// first model volume met
|
||||
single_volume_region = region_id;
|
||||
else if (single_volume_region != region_id)
|
||||
// multiple volumes met and they are not equal
|
||||
single_volume_region = -1;
|
||||
++ num_volumes;
|
||||
} else if (model_volume->is_modifier())
|
||||
++ num_modifiers;
|
||||
}
|
||||
}
|
||||
assert(num_volumes > 0);
|
||||
|
||||
// Slice all non-modifier volumes.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||
bool clipped = false;
|
||||
bool upscaled = false;
|
||||
if (! m_config.clip_multipart_objects.value || single_volume_region >= 0) {
|
||||
// Cheap path: Slice regions without mutual clipping.
|
||||
// The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||
}
|
||||
} else {
|
||||
// Expensive path: Slice one volume after the other in the order they are presented at the user interface,
|
||||
// clip the last volumes with the first.
|
||||
// First slice the volumes.
|
||||
struct SlicedVolume {
|
||||
SlicedVolume(int volume_id, int region_id, std::vector<ExPolygons> &&expolygons_by_layer) :
|
||||
volume_id(volume_id), region_id(region_id), expolygons_by_layer(std::move(expolygons_by_layer)) {}
|
||||
int volume_id;
|
||||
int region_id;
|
||||
std::vector<ExPolygons> expolygons_by_layer;
|
||||
};
|
||||
std::vector<SlicedVolume> sliced_volumes;
|
||||
sliced_volumes.reserve(num_volumes);
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||
for (int volume_id : this->region_volumes[region_id]) {
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
|
||||
// slicing in parallel
|
||||
sliced_volumes.emplace_back(volume_id, map_volume_to_region[volume_id], this->_slice_volume(slice_zs, *model_volume));
|
||||
}
|
||||
}
|
||||
// Second clip the volumes in the order they are presented at the user interface.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, slice_zs.size()),
|
||||
[this, &sliced_volumes, num_modifiers](const tbb::blocked_range<size_t>& range) {
|
||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||
// Only upscale together with clipping if there are no modifiers, as the modifiers shall be applied before upscaling
|
||||
// (upscaling may grow the object outside of the modifier mesh).
|
||||
bool upscale = delta > 0 && num_modifiers == 0;
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
m_print->throw_if_canceled();
|
||||
// Trim volumes in a single layer, one by the other, possibly apply upscaling.
|
||||
{
|
||||
Polygons processed;
|
||||
for (SlicedVolume &sliced_volume : sliced_volumes) {
|
||||
ExPolygons slices = std::move(sliced_volume.expolygons_by_layer[layer_id]);
|
||||
if (upscale)
|
||||
slices = offset_ex(std::move(slices), delta);
|
||||
if (! processed.empty())
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
sliced_volume.expolygons_by_layer[layer_id] = std::move(slices);
|
||||
}
|
||||
}
|
||||
// Collect and union volumes of a single region.
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
ExPolygons expolygons;
|
||||
size_t num_volumes = 0;
|
||||
for (SlicedVolume &sliced_volume : sliced_volumes)
|
||||
if (sliced_volume.region_id == region_id && ! sliced_volume.expolygons_by_layer[layer_id].empty()) {
|
||||
++ num_volumes;
|
||||
append(expolygons, std::move(sliced_volume.expolygons_by_layer[layer_id]));
|
||||
}
|
||||
if (num_volumes > 1)
|
||||
// Merge the islands using a positive / negative offset.
|
||||
expolygons = offset_ex(offset_ex(expolygons, float(scale_(EPSILON))), -float(scale_(EPSILON)));
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stInternal);
|
||||
}
|
||||
}
|
||||
});
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - end";
|
||||
clipped = true;
|
||||
upscaled = m_config.xy_size_compensation.value > 0 && num_modifiers == 0;
|
||||
}
|
||||
|
||||
// Slice all modifier volumes.
|
||||
if (this->region_volumes.size() > 1) {
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, true);
|
||||
m_print->throw_if_canceled();
|
||||
if (expolygons_by_layer.empty())
|
||||
continue;
|
||||
// loop through the other regions and 'steal' the slices belonging to this one
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " start";
|
||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||
if (region_id == other_region_id)
|
||||
continue;
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) {
|
||||
Layer *layer = m_layers[layer_id];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr)
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stInternal);
|
||||
}
|
||||
}
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||
if (region_id == other_region_id)
|
||||
continue;
|
||||
Layer *layer = m_layers[layer_id];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr)
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stInternal);
|
||||
}
|
||||
}
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " end";
|
||||
}
|
||||
@ -1540,38 +1647,94 @@ end:
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this](const tbb::blocked_range<size_t>& range) {
|
||||
[this, upscaled, clipped](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer *layer = m_layers[layer_id];
|
||||
// Apply size compensation and perform clipping of multi-part objects.
|
||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||
float elephant_foot_compensation = 0.f;
|
||||
if (layer_id == 0)
|
||||
delta -= float(scale_(m_config.elefant_foot_compensation.value));
|
||||
bool scale = delta != 0.f;
|
||||
bool clip = m_config.clip_multipart_objects.value || delta > 0.f;
|
||||
elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value));
|
||||
if (layer->m_regions.size() == 1) {
|
||||
if (scale) {
|
||||
// Optimized version for a single region layer.
|
||||
if (layer_id == 0) {
|
||||
if (delta > elephant_foot_compensation) {
|
||||
delta -= elephant_foot_compensation;
|
||||
elephant_foot_compensation = 0.f;
|
||||
} else if (delta > 0)
|
||||
elephant_foot_compensation -= delta;
|
||||
}
|
||||
if (delta != 0.f || elephant_foot_compensation > 0.f) {
|
||||
// Single region, growing or shrinking.
|
||||
LayerRegion *layerm = layer->m_regions.front();
|
||||
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal);
|
||||
// Apply the XY compensation.
|
||||
ExPolygons expolygons = (delta == 0.f) ?
|
||||
to_expolygons(std::move(layerm->slices.surfaces)) :
|
||||
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
||||
// Apply the elephant foot compensation.
|
||||
if (elephant_foot_compensation > 0) {
|
||||
float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
|
||||
float external_perimeter_nozzle = float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
||||
size_t nsteps = size_t(steps);
|
||||
float step = elephant_foot_compensation / steps;
|
||||
for (size_t i = 0; i < nsteps; ++ i) {
|
||||
Polygons tmp = offset(expolygons, - step);
|
||||
append(tmp, diff(to_polygons(expolygons), offset(offset_ex(expolygons, -elephant_foot_spacing - step), elephant_foot_spacing + step)));
|
||||
expolygons = union_ex(tmp);
|
||||
}
|
||||
}
|
||||
layerm->slices.set(std::move(expolygons), stInternal);
|
||||
}
|
||||
} else if (scale || clip) {
|
||||
// Multiple regions, growing, shrinking or just clipping one region by the other.
|
||||
// When clipping the regions, priority is given to the first regions.
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||
if (scale)
|
||||
slices = offset_ex(slices, delta);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (clip && region_id + 1 < layer->m_regions.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stInternal);
|
||||
} else {
|
||||
bool upscale = ! upscaled && delta > 0.f;
|
||||
bool clip = ! clipped && m_config.clip_multipart_objects.value;
|
||||
if (upscale || clip) {
|
||||
// Multiple regions, growing or just clipping one region by the other.
|
||||
// When clipping the regions, priority is given to the first regions.
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||
if (upscale)
|
||||
slices = offset_ex(std::move(slices), delta);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (clip && (region_id + 1 < layer->m_regions.size()))
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stInternal);
|
||||
}
|
||||
}
|
||||
if (delta < 0.f) {
|
||||
// Apply the negative XY compensation.
|
||||
Polygons trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON));
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||
layer->m_regions[region_id]->trim_surfaces(trimming);
|
||||
}
|
||||
if (elephant_foot_compensation > 0.f) {
|
||||
// Apply the elephant foot compensation.
|
||||
std::vector<float> elephant_foot_spacing;
|
||||
elephant_foot_spacing.reserve(layer->m_regions.size());
|
||||
float external_perimeter_nozzle = 0.f;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
elephant_foot_spacing.emplace_back(float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing()));
|
||||
external_perimeter_nozzle += float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||
}
|
||||
external_perimeter_nozzle /= (float)layer->m_regions.size();
|
||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
||||
size_t nsteps = size_t(steps);
|
||||
float step = elephant_foot_compensation / steps;
|
||||
for (size_t i = 0; i < nsteps; ++ i) {
|
||||
Polygons trimming_polygons = offset(layer->merged(float(EPSILON)), - step - float(EPSILON));
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||
layer->m_regions[region_id]->elephant_foot_compensation_step(elephant_foot_spacing[region_id] + step, trimming_polygons);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge all regions' slices to get islands, chain them by a shortest path.
|
||||
@ -1643,13 +1806,35 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
||||
const Print *print = this->print();
|
||||
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
||||
mslicer.init(&mesh, callback);
|
||||
mslicer.slice(z, &layers, callback);
|
||||
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z, const ModelVolume &volume) const
|
||||
{
|
||||
std::vector<ExPolygons> layers;
|
||||
// Compose mesh.
|
||||
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||
TriangleMesh mesh(volume.mesh);
|
||||
mesh.transform(volume.get_matrix());
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo);
|
||||
// apply XY shift
|
||||
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
|
||||
// perform actual slicing
|
||||
TriangleMeshSlicer mslicer;
|
||||
const Print *print = this->print();
|
||||
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
||||
mslicer.init(&mesh, callback);
|
||||
mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback);
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
std::string PrintObject::_fix_slicing_errors()
|
||||
{
|
||||
// Collect layers with slicing errors.
|
||||
@ -2245,7 +2430,7 @@ void PrintObject::combine_infill()
|
||||
|
||||
void PrintObject::_generate_support_material()
|
||||
{
|
||||
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
|
||||
PrintObjectSupportMaterial support_material(this, m_slicing_params);
|
||||
support_material.generate(*this);
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,8 @@ static std::vector<SLAAutoSupports::MyLayer> make_layers(
|
||||
const float layer_height = (layer_id!=0 ? heights[layer_id]-heights[layer_id-1] : heights[0]);
|
||||
const float safe_angle = 5.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle)));
|
||||
const float slope_angle = 75.f * (float(M_PI)/180.f); // smaller number - less supports
|
||||
const float slope_offset = float(scale_(layer_height / std::tan(slope_angle)));
|
||||
//FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands.
|
||||
for (SLAAutoSupports::Structure &top : layer_above.islands) {
|
||||
for (SLAAutoSupports::Structure &bottom : layer_below.islands) {
|
||||
@ -173,6 +175,7 @@ static std::vector<SLAAutoSupports::MyLayer> make_layers(
|
||||
overhangs_sorted.emplace_back(std::move(*p.first));
|
||||
top.overhangs = std::move(overhangs_sorted);
|
||||
top.overhangs_area *= float(SCALING_FACTOR * SCALING_FACTOR);
|
||||
top.overhangs_slopes = diff_ex(top_polygons, offset(bottom_polygons, slope_offset));
|
||||
top.dangling_areas = diff_ex(top_polygons, offset(bottom_polygons, between_layers_offset));
|
||||
}
|
||||
}
|
||||
@ -241,9 +244,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
||||
// What we now have in polygons needs support, regardless of what the forces are, so we can add them.
|
||||
//FIXME is it an island point or not? Vojtech thinks it is.
|
||||
uniformly_cover(s.dangling_areas, s, point_grid);
|
||||
} else if (! s.overhangs.empty()) {
|
||||
} else if (! s.overhangs_slopes.empty()) {
|
||||
//FIXME add the support force deficit as a parameter, only cover until the defficiency is covered.
|
||||
uniformly_cover(s.overhangs, s, point_grid);
|
||||
uniformly_cover(s.overhangs_slopes, s, point_grid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,12 @@ public:
|
||||
std::vector<Link> islands_above;
|
||||
std::vector<Link> islands_below;
|
||||
#endif
|
||||
// Overhangs, that are dangling considerably.
|
||||
ExPolygons dangling_areas;
|
||||
// Complete overhands.
|
||||
ExPolygons overhangs;
|
||||
// Overhangs, where the surface must slope.
|
||||
ExPolygons overhangs_slopes;
|
||||
float overhangs_area;
|
||||
|
||||
bool overlaps(const Structure &rhs) const {
|
||||
|
@ -561,7 +561,7 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
|
||||
heights.emplace_back(hi);
|
||||
|
||||
std::vector<ExPolygons> out; out.reserve(size_t(std::ceil(h/layerh)));
|
||||
slicer.slice(heights, &out, thrfn);
|
||||
slicer.slice(heights, 0.f, &out, thrfn);
|
||||
|
||||
size_t count = 0; for(auto& o : out) count += o.size();
|
||||
|
||||
|
@ -16,6 +16,14 @@ class TriangleMesh;
|
||||
|
||||
namespace sla {
|
||||
|
||||
// An enum to keep track of where the current points on the ModelObject came from.
|
||||
enum class PointsStatus {
|
||||
None, // No points were generated so far.
|
||||
Generating, // The autogeneration algorithm triggered, but not yet finished.
|
||||
AutoGenerated, // Points were autogenerated (i.e. copied from the backend).
|
||||
UserModified // User has done some edits.
|
||||
};
|
||||
|
||||
struct SupportPoint {
|
||||
Vec3f pos;
|
||||
float head_front_radius;
|
||||
|
@ -2129,7 +2129,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
|
||||
fullmesh.merge(get_pad());
|
||||
TriangleMeshSlicer slicer(&fullmesh);
|
||||
SlicedSupports ret;
|
||||
slicer.slice(heights, &ret, get().ctl().cancelfn);
|
||||
slicer.slice(heights, 0.f, &ret, get().ctl().cancelfn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -337,11 +337,34 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
||||
}
|
||||
}
|
||||
}
|
||||
if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
||||
/*if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
}
|
||||
if (model_object.sla_points_status != model_object_new.sla_points_status) {
|
||||
// Change of this status should invalidate support points. The points themselves are not enough, there are none
|
||||
// in case that nothing was generated OR that points were autogenerated already and not copied to the front-end.
|
||||
// These cases can only be differentiated by checking the status change. However, changing from 'Generating' should NOT
|
||||
// invalidate - that would keep stopping the background processing without a reason.
|
||||
if (model_object.sla_points_status != sla::PointsStatus::Generating)
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
}*/
|
||||
|
||||
bool old_user_modified = model_object.sla_points_status == sla::PointsStatus::UserModified;
|
||||
bool new_user_modified = model_object_new.sla_points_status == sla::PointsStatus::UserModified;
|
||||
if ((old_user_modified && ! new_user_modified) || // switching to automatic supports from manual supports
|
||||
(! old_user_modified && new_user_modified) || // switching to manual supports from automatic supports
|
||||
(new_user_modified && model_object.sla_support_points != model_object_new.sla_support_points)) {
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
}
|
||||
|
||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||
model_object.name = model_object_new.name;
|
||||
model_object.input_file = model_object_new.input_file;
|
||||
@ -613,7 +636,7 @@ void SLAPrint::process()
|
||||
ilh, float(lh));
|
||||
|
||||
auto& layers = po.m_model_slices; layers.clear();
|
||||
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
||||
slicer.slice(heights, float(po.config().slice_closing_radius.value), &layers, [this](){ throw_if_canceled(); });
|
||||
};
|
||||
|
||||
// In this step we check the slices, identify island and cover them with
|
||||
@ -629,10 +652,11 @@ void SLAPrint::process()
|
||||
BOOST_LOG_TRIVIAL(debug) << "Support point count "
|
||||
<< mo.sla_support_points.size();
|
||||
|
||||
// If there are no points on the front-end, we will do the
|
||||
// autoplacement. Otherwise we will just blindly copy the frontend data
|
||||
// Unless the user modified the points or we already did the calculation, we will do
|
||||
// the autoplacement. Otherwise we will just blindly copy the frontend data
|
||||
// into the backend cache.
|
||||
if(mo.sla_support_points.empty()) {
|
||||
if (mo.sla_points_status != sla::PointsStatus::UserModified) {
|
||||
|
||||
// calculate heights of slices (slices are calculated already)
|
||||
double lh = po.m_config.layer_height.getFloat();
|
||||
|
||||
@ -644,7 +668,9 @@ void SLAPrint::process()
|
||||
this->throw_if_canceled();
|
||||
SLAAutoSupports::Config config;
|
||||
const SLAPrintObjectConfig& cfg = po.config();
|
||||
config.density_relative = float(cfg.support_points_density_relative / 100.f); // the config value is in percents
|
||||
|
||||
// the density config value is in percents:
|
||||
config.density_relative = float(cfg.support_points_density_relative / 100.f);
|
||||
config.minimal_distance = float(cfg.support_points_minimal_distance);
|
||||
|
||||
// Construction of this object does the calculation.
|
||||
@ -668,7 +694,7 @@ void SLAPrint::process()
|
||||
report_status(*this, -1, L("Generating support points"), SlicingStatus::RELOAD_SLA_SUPPORT_POINTS);
|
||||
}
|
||||
else {
|
||||
// There are some points on the front-end, no calculation will be done.
|
||||
// There are either some points on the front-end, or the user removed them on purpose. No calculation will be done.
|
||||
po.m_supportdata->support_points = po.transformed_support_points();
|
||||
}
|
||||
};
|
||||
@ -1341,7 +1367,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
bool invalidated = false;
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if ( opt_key == "layer_height"
|
||||
|| opt_key == "faded_layers") {
|
||||
|| opt_key == "faded_layers"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
opt_key == "supports_enable"
|
||||
|
@ -149,6 +149,7 @@ SlicingParameters SlicingParameters::create_from_config(
|
||||
params.object_print_z_max += print_z;
|
||||
}
|
||||
|
||||
params.valid = true;
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ struct SlicingParameters
|
||||
// Height of the object to be printed. This value does not contain the raft height.
|
||||
coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; }
|
||||
|
||||
bool valid;
|
||||
|
||||
// Number of raft layers.
|
||||
size_t base_raft_layers;
|
||||
// Number of interface layers including the contact layer.
|
||||
@ -100,6 +102,8 @@ static_assert(IsTriviallyCopyable<SlicingParameters>::value, "SlicingParameters
|
||||
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
||||
inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters &sp2)
|
||||
{
|
||||
assert(sp1.valid);
|
||||
assert(sp2.valid);
|
||||
return sp1.base_raft_layers == sp2.base_raft_layers &&
|
||||
sp1.interface_raft_layers == sp2.interface_raft_layers &&
|
||||
sp1.base_raft_layer_height == sp2.base_raft_layer_height &&
|
||||
|
@ -42,15 +42,6 @@
|
||||
#define ENABLE_VOLUMES_CENTERING_FIXES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha5 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA5 1
|
||||
|
||||
// Toolbar items hidden/shown in dependence of the user mode
|
||||
#define ENABLE_MODE_AWARE_TOOLBAR_ITEMS (1 && ENABLE_1_42_0_ALPHA5)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha7 techs
|
||||
//====================
|
||||
@ -59,4 +50,13 @@
|
||||
// Printbed textures generated from svg files
|
||||
#define ENABLE_TEXTURES_FROM_SVG (1 && ENABLE_1_42_0_ALPHA7)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha8 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA8 1
|
||||
|
||||
// Toolbars and Gizmos use icons imported from svg files
|
||||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
||||
|
||||
#endif // _technologies_h_
|
||||
|
@ -852,7 +852,7 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
|
||||
}
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const
|
||||
void TriangleMeshSlicer::slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const
|
||||
{
|
||||
std::vector<Polygons> layers_p;
|
||||
this->slice(z, &layers_p, throw_on_cancel);
|
||||
@ -861,13 +861,13 @@ void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygo
|
||||
layers->resize(z.size());
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, z.size()),
|
||||
[&layers_p, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) {
|
||||
[&layers_p, closing_radius, layers, throw_on_cancel, this](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
||||
printf("Layer " PRINTF_ZU " (slice_z = %.2f):\n", layer_id, z[layer_id]);
|
||||
#endif
|
||||
throw_on_cancel();
|
||||
this->make_expolygons(layers_p[layer_id], &(*layers)[layer_id]);
|
||||
this->make_expolygons(layers_p[layer_id], closing_radius, &(*layers)[layer_id]);
|
||||
}
|
||||
});
|
||||
BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::make_expolygons in parallel - end";
|
||||
@ -1600,7 +1600,7 @@ void TriangleMeshSlicer::make_expolygons_simple(std::vector<IntersectionLine> &l
|
||||
#endif
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) const
|
||||
void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const
|
||||
{
|
||||
/*
|
||||
Input loops are not suitable for evenodd nor nonzero fill types, as we might get
|
||||
@ -1655,7 +1655,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
||||
// 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959
|
||||
// double safety_offset = scale_(0.0499);
|
||||
// 0.0001 is set to satisfy GH #520, #1029, #1364
|
||||
double safety_offset = scale_(0.0001);
|
||||
double safety_offset = scale_(closing_radius);
|
||||
|
||||
/* The following line is commented out because it can generate wrong polygons,
|
||||
see for example issue #661 */
|
||||
@ -1670,17 +1670,17 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
||||
#endif
|
||||
|
||||
// append to the supplied collection
|
||||
/* Fix for issue #661 { */
|
||||
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
|
||||
//expolygons_append(*slices, ex_slices);
|
||||
/* } */
|
||||
if (safety_offset > 0)
|
||||
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
|
||||
else
|
||||
expolygons_append(*slices, union_ex(loops, false));
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const
|
||||
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const
|
||||
{
|
||||
Polygons pp;
|
||||
this->make_loops(lines, &pp);
|
||||
this->make_expolygons(pp, slices);
|
||||
this->make_expolygons(pp, closing_radius, slices);
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) const
|
||||
|
@ -165,7 +165,7 @@ public:
|
||||
TriangleMeshSlicer(TriangleMesh* mesh) { this->init(mesh, [](){}); }
|
||||
void init(TriangleMesh *mesh, throw_on_cancel_callback_type throw_on_cancel);
|
||||
void slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
||||
void slice(const std::vector<float> &z, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
||||
void slice(const std::vector<float> &z, const float closing_radius, std::vector<ExPolygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const;
|
||||
enum FacetSliceType {
|
||||
NoSlice = 0,
|
||||
Slicing = 1,
|
||||
@ -184,9 +184,9 @@ private:
|
||||
|
||||
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
||||
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;
|
||||
void make_expolygons(const Polygons &loops, ExPolygons* slices) const;
|
||||
void make_expolygons(const Polygons &loops, const float closing_radius, ExPolygons* slices) const;
|
||||
void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
||||
void make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
||||
void make_expolygons(std::vector<IntersectionLine> &lines, const float closing_radius, ExPolygons* slices) const;
|
||||
};
|
||||
|
||||
TriangleMesh make_cube(double x, double y, double z);
|
||||
|
@ -516,9 +516,9 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
|
||||
|
||||
if (max_anisotropy > 0.0f)
|
||||
{
|
||||
::glBindTexture(GL_TEXTURE_2D, m_texture.get_id());
|
||||
::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_texture.get_id()));
|
||||
glsafe(::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,9 +542,9 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
|
||||
|
||||
if (!m_model.get_filename().empty())
|
||||
{
|
||||
::glEnable(GL_LIGHTING);
|
||||
glsafe(::glEnable(GL_LIGHTING));
|
||||
m_model.render();
|
||||
::glDisable(GL_LIGHTING);
|
||||
glsafe(::glDisable(GL_LIGHTING));
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,39 +553,32 @@ void Bed3D::render_prusa(const std::string &key, bool bottom) const
|
||||
{
|
||||
if (m_vbo_id == 0)
|
||||
{
|
||||
::glGenBuffers(1, &m_vbo_id);
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
|
||||
::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)m_triangles.get_vertices_data_size(), (const GLvoid*)m_triangles.get_vertices_data(), GL_STATIC_DRAW);
|
||||
::glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_position_offset());
|
||||
::glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_tex_coords_offset());
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glsafe(::glGenBuffers(1, &m_vbo_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)m_triangles.get_vertices_data_size(), (const GLvoid*)m_triangles.get_vertices_data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
::glEnable(GL_DEPTH_TEST);
|
||||
::glDepthMask(GL_FALSE);
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
|
||||
::glEnable(GL_BLEND);
|
||||
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
::glEnable(GL_TEXTURE_2D);
|
||||
::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if (bottom)
|
||||
::glFrontFace(GL_CW);
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
render_prusa_shader(triangles_vcount, bottom);
|
||||
render_prusa_shader(bottom);
|
||||
|
||||
if (bottom)
|
||||
::glFrontFace(GL_CCW);
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
|
||||
::glDisable(GL_TEXTURE_2D);
|
||||
|
||||
::glDisable(GL_BLEND);
|
||||
::glDepthMask(GL_TRUE);
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
}
|
||||
}
|
||||
|
||||
void Bed3D::render_prusa_shader(unsigned int vertices_count, bool transparent) const
|
||||
void Bed3D::render_prusa_shader(bool transparent) const
|
||||
{
|
||||
if (m_shader.get_shader_program_id() == 0)
|
||||
m_shader.init("printbed.vs", "printbed.fs");
|
||||
@ -595,15 +588,35 @@ void Bed3D::render_prusa_shader(unsigned int vertices_count, bool transparent) c
|
||||
m_shader.start_using();
|
||||
m_shader.set_uniform("transparent_background", transparent);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_texture.get_id());
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
|
||||
::glEnableVertexAttribArray(0);
|
||||
::glEnableVertexAttribArray(1);
|
||||
::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices_count);
|
||||
::glDisableVertexAttribArray(1);
|
||||
::glDisableVertexAttribArray(0);
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
unsigned int stride = m_triangles.get_vertex_data_size();
|
||||
|
||||
GLint position_id = m_shader.get_attrib_location("v_position");
|
||||
GLint tex_coords_id = m_shader.get_attrib_location("v_tex_coords");
|
||||
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)m_texture.get_id()));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
||||
|
||||
if (position_id != -1)
|
||||
{
|
||||
glsafe(::glEnableVertexAttribArray(position_id));
|
||||
glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)m_triangles.get_position_offset()));
|
||||
}
|
||||
if (tex_coords_id != -1)
|
||||
{
|
||||
glsafe(::glEnableVertexAttribArray(tex_coords_id));
|
||||
glsafe(::glVertexAttribPointer(tex_coords_id, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)m_triangles.get_tex_coords_offset()));
|
||||
}
|
||||
|
||||
glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)m_triangles.get_vertices_count()));
|
||||
|
||||
if (tex_coords_id != -1)
|
||||
glsafe(::glDisableVertexAttribArray(tex_coords_id));
|
||||
|
||||
if (position_id != -1)
|
||||
glsafe(::glDisableVertexAttribArray(position_id));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
m_shader.stop_using();
|
||||
}
|
||||
@ -754,7 +767,7 @@ void Bed3D::render_custom() const
|
||||
glsafe(::glColor4f(0.35f, 0.35f, 0.35f, 0.4f));
|
||||
glsafe(::glNormal3d(0.0f, 0.0f, 1.0f));
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data());
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_triangles.get_vertices_data()));
|
||||
#else
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)m_triangles.get_vertices()));
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
@ -768,7 +781,7 @@ void Bed3D::render_custom() const
|
||||
glsafe(::glLineWidth(3.0f * m_scale_factor));
|
||||
glsafe(::glColor4f(0.2f, 0.2f, 0.2f, 0.4f));
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data());
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data()));
|
||||
#else
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 0, (GLvoid*)m_gridlines.get_vertices()));
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
@ -786,7 +799,7 @@ void Bed3D::reset()
|
||||
{
|
||||
if (m_vbo_id > 0)
|
||||
{
|
||||
::glDeleteBuffers(1, &m_vbo_id);
|
||||
glsafe(::glDeleteBuffers(1, &m_vbo_id));
|
||||
m_vbo_id = 0;
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ private:
|
||||
EType detect_type(const Pointfs& shape) const;
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
void render_prusa(const std::string& key, bool bottom) const;
|
||||
void render_prusa_shader(unsigned int vertices_count, bool transparent) const;
|
||||
void render_prusa_shader(bool transparent) const;
|
||||
#else
|
||||
void render_prusa(const std::string &key, float theta, bool useVBOs) const;
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
@ -92,8 +92,8 @@ AboutDialog::AboutDialog()
|
||||
"<html>"
|
||||
"<body bgcolor= %s link= %s>"
|
||||
"<font color=%s>"
|
||||
"Copyright © 2016-2018 Prusa Research. <br />"
|
||||
"Copyright © 2011-2017 Alessandro Ranellucci. <br />"
|
||||
"Copyright © 2016-2019 Prusa Research. <br />"
|
||||
"Copyright © 2011-2018 Alessandro Ranellucci. <br />"
|
||||
"<a href=\"http://slic3r.org/\">Slic3r</a> is licensed under the "
|
||||
"<a href=\"http://www.gnu.org/licenses/agpl-3.0.html\">GNU Affero General Public License, version 3</a>."
|
||||
"<br /><br />"
|
||||
|
@ -1004,7 +1004,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason)
|
||||
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
|
||||
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
|
||||
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
|
||||
p->btn_cancel = new wxButton(this, wxID_CANCEL);
|
||||
p->btn_cancel = new wxButton(this, wxID_CANCEL, _(L("Cancel"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||
p->btnsizer->AddStretchSpacer();
|
||||
p->btnsizer->Add(p->btn_prev, 0, wxLEFT, BTN_SPACING);
|
||||
p->btnsizer->Add(p->btn_next, 0, wxLEFT, BTN_SPACING);
|
||||
|
@ -464,8 +464,14 @@ void SpinCtrl::BUILD() {
|
||||
// # As a workaround, we get the new value from $event->GetString and store
|
||||
// # here temporarily so that we can return it from $self->get_value
|
||||
std::string value = e.GetString().utf8_str().data();
|
||||
if (is_matched(value, "^\\-?\\d+$"))
|
||||
tmp_value = std::stoi(value);
|
||||
if (is_matched(value, "^\\-?\\d+$")) {
|
||||
try {
|
||||
tmp_value = std::stoi(value);
|
||||
}
|
||||
catch (const std::exception & /* e */) {
|
||||
tmp_value = -9999;
|
||||
}
|
||||
}
|
||||
else tmp_value = -9999;
|
||||
#ifdef __WXOSX__
|
||||
propagate_value();
|
||||
|
@ -122,7 +122,6 @@ struct FirmwareDialog::priv
|
||||
// This is a shared pointer holding the background AvrDude task
|
||||
// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
|
||||
AvrDude::Ptr avrdude;
|
||||
std::string avrdude_config;
|
||||
unsigned progress_tasks_done;
|
||||
unsigned progress_tasks_bar;
|
||||
bool user_cancelled;
|
||||
@ -134,7 +133,6 @@ struct FirmwareDialog::priv
|
||||
btn_flash_label_flashing(_(L("Cancel"))),
|
||||
label_status_flashing(_(L("Flashing in progress. Please do not disconnect the printer!"))),
|
||||
timer_pulse(q),
|
||||
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
|
||||
progress_tasks_done(0),
|
||||
progress_tasks_bar(0),
|
||||
user_cancelled(false),
|
||||
@ -553,7 +551,7 @@ void FirmwareDialog::priv::perform_upload()
|
||||
flashing_start(hex_file.device == HexFile::DEV_MK3 ? 2 : 1);
|
||||
|
||||
// Init the avrdude object
|
||||
AvrDude avrdude(avrdude_config);
|
||||
AvrDude avrdude;
|
||||
|
||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||
@ -722,7 +720,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
||||
panel->SetSizer(vsizer);
|
||||
|
||||
auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
|
||||
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
|
||||
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString, wxFileSelectorPromptStr,
|
||||
"Hex files (*.hex)|*.hex|All files|*.*");
|
||||
|
||||
auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
|
||||
@ -770,7 +768,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
||||
// Experience says it needs to be 1, otherwise things won't get sized properly.
|
||||
vsizer->Add(p->spoiler, 1, wxEXPAND | wxBOTTOM, SPACING);
|
||||
|
||||
p->btn_close = new wxButton(panel, wxID_CLOSE);
|
||||
p->btn_close = new wxButton(panel, wxID_CLOSE, _(L("Close"))); // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||
p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
|
||||
p->btn_flash->Disable();
|
||||
auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
@ -375,6 +375,59 @@ class GLCanvas3D
|
||||
};
|
||||
|
||||
public:
|
||||
class TransformationType
|
||||
{
|
||||
public:
|
||||
enum Enum {
|
||||
// Transforming in a world coordinate system
|
||||
World = 0,
|
||||
// Transforming in a local coordinate system
|
||||
Local = 1,
|
||||
// Absolute transformations, allowed in local coordinate system only.
|
||||
Absolute = 0,
|
||||
// Relative transformations, allowed in both local and world coordinate system.
|
||||
Relative = 2,
|
||||
// For group selection, the transformation is performed as if the group made a single solid body.
|
||||
Joint = 0,
|
||||
// For group selection, the transformation is performed on each object independently.
|
||||
Independent = 4,
|
||||
|
||||
World_Relative_Joint = World | Relative | Joint,
|
||||
World_Relative_Independent = World | Relative | Independent,
|
||||
Local_Absolute_Joint = Local | Absolute | Joint,
|
||||
Local_Absolute_Independent = Local | Absolute | Independent,
|
||||
Local_Relative_Joint = Local | Relative | Joint,
|
||||
Local_Relative_Independent = Local | Relative | Independent,
|
||||
};
|
||||
|
||||
TransformationType() : m_value(World) {}
|
||||
TransformationType(Enum value) : m_value(value) {}
|
||||
TransformationType& operator=(Enum value) { m_value = value; return *this; }
|
||||
|
||||
Enum operator()() const { return m_value; }
|
||||
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
|
||||
|
||||
void set_world() { this->remove(Local); }
|
||||
void set_local() { this->add(Local); }
|
||||
void set_absolute() { this->remove(Relative); }
|
||||
void set_relative() { this->add(Relative); }
|
||||
void set_joint() { this->remove(Independent); }
|
||||
void set_independent() { this->add(Independent); }
|
||||
|
||||
bool world() const { return ! this->has(Local); }
|
||||
bool local() const { return this->has(Local); }
|
||||
bool absolute() const { return ! this->has(Relative); }
|
||||
bool relative() const { return this->has(Relative); }
|
||||
bool joint() const { return ! this->has(Independent); }
|
||||
bool independent() const { return this->has(Independent); }
|
||||
|
||||
private:
|
||||
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
|
||||
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
|
||||
|
||||
Enum m_value;
|
||||
};
|
||||
|
||||
class Selection
|
||||
{
|
||||
public:
|
||||
@ -415,6 +468,7 @@ public:
|
||||
Transform3d rotation_matrix;
|
||||
Transform3d scale_matrix;
|
||||
Transform3d mirror_matrix;
|
||||
Transform3d full_matrix;
|
||||
|
||||
TransformCache();
|
||||
explicit TransformCache(const Geometry::Transformation& transform);
|
||||
@ -434,6 +488,7 @@ public:
|
||||
const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
|
||||
const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
|
||||
const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
|
||||
const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
|
||||
|
||||
const Vec3d& get_instance_position() const { return m_instance.position; }
|
||||
const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
|
||||
@ -442,6 +497,7 @@ public:
|
||||
const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
|
||||
const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
|
||||
const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
|
||||
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
|
||||
};
|
||||
|
||||
typedef std::map<unsigned int, VolumeCache> VolumesCache;
|
||||
@ -553,7 +609,7 @@ public:
|
||||
void start_dragging();
|
||||
|
||||
void translate(const Vec3d& displacement, bool local = false);
|
||||
void rotate(const Vec3d& rotation, bool local);
|
||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||
void flattening_rotate(const Vec3d& normal);
|
||||
void scale(const Vec3d& scale, bool local);
|
||||
void mirror(Axis axis);
|
||||
@ -635,6 +691,10 @@ private:
|
||||
class Gizmos
|
||||
{
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
static const float Default_Icons_Size;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
enum EType : unsigned char
|
||||
{
|
||||
Undefined,
|
||||
@ -651,10 +711,21 @@ private:
|
||||
bool m_enabled;
|
||||
typedef std::map<EType, GLGizmoBase*> GizmosMap;
|
||||
GizmosMap m_gizmos;
|
||||
#if ENABLE_SVG_ICONS
|
||||
mutable GLTexture m_icons_texture;
|
||||
mutable bool m_icons_texture_dirty;
|
||||
#else
|
||||
ItemsIconsTexture m_icons_texture;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
BackgroundTexture m_background_texture;
|
||||
EType m_current;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float m_overlay_icons_size;
|
||||
float m_overlay_scale;
|
||||
#else
|
||||
float m_overlay_icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float m_overlay_border;
|
||||
float m_overlay_gap_y;
|
||||
|
||||
@ -667,6 +738,9 @@ private:
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool enable);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
void set_overlay_icon_size(float size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
void set_overlay_scale(float scale);
|
||||
|
||||
std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
|
||||
@ -716,15 +790,19 @@ private:
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
private:
|
||||
void _reset();
|
||||
void reset();
|
||||
|
||||
void _render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
|
||||
void _render_current_gizmo(const Selection& selection) const;
|
||||
void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
|
||||
void do_render_current_gizmo(const Selection& selection) const;
|
||||
|
||||
float _get_total_overlay_height() const;
|
||||
float _get_total_overlay_width() const;
|
||||
float get_total_overlay_height() const;
|
||||
float get_total_overlay_width() const;
|
||||
|
||||
GLGizmoBase* _get_current() const;
|
||||
GLGizmoBase* get_current() const;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool generate_icons_texture() const;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
};
|
||||
|
||||
struct SlaCap
|
||||
@ -793,7 +871,7 @@ private:
|
||||
void fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas,
|
||||
std::vector<std::pair<double, double>>& cp_legend_values);
|
||||
|
||||
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas, bool use_error_colors);
|
||||
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas);
|
||||
|
||||
void render(const GLCanvas3D& canvas) const;
|
||||
};
|
||||
@ -931,9 +1009,7 @@ public:
|
||||
|
||||
void update_volumes_colors_by_extruder();
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
void update_toolbar_items_visibility();
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
#if !ENABLE_IMGUI
|
||||
Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const;
|
||||
@ -1095,7 +1171,9 @@ private:
|
||||
|
||||
bool _is_any_volume_outside() const;
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
void _resize_toolbars() const;
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectSettings.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
|
||||
@ -157,11 +159,19 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
#else
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
: m_parent(parent)
|
||||
, m_group_id(-1)
|
||||
, m_state(Off)
|
||||
, m_shortcut_key(0)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_icon_filename(icon_filename)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_sprite_id(sprite_id)
|
||||
, m_hover_id(-1)
|
||||
, m_dragging(false)
|
||||
#if ENABLE_IMGUI
|
||||
@ -304,7 +314,11 @@ const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
|
||||
const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius
|
||||
|
||||
GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
: GLGizmoBase(parent, "", -1)
|
||||
#else
|
||||
: GLGizmoBase(parent, -1)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_axis(axis)
|
||||
, m_angle(0.0)
|
||||
, m_quadric(nullptr)
|
||||
@ -321,7 +335,11 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
|
||||
}
|
||||
|
||||
GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other)
|
||||
: GLGizmoBase(other.m_parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
: GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id)
|
||||
#else
|
||||
: GLGizmoBase(other.m_parent, other.m_sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_axis(other.m_axis)
|
||||
, m_angle(other.m_angle)
|
||||
, m_quadric(nullptr)
|
||||
@ -628,7 +646,7 @@ void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) c
|
||||
{
|
||||
::glTranslated(m_center(0), m_center(1), m_center(2));
|
||||
|
||||
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||
{
|
||||
Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
::glMultMatrixd(orient_matrix.data());
|
||||
@ -685,7 +703,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
||||
}
|
||||
}
|
||||
|
||||
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||
m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse();
|
||||
|
||||
m.translate(-m_center);
|
||||
@ -693,8 +711,13 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
||||
return transform(mouse_ray, m).intersect_plane(0.0);
|
||||
}
|
||||
|
||||
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
{
|
||||
m_gizmos.emplace_back(parent, GLGizmoRotate::X);
|
||||
m_gizmos.emplace_back(parent, GLGizmoRotate::Y);
|
||||
@ -719,17 +742,6 @@ bool GLGizmoRotate3D::on_init()
|
||||
m_gizmos[i].set_highlight_color(AXES_COLOR[i]);
|
||||
}
|
||||
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "rotate_off.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "rotate_hover.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "rotate_on.png", false))
|
||||
return false;
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_R;
|
||||
|
||||
return true;
|
||||
@ -767,7 +779,7 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
}
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
|
||||
Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));
|
||||
@ -784,8 +796,13 @@ void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D:
|
||||
|
||||
const float GLGizmoScale3D::Offset = 5.0f;
|
||||
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_scale(Vec3d::Ones())
|
||||
, m_snap_step(0.05)
|
||||
, m_starting_scale(Vec3d::Ones())
|
||||
@ -794,17 +811,6 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent)
|
||||
|
||||
bool GLGizmoScale3D::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "scale_off.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "scale_hover.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "scale_on.png", false))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
m_grabbers.push_back(Grabber());
|
||||
@ -975,7 +981,7 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
|
||||
::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f);
|
||||
|
||||
float grabber_max_size = (float)std::max(grabber_size(0), std::max(grabber_size(1), grabber_size(2)));
|
||||
float grabber_mean_size = (float)(grabber_size(0) + grabber_size(1) + grabber_size(2)) / 3.0f;
|
||||
|
||||
if (m_hover_id == -1)
|
||||
{
|
||||
@ -1001,7 +1007,7 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
render_grabbers_connection(8, 9);
|
||||
render_grabbers_connection(9, 6);
|
||||
// draw grabbers
|
||||
render_grabbers(grabber_max_size);
|
||||
render_grabbers(grabber_mean_size);
|
||||
}
|
||||
else if ((m_hover_id == 0) || (m_hover_id == 1))
|
||||
{
|
||||
@ -1009,8 +1015,8 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
::glColor3fv(m_grabbers[0].color);
|
||||
render_grabbers_connection(0, 1);
|
||||
// draw grabbers
|
||||
m_grabbers[0].render(true, grabber_max_size);
|
||||
m_grabbers[1].render(true, grabber_max_size);
|
||||
m_grabbers[0].render(true, grabber_mean_size);
|
||||
m_grabbers[1].render(true, grabber_mean_size);
|
||||
}
|
||||
else if ((m_hover_id == 2) || (m_hover_id == 3))
|
||||
{
|
||||
@ -1018,8 +1024,8 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
::glColor3fv(m_grabbers[2].color);
|
||||
render_grabbers_connection(2, 3);
|
||||
// draw grabbers
|
||||
m_grabbers[2].render(true, grabber_max_size);
|
||||
m_grabbers[3].render(true, grabber_max_size);
|
||||
m_grabbers[2].render(true, grabber_mean_size);
|
||||
m_grabbers[3].render(true, grabber_mean_size);
|
||||
}
|
||||
else if ((m_hover_id == 4) || (m_hover_id == 5))
|
||||
{
|
||||
@ -1027,8 +1033,8 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
::glColor3fv(m_grabbers[4].color);
|
||||
render_grabbers_connection(4, 5);
|
||||
// draw grabbers
|
||||
m_grabbers[4].render(true, grabber_max_size);
|
||||
m_grabbers[5].render(true, grabber_max_size);
|
||||
m_grabbers[4].render(true, grabber_mean_size);
|
||||
m_grabbers[5].render(true, grabber_mean_size);
|
||||
}
|
||||
else if (m_hover_id >= 6)
|
||||
{
|
||||
@ -1041,7 +1047,7 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
|
||||
// draw grabbers
|
||||
for (int i = 6; i < 10; ++i)
|
||||
{
|
||||
m_grabbers[i].render(true, grabber_max_size);
|
||||
m_grabbers[i].render(true, grabber_mean_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1054,7 +1060,7 @@ void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selectio
|
||||
}
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoScale3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||
void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
|
||||
bool single_instance = selection.is_single_full_instance();
|
||||
@ -1141,8 +1147,13 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||
|
||||
const double GLGizmoMove3D::Offset = 10.0;
|
||||
|
||||
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_displacement(Vec3d::Zero())
|
||||
, m_snap_step(1.0)
|
||||
, m_starting_drag_position(Vec3d::Zero())
|
||||
@ -1163,17 +1174,6 @@ GLGizmoMove3D::~GLGizmoMove3D()
|
||||
|
||||
bool GLGizmoMove3D::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "move_off.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "move_hover.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "move_on.png", false))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
m_grabbers.push_back(Grabber());
|
||||
@ -1305,7 +1305,7 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection
|
||||
}
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoMove3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||
void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
|
||||
bool show_position = selection.is_single_full_instance();
|
||||
@ -1389,8 +1389,13 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
||||
::glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_normal(Vec3d::Zero())
|
||||
, m_starting_center(Vec3d::Zero())
|
||||
{
|
||||
@ -1398,19 +1403,7 @@ GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent)
|
||||
|
||||
bool GLGizmoFlatten::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "layflat_off.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "layflat_hover.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "layflat_on.png", false))
|
||||
return false;
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_F;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1740,8 +1733,14 @@ Vec3d GLGizmoFlatten::get_flattening_normal() const
|
||||
return out;
|
||||
}
|
||||
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent), m_starting_center(Vec3d::Zero()), m_quadric(nullptr)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_starting_center(Vec3d::Zero()), m_quadric(nullptr)
|
||||
{
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
@ -1758,19 +1757,7 @@ GLGizmoSlaSupports::~GLGizmoSlaSupports()
|
||||
|
||||
bool GLGizmoSlaSupports::on_init()
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "sla_support_points_off.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "sla_support_points_hover.png", false))
|
||||
return false;
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "sla_support_points_on.png", false))
|
||||
return false;
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_L;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1789,12 +1776,12 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
|
||||
if (is_mesh_update_necessary())
|
||||
update_mesh();
|
||||
|
||||
// If there are no points, let's ask the backend if it calculated some.
|
||||
if (m_editing_mode_cache.empty())
|
||||
get_data_from_backend();
|
||||
|
||||
if (m_model_object != m_old_model_object)
|
||||
m_editing_mode = false;
|
||||
|
||||
if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified)
|
||||
get_data_from_backend();
|
||||
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
||||
@ -1937,7 +1924,7 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b
|
||||
|
||||
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
|
||||
{
|
||||
return (m_state == On) && (m_model_object != nullptr) && (m_model_object != m_old_model_object) && !m_model_object->instances.empty();
|
||||
return (m_state == On) && (m_model_object != m_old_model_object) && (m_model_object != nullptr) && !m_model_object->instances.empty();
|
||||
|
||||
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
|
||||
// return false;
|
||||
@ -2176,13 +2163,10 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::delete_selected_points()
|
||||
void GLGizmoSlaSupports::delete_selected_points(bool force)
|
||||
{
|
||||
if (!m_editing_mode)
|
||||
return;
|
||||
|
||||
for (unsigned int idx=0; idx<m_editing_mode_cache.size(); ++idx) {
|
||||
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands)) {
|
||||
if (m_editing_mode_cache[idx].second && (!m_editing_mode_cache[idx].first.is_new_island || !m_lock_unique_islands || force)) {
|
||||
m_editing_mode_cache.erase(m_editing_mode_cache.begin() + (idx--));
|
||||
m_unsaved_changes = true;
|
||||
}
|
||||
@ -2243,20 +2227,59 @@ void GLGizmoSlaSupports::render_tooltip_texture() const {
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoSlaSupports::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||
std::vector<ConfigOption*> GLGizmoSlaSupports::get_config_options(const std::vector<std::string>& keys) const
|
||||
{
|
||||
std::vector<ConfigOption*> out;
|
||||
|
||||
if (!m_model_object)
|
||||
return out;
|
||||
|
||||
DynamicPrintConfig& object_cfg = m_model_object->config;
|
||||
DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
std::unique_ptr<DynamicPrintConfig> default_cfg = nullptr;
|
||||
|
||||
for (const std::string& key : keys) {
|
||||
if (object_cfg.has(key))
|
||||
out.push_back(object_cfg.option(key));
|
||||
else
|
||||
if (print_cfg.has(key))
|
||||
out.push_back(print_cfg.option(key));
|
||||
else { // we must get it from defaults
|
||||
if (default_cfg == nullptr)
|
||||
default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys));
|
||||
out.push_back(default_cfg->option(key));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
if (!m_model_object)
|
||||
return;
|
||||
|
||||
bool first_run = true; // This is a hack to redraw the button when all points are removed,
|
||||
// so it is not delayed until the background process finishes.
|
||||
RENDER_AGAIN:
|
||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
|
||||
const float scaling = m_imgui->get_style_scaling();
|
||||
const ImVec2 window_size(285.f * scaling, 260.f * scaling);
|
||||
ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) ));
|
||||
ImGui::SetNextWindowSize(ImVec2(window_size));
|
||||
|
||||
m_imgui->set_next_window_bg_alpha(0.5f);
|
||||
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove |/* ImGuiWindowFlags_NoResize | */ImGuiWindowFlags_NoCollapse);
|
||||
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
ImGui::PushItemWidth(100.0f);
|
||||
|
||||
bool force_refresh = false;
|
||||
bool remove_selected = false;
|
||||
bool remove_all = false;
|
||||
|
||||
if (m_editing_mode) {
|
||||
m_imgui->text(_(L("Left mouse click - add point")));
|
||||
@ -2264,16 +2287,20 @@ RENDER_AGAIN:
|
||||
m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)")));
|
||||
m_imgui->text(" "); // vertical gap
|
||||
|
||||
std::vector<wxString> options = {"0.2", "0.4", "0.6", "0.8", "1.0"};
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(1) << m_new_point_head_diameter;
|
||||
wxString str = ss.str();
|
||||
static const std::vector<float> options = {0.2f, 0.4f, 0.6f, 0.8f, 1.0f};
|
||||
static const std::vector<std::string> options_str = {"0.2", "0.4", "0.6", "0.8", "1.0"};
|
||||
int selection = -1;
|
||||
for (size_t i = 0; i < options.size(); i++) {
|
||||
if (options[i] == m_new_point_head_diameter) { selection = (int)i; }
|
||||
}
|
||||
|
||||
bool old_combo_state = m_combo_box_open;
|
||||
m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options, str);
|
||||
// The combo is commented out for now, until the feature is supported by backend.
|
||||
// m_combo_box_open = m_imgui->combo(_(L("Head diameter")), options_str, selection);
|
||||
force_refresh |= (old_combo_state != m_combo_box_open);
|
||||
|
||||
float current_number = atof(str);
|
||||
// float current_number = atof(str);
|
||||
const float current_number = selection < options.size() ? options[selection] : m_new_point_head_diameter;
|
||||
if (old_combo_state && !m_combo_box_open) // closing the combo must always change the sizes (even if the selection did not change)
|
||||
for (auto& point_and_selection : m_editing_mode_cache)
|
||||
if (point_and_selection.second) {
|
||||
@ -2294,10 +2321,13 @@ RENDER_AGAIN:
|
||||
remove_selected = m_imgui->button(_(L("Remove selected points")));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->disabled_begin(m_editing_mode_cache.empty());
|
||||
remove_all = m_imgui->button(_(L("Remove all points")));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->text(" "); // vertical gap
|
||||
|
||||
bool apply_changes = m_imgui->button(_(L("Apply changes")));
|
||||
if (apply_changes) {
|
||||
if (m_imgui->button(_(L("Apply changes")))) {
|
||||
editing_mode_apply_changes();
|
||||
force_refresh = true;
|
||||
}
|
||||
@ -2308,24 +2338,52 @@ RENDER_AGAIN:
|
||||
force_refresh = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* ImGui::PushItemWidth(50.0f);
|
||||
else { // not in editing mode:
|
||||
ImGui::PushItemWidth(100.0f);
|
||||
m_imgui->text(_(L("Minimal points distance: ")));
|
||||
ImGui::SameLine();
|
||||
bool value_changed = ImGui::InputDouble("mm", &m_minimal_point_distance, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
std::vector<ConfigOption*> opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"});
|
||||
float density = static_cast<ConfigOptionInt*>(opts[0])->value;
|
||||
float minimal_point_distance = static_cast<ConfigOptionFloat*>(opts[1])->value;
|
||||
|
||||
bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
|
||||
if (value_changed)
|
||||
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
|
||||
|
||||
m_imgui->text(_(L("Support points density: ")));
|
||||
ImGui::SameLine();
|
||||
value_changed |= ImGui::InputDouble("%", &m_density, 0.0f, 0.0f, "%.f");*/
|
||||
if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) {
|
||||
value_changed = true;
|
||||
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
|
||||
}
|
||||
|
||||
if (value_changed) { // Update side panel
|
||||
wxTheApp->CallAfter([]() {
|
||||
wxGetApp().obj_settings()->UpdateAndShow(true);
|
||||
wxGetApp().obj_list()->update_settings_items();
|
||||
});
|
||||
}
|
||||
|
||||
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
|
||||
|
||||
if (generate)
|
||||
auto_generate();
|
||||
|
||||
m_imgui->text("");
|
||||
m_imgui->text("");
|
||||
if (m_imgui->button(_(L("Manual editing [M]"))))
|
||||
switch_to_editing_mode();
|
||||
|
||||
m_imgui->disabled_begin(m_editing_mode_cache.empty());
|
||||
remove_all = m_imgui->button(_(L("Remove all points")));
|
||||
m_imgui->disabled_end();
|
||||
|
||||
m_imgui->text("");
|
||||
|
||||
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
|
||||
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
|
||||
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
|
||||
(m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS"))));
|
||||
}
|
||||
|
||||
m_imgui->end();
|
||||
@ -2336,10 +2394,14 @@ RENDER_AGAIN:
|
||||
}
|
||||
m_old_editing_state = m_editing_mode;
|
||||
|
||||
if (remove_selected) {
|
||||
if (remove_selected || remove_all) {
|
||||
force_refresh = false;
|
||||
m_parent.reload_scene(true);
|
||||
delete_selected_points();
|
||||
m_parent.set_as_dirty();
|
||||
if (remove_all)
|
||||
select_point(AllPoints);
|
||||
delete_selected_points(remove_all);
|
||||
if (remove_all && !m_editing_mode)
|
||||
editing_mode_apply_changes();
|
||||
if (first_run) {
|
||||
first_run = false;
|
||||
goto RENDER_AGAIN;
|
||||
@ -2347,7 +2409,7 @@ RENDER_AGAIN:
|
||||
}
|
||||
|
||||
if (force_refresh)
|
||||
m_parent.reload_scene(true);
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
@ -2387,19 +2449,22 @@ void GLGizmoSlaSupports::on_set_state()
|
||||
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
|
||||
}
|
||||
if (m_state == Off) {
|
||||
if (m_old_state != Off && m_model_object) { // the gizmo was just turned Off
|
||||
if (m_old_state != Off) { // the gizmo was just turned Off
|
||||
|
||||
if (m_unsaved_changes) {
|
||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
|
||||
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_YES)
|
||||
editing_mode_apply_changes();
|
||||
else
|
||||
editing_mode_discard_changes();
|
||||
if (m_model_object) {
|
||||
if (m_unsaved_changes) {
|
||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
|
||||
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_YES)
|
||||
editing_mode_apply_changes();
|
||||
else
|
||||
editing_mode_discard_changes();
|
||||
}
|
||||
}
|
||||
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
m_editing_mode = false; // so it is not active next time the gizmo opens
|
||||
m_editing_mode_cache.clear();
|
||||
}
|
||||
}
|
||||
m_old_state = m_state;
|
||||
@ -2448,16 +2513,18 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
|
||||
// If there are no changes, don't touch the front-end. The data in the cache could have been
|
||||
// taken from the backend and copying them to ModelObject would needlessly invalidate them.
|
||||
if (m_unsaved_changes) {
|
||||
m_model_object->sla_points_status = sla::PointsStatus::UserModified;
|
||||
m_model_object->sla_support_points.clear();
|
||||
for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache)
|
||||
m_model_object->sla_support_points.push_back(point_and_selection.first);
|
||||
|
||||
// Recalculate support structures once the editing mode is left.
|
||||
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
m_editing_mode = false;
|
||||
m_unsaved_changes = false;
|
||||
|
||||
// Recalculate support structures once the editing mode is left.
|
||||
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
|
||||
|
||||
@ -2467,6 +2534,7 @@ void GLGizmoSlaSupports::editing_mode_reload_cache()
|
||||
m_editing_mode_cache.clear();
|
||||
for (const sla::SupportPoint& point : m_model_object->sla_support_points)
|
||||
m_editing_mode_cache.push_back(std::make_pair(point, false));
|
||||
|
||||
m_unsaved_changes = false;
|
||||
}
|
||||
|
||||
@ -2476,10 +2544,15 @@ void GLGizmoSlaSupports::get_data_from_backend()
|
||||
{
|
||||
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
||||
if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) {
|
||||
m_editing_mode_cache.clear();
|
||||
const std::vector<sla::SupportPoint>& points = po->get_support_points();
|
||||
auto mat = po->trafo().inverse().cast<float>();
|
||||
for (unsigned int i=0; i<points.size();++i)
|
||||
m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false);
|
||||
|
||||
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified)
|
||||
m_model_object->sla_points_status = sla::PointsStatus::AutoGenerated;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2497,8 +2570,9 @@ void GLGizmoSlaSupports::auto_generate()
|
||||
"Are you sure you want to do it?\n"
|
||||
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
||||
|
||||
if (m_model_object->sla_support_points.empty() || dlg.ShowModal() == wxID_YES) {
|
||||
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) {
|
||||
m_model_object->sla_support_points.clear();
|
||||
m_model_object->sla_points_status = sla::PointsStatus::Generating;
|
||||
m_editing_mode_cache.clear();
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
@ -2508,7 +2582,9 @@ void GLGizmoSlaSupports::auto_generate()
|
||||
|
||||
void GLGizmoSlaSupports::switch_to_editing_mode()
|
||||
{
|
||||
editing_mode_reload_cache();
|
||||
if (m_model_object->sla_points_status != sla::PointsStatus::AutoGenerated)
|
||||
editing_mode_reload_cache();
|
||||
m_unsaved_changes = false;
|
||||
m_editing_mode = true;
|
||||
}
|
||||
|
||||
@ -2564,8 +2640,13 @@ const double GLGizmoCut::Offset = 10.0;
|
||||
const double GLGizmoCut::Margin = 20.0;
|
||||
const std::array<float, 3> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 };
|
||||
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
#else
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, sprite_id)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_cut_z(0.0)
|
||||
, m_max_z(0.0)
|
||||
#if !ENABLE_IMGUI
|
||||
@ -2598,26 +2679,8 @@ void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent)
|
||||
|
||||
bool GLGizmoCut::on_init()
|
||||
{
|
||||
// TODO: icon
|
||||
|
||||
std::string path = resources_dir() + "/icons/overlay/";
|
||||
|
||||
if (!m_textures[Off].load_from_file(path + "cut_off.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_textures[Hover].load_from_file(path + "cut_hover.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_textures[On].load_from_file(path + "cut_on.png", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_grabbers.emplace_back();
|
||||
|
||||
m_shortcut_key = WXK_CONTROL_C;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2724,7 +2787,7 @@ void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) c
|
||||
}
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void GLGizmoCut::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
|
||||
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
m_imgui->set_next_window_bg_alpha(0.5f);
|
||||
|
@ -87,8 +87,10 @@ protected:
|
||||
int m_group_id;
|
||||
EState m_state;
|
||||
int m_shortcut_key;
|
||||
// textures are assumed to be square and all with the same size in pixels, no internal check is done
|
||||
GLTexture m_textures[Num_States];
|
||||
#if ENABLE_SVG_ICONS
|
||||
std::string m_icon_filename;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
unsigned int m_sprite_id;
|
||||
int m_hover_id;
|
||||
bool m_dragging;
|
||||
float m_base_color[3];
|
||||
@ -100,7 +102,11 @@ protected:
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
public:
|
||||
explicit GLGizmoBase(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
virtual ~GLGizmoBase() {}
|
||||
|
||||
bool init() { return on_init(); }
|
||||
@ -116,11 +122,14 @@ public:
|
||||
int get_shortcut_key() const { return m_shortcut_key; }
|
||||
void set_shortcut_key(int key) { m_shortcut_key = key; }
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
const std::string& get_icon_filename() const { return m_icon_filename; }
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); }
|
||||
bool is_selectable() const { return on_is_selectable(); }
|
||||
|
||||
unsigned int get_texture_id() const { return m_textures[m_state].get_id(); }
|
||||
int get_textures_size() const { return m_textures[Off].get_width(); }
|
||||
unsigned int get_sprite_id() const { return m_sprite_id; }
|
||||
|
||||
int get_hover_id() const { return m_hover_id; }
|
||||
void set_hover_id(int id);
|
||||
@ -144,7 +153,7 @@ public:
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
void render_input_window(float x, float y, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, selection); }
|
||||
void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
protected:
|
||||
@ -163,7 +172,7 @@ protected:
|
||||
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) {}
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {}
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
float picking_color_component(unsigned int id) const;
|
||||
@ -244,7 +253,11 @@ class GLGizmoRotate3D : public GLGizmoBase
|
||||
std::vector<GLGizmoRotate> m_gizmos;
|
||||
|
||||
public:
|
||||
explicit GLGizmoRotate3D(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
|
||||
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
|
||||
@ -296,7 +309,7 @@ protected:
|
||||
}
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
|
||||
#endif // ENABLE_IMGUI
|
||||
};
|
||||
|
||||
@ -315,7 +328,11 @@ class GLGizmoScale3D : public GLGizmoBase
|
||||
BoundingBoxf3 m_starting_box;
|
||||
|
||||
public:
|
||||
explicit GLGizmoScale3D(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
double get_snap_step(double step) const { return m_snap_step; }
|
||||
void set_snap_step(double step) { m_snap_step = step; }
|
||||
@ -333,7 +350,7 @@ protected:
|
||||
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
private:
|
||||
@ -362,7 +379,11 @@ class GLGizmoMove3D : public GLGizmoBase
|
||||
GLUquadricObj* m_quadric;
|
||||
|
||||
public:
|
||||
explicit GLGizmoMove3D(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
virtual ~GLGizmoMove3D();
|
||||
|
||||
double get_snap_step(double step) const { return m_snap_step; }
|
||||
@ -380,7 +401,7 @@ protected:
|
||||
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
private:
|
||||
@ -417,7 +438,11 @@ private:
|
||||
bool is_plane_update_necessary() const;
|
||||
|
||||
public:
|
||||
explicit GLGizmoFlatten(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
void set_flattening_data(const ModelObject* model_object);
|
||||
Vec3d get_flattening_normal() const;
|
||||
@ -437,7 +462,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define SLAGIZMO_IMGUI_MODAL 0
|
||||
|
||||
class GLGizmoSlaSupports : public GLGizmoBase
|
||||
{
|
||||
@ -465,11 +490,15 @@ private:
|
||||
mutable Vec3d m_starting_center;
|
||||
|
||||
public:
|
||||
explicit GLGizmoSlaSupports(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
virtual ~GLGizmoSlaSupports();
|
||||
void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
|
||||
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
|
||||
void delete_selected_points();
|
||||
void delete_selected_points(bool force = false);
|
||||
|
||||
private:
|
||||
bool on_init();
|
||||
@ -489,24 +518,26 @@ private:
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
bool m_lock_unique_islands = false;
|
||||
bool m_editing_mode = false;
|
||||
bool m_old_editing_state = false;
|
||||
float m_new_point_head_diameter = 0.4f;
|
||||
double m_minimal_point_distance = 20.;
|
||||
double m_density = 100.;
|
||||
bool m_editing_mode = false; // Is editing mode active?
|
||||
bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
|
||||
float m_new_point_head_diameter = 0.4f; // Size of a new point.
|
||||
float m_minimal_point_distance = 20.f;
|
||||
float m_density = 100.f;
|
||||
std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected
|
||||
|
||||
bool m_selection_rectangle_active = false;
|
||||
Vec2d m_selection_rectangle_start_corner;
|
||||
Vec2d m_selection_rectangle_end_corner;
|
||||
bool m_ignore_up_event = false;
|
||||
bool m_combo_box_open = false;
|
||||
bool m_unsaved_changes = false;
|
||||
bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox.
|
||||
bool m_unsaved_changes = false; // Are there unsaved changes in manual mode?
|
||||
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)
|
||||
int m_canvas_width;
|
||||
int m_canvas_height;
|
||||
|
||||
std::vector<ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
|
||||
|
||||
// Methods that do the model_object and editing cache synchronization,
|
||||
// editing mode selection, etc:
|
||||
enum {
|
||||
@ -526,7 +557,7 @@ protected:
|
||||
void on_start_dragging(const GLCanvas3D::Selection& selection) override;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) override;
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override;
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
virtual std::string on_get_name() const;
|
||||
@ -558,7 +589,11 @@ class GLGizmoCut : public GLGizmoBase
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
public:
|
||||
explicit GLGizmoCut(GLCanvas3D& parent);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
#if !ENABLE_IMGUI
|
||||
virtual void create_external_gizmo_widgets(wxWindow *parent);
|
||||
@ -577,7 +612,7 @@ protected:
|
||||
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
|
||||
virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
|
||||
#endif // ENABLE_IMGUI
|
||||
private:
|
||||
void update_max_z(const GLCanvas3D::Selection& selection) const;
|
||||
|
@ -225,6 +225,17 @@ bool GLShader::set_uniform(const char* name, const float* matrix) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GLShader::set_uniform(const char* name, int value) const
|
||||
{
|
||||
int id = get_uniform_location(name);
|
||||
if (id >= 0)
|
||||
{
|
||||
::glUniform1i(id, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
# Set shader vector
|
||||
sub SetVector
|
||||
@ -306,6 +317,16 @@ void Shader::stop_using() const
|
||||
m_shader->disable();
|
||||
}
|
||||
|
||||
int Shader::get_attrib_location(const std::string& name) const
|
||||
{
|
||||
return (m_shader != nullptr) ? m_shader->get_attrib_location(name.c_str()) : -1;
|
||||
}
|
||||
|
||||
int Shader::get_uniform_location(const std::string& name) const
|
||||
{
|
||||
return (m_shader != nullptr) ? m_shader->get_uniform_location(name.c_str()) : -1;
|
||||
}
|
||||
|
||||
void Shader::set_uniform(const std::string& name, float value) const
|
||||
{
|
||||
if (m_shader != nullptr)
|
||||
@ -321,7 +342,7 @@ void Shader::set_uniform(const std::string& name, const float* matrix) const
|
||||
void Shader::set_uniform(const std::string& name, bool value) const
|
||||
{
|
||||
if (m_shader != nullptr)
|
||||
m_shader->set_uniform(name.c_str(), value);
|
||||
m_shader->set_uniform(name.c_str(), value ? 1 : 0);
|
||||
}
|
||||
|
||||
unsigned int Shader::get_shader_program_id() const
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
|
||||
bool set_uniform(const char *name, float value) const;
|
||||
bool set_uniform(const char* name, const float* matrix) const;
|
||||
bool set_uniform(const char* name, int value) const;
|
||||
|
||||
void enable() const;
|
||||
void disable() const;
|
||||
@ -52,6 +53,9 @@ public:
|
||||
bool start_using() const;
|
||||
void stop_using() const;
|
||||
|
||||
int get_attrib_location(const std::string& name) const;
|
||||
int get_uniform_location(const std::string& name) const;
|
||||
|
||||
void set_uniform(const std::string& name, float value) const;
|
||||
void set_uniform(const std::string& name, const float* matrix) const;
|
||||
void set_uniform(const std::string& name, bool value) const;
|
||||
|
@ -6,19 +6,19 @@
|
||||
#include <wx/image.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvg.h"
|
||||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvgrast.h"
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@ -38,7 +38,6 @@ GLTexture::~GLTexture()
|
||||
reset();
|
||||
}
|
||||
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps)
|
||||
{
|
||||
reset();
|
||||
@ -64,25 +63,20 @@ bool GLTexture::load_from_svg_file(const std::string& filename, bool use_mipmaps
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps)
|
||||
|
||||
bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, const std::vector<std::pair<int, bool>>& states, unsigned int sprite_size_px)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (!boost::filesystem::exists(filename))
|
||||
if (filenames.empty() || states.empty() || (sprite_size_px == 0))
|
||||
return false;
|
||||
|
||||
// Load a PNG with an alpha channel.
|
||||
wxImage image;
|
||||
if (!image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG))
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_width = image.GetWidth();
|
||||
m_height = image.GetHeight();
|
||||
m_width = (int)(sprite_size_px * states.size());
|
||||
m_height = (int)(sprite_size_px * filenames.size());
|
||||
int n_pixels = m_width * m_height;
|
||||
int sprite_n_pixels = sprite_size_px * sprite_size_px;
|
||||
int sprite_bytes = sprite_n_pixels * 4;
|
||||
int sprite_stride = sprite_size_px * 4;
|
||||
|
||||
if (n_pixels <= 0)
|
||||
{
|
||||
@ -90,52 +84,136 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get RGB & alpha raw data from wxImage, pack them into an array.
|
||||
unsigned char* img_rgb = image.GetData();
|
||||
if (img_rgb == nullptr)
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
std::vector<unsigned char> sprite_data(sprite_bytes, 0);
|
||||
std::vector<unsigned char> sprite_white_only_data(sprite_bytes, 0);
|
||||
std::vector<unsigned char> sprite_gray_only_data(sprite_bytes, 0);
|
||||
std::vector<unsigned char> output_data(sprite_bytes, 0);
|
||||
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
if (rast == nullptr)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char* img_alpha = image.GetAlpha();
|
||||
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
for (int i = 0; i < n_pixels; ++i)
|
||||
int sprite_id = -1;
|
||||
for (const std::string& filename : filenames)
|
||||
{
|
||||
int data_id = i * 4;
|
||||
int img_id = i * 3;
|
||||
data[data_id + 0] = img_rgb[img_id + 0];
|
||||
data[data_id + 1] = img_rgb[img_id + 1];
|
||||
data[data_id + 2] = img_rgb[img_id + 2];
|
||||
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
|
||||
++sprite_id;
|
||||
|
||||
if (!boost::filesystem::exists(filename))
|
||||
continue;
|
||||
|
||||
if (!boost::algorithm::iends_with(filename, ".svg"))
|
||||
continue;
|
||||
|
||||
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
|
||||
if (image == nullptr)
|
||||
continue;
|
||||
|
||||
float scale = (float)sprite_size_px / std::max(image->width, image->height);
|
||||
|
||||
nsvgRasterize(rast, image, 0, 0, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride);
|
||||
|
||||
// makes white only copy of the sprite
|
||||
::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i)
|
||||
{
|
||||
int offset = i * 4;
|
||||
if (sprite_white_only_data.data()[offset] != 0)
|
||||
::memset((void*)&sprite_white_only_data.data()[offset], 255, 3);
|
||||
}
|
||||
|
||||
// makes gray only copy of the sprite
|
||||
::memcpy((void*)sprite_gray_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i)
|
||||
{
|
||||
int offset = i * 4;
|
||||
if (sprite_gray_only_data.data()[offset] != 0)
|
||||
::memset((void*)&sprite_gray_only_data.data()[offset], 128, 3);
|
||||
}
|
||||
|
||||
int sprite_offset_px = sprite_id * sprite_size_px * m_width;
|
||||
int state_id = -1;
|
||||
for (const std::pair<int, bool>& state : states)
|
||||
{
|
||||
++state_id;
|
||||
|
||||
// select the sprite variant
|
||||
std::vector<unsigned char>* src = nullptr;
|
||||
switch (state.first)
|
||||
{
|
||||
case 1: { src = &sprite_white_only_data; break; }
|
||||
case 2: { src = &sprite_gray_only_data; break; }
|
||||
default: { src = &sprite_data; break; }
|
||||
}
|
||||
|
||||
::memcpy((void*)output_data.data(), (const void*)src->data(), sprite_bytes);
|
||||
// applies background, if needed
|
||||
if (state.second)
|
||||
{
|
||||
for (int i = 0; i < sprite_n_pixels; ++i)
|
||||
{
|
||||
int offset = i * 4;
|
||||
float alpha = (float)output_data.data()[offset + 3] / 255.0f;
|
||||
output_data.data()[offset + 0] = (unsigned char)(output_data.data()[offset + 0] * alpha);
|
||||
output_data.data()[offset + 1] = (unsigned char)(output_data.data()[offset + 1] * alpha);
|
||||
output_data.data()[offset + 2] = (unsigned char)(output_data.data()[offset + 2] * alpha);
|
||||
output_data.data()[offset + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[offset + 3] * alpha);
|
||||
}
|
||||
}
|
||||
|
||||
int state_offset_px = sprite_offset_px + state_id * sprite_size_px;
|
||||
for (int j = 0; j < (int)sprite_size_px; ++j)
|
||||
{
|
||||
::memcpy((void*)&data.data()[(state_offset_px + j * m_width) * 4], (const void*)&output_data.data()[j * sprite_stride], sprite_stride);
|
||||
}
|
||||
}
|
||||
|
||||
nsvgDelete(image);
|
||||
}
|
||||
|
||||
nsvgDeleteRasterizer(rast);
|
||||
|
||||
// sends data to gpu
|
||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
::glGenTextures(1, &m_id);
|
||||
::glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
if (use_mipmaps)
|
||||
{
|
||||
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
|
||||
unsigned int levels_count = generate_mipmaps(image);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 + levels_count);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
}
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
m_source = filename;
|
||||
m_source = filenames.front();
|
||||
|
||||
#if 0
|
||||
// debug output
|
||||
static int pass = 0;
|
||||
++pass;
|
||||
|
||||
wxImage output(m_width, m_height);
|
||||
output.InitAlpha();
|
||||
|
||||
for (int h = 0; h < m_height; ++h)
|
||||
{
|
||||
int px_h = h * m_width;
|
||||
for (int w = 0; w < m_width; ++w)
|
||||
{
|
||||
int offset = (px_h + w) * 4;
|
||||
output.SetRGB(w, h, data.data()[offset + 0], data.data()[offset + 1], data.data()[offset + 2]);
|
||||
output.SetAlpha(w, h, data.data()[offset + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string out_filename = resources_dir() + "/icons/test_" + std::to_string(pass) + ".png";
|
||||
output.SaveFile(out_filename, wxBITMAP_TYPE_PNG);
|
||||
#endif // 0
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
||||
void GLTexture::reset()
|
||||
{
|
||||
@ -214,7 +292,6 @@ unsigned int GLTexture::generate_mipmaps(wxImage& image)
|
||||
return (unsigned int)level;
|
||||
}
|
||||
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps)
|
||||
{
|
||||
// Load a PNG with an alpha channel.
|
||||
@ -265,13 +342,13 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps)
|
||||
{
|
||||
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
|
||||
unsigned int levels_count = generate_mipmaps(image);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 + levels_count);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels_count);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
@ -340,13 +417,13 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
|
||||
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
}
|
||||
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 + level);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
}
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
@ -359,7 +436,6 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, uns
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
@ -38,9 +38,16 @@ namespace GUI {
|
||||
virtual ~GLTexture();
|
||||
|
||||
bool load_from_file(const std::string& filename, bool use_mipmaps);
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
bool load_from_svg_file(const std::string& filename, bool use_mipmaps, unsigned int max_size_px);
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
// meanings of states: (std::pair<int, bool>)
|
||||
// first field (int):
|
||||
// 0 -> no changes
|
||||
// 1 -> use white only color variant
|
||||
// 2 -> use gray only color variant
|
||||
// second field (bool):
|
||||
// false -> no changes
|
||||
// true -> add background color
|
||||
bool load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, const std::vector<std::pair<int, bool>>& states, unsigned int sprite_size_px);
|
||||
void reset();
|
||||
|
||||
unsigned int get_id() const { return m_id; }
|
||||
@ -54,11 +61,9 @@ namespace GUI {
|
||||
|
||||
protected:
|
||||
unsigned int generate_mipmaps(wxImage& image);
|
||||
#if ENABLE_TEXTURES_FROM_SVG
|
||||
private:
|
||||
bool load_from_png(const std::string& filename, bool use_mipmaps);
|
||||
bool load_from_svg(const std::string& filename, bool use_mipmaps, unsigned int max_size_px);
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
@ -32,12 +32,13 @@ wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
|
||||
|
||||
GLToolbarItem::Data::Data()
|
||||
: name("")
|
||||
#if ENABLE_SVG_ICONS
|
||||
, icon_filename("")
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, tooltip("")
|
||||
, sprite_id(-1)
|
||||
, is_toggable(false)
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
, visible(true)
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
{
|
||||
}
|
||||
|
||||
@ -53,26 +54,24 @@ void GLToolbarItem::do_action(wxEvtHandler *target)
|
||||
wxPostEvent(target, SimpleEvent(m_data.action_event));
|
||||
}
|
||||
|
||||
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const
|
||||
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
|
||||
{
|
||||
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(texture_size, border_size, icon_size, gap_size));
|
||||
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(tex_width, tex_height, icon_size));
|
||||
}
|
||||
|
||||
GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const
|
||||
GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
|
||||
{
|
||||
GLTexture::Quad_UVs uvs;
|
||||
|
||||
float inv_texture_size = (texture_size != 0) ? 1.0f / (float)texture_size : 0.0f;
|
||||
float inv_tex_width = (tex_width != 0) ? 1.0f / (float)tex_width : 0.0f;
|
||||
float inv_tex_height = (tex_height != 0) ? 1.0f / (float)tex_height : 0.0f;
|
||||
|
||||
float scaled_icon_size = (float)icon_size * inv_texture_size;
|
||||
float scaled_border_size = (float)border_size * inv_texture_size;
|
||||
float scaled_gap_size = (float)gap_size * inv_texture_size;
|
||||
float stride = scaled_icon_size + scaled_gap_size;
|
||||
|
||||
float left = scaled_border_size + (float)m_state * stride;
|
||||
float right = left + scaled_icon_size;
|
||||
float top = scaled_border_size + (float)m_data.sprite_id * stride;
|
||||
float bottom = top + scaled_icon_size;
|
||||
float scaled_icon_width = (float)icon_size * inv_tex_width;
|
||||
float scaled_icon_height = (float)icon_size * inv_tex_height;
|
||||
float left = (float)m_state * scaled_icon_width;
|
||||
float right = left + scaled_icon_width;
|
||||
float top = (float)m_data.sprite_id * scaled_icon_height;
|
||||
float bottom = top + scaled_icon_height;
|
||||
|
||||
uvs.left_top = { left, top };
|
||||
uvs.left_bottom = { left, bottom };
|
||||
@ -82,13 +81,13 @@ GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int texture_size, unsigned i
|
||||
return uvs;
|
||||
}
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
ItemsIconsTexture::Metadata::Metadata()
|
||||
: filename("")
|
||||
, icon_size(0)
|
||||
, icon_border_size(0)
|
||||
, icon_gap_size(0)
|
||||
{
|
||||
}
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
BackgroundTexture::Metadata::Metadata()
|
||||
: filename("")
|
||||
@ -99,6 +98,10 @@ BackgroundTexture::Metadata::Metadata()
|
||||
{
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
const float GLToolbar::Default_Icons_Size = 64.0f;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
GLToolbar::Layout::Layout()
|
||||
: type(Horizontal)
|
||||
, orientation(Center)
|
||||
@ -107,16 +110,31 @@ GLToolbar::Layout::Layout()
|
||||
, border(0.0f)
|
||||
, separator_size(0.0f)
|
||||
, gap_size(0.0f)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, icons_size(Default_Icons_Size)
|
||||
, scale(1.0f)
|
||||
#else
|
||||
, icons_scale(1.0f)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, width(0.0f)
|
||||
, height(0.0f)
|
||||
, dirty(true)
|
||||
{
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLToolbar::GLToolbar(GLToolbar::EType type, const std::string& name)
|
||||
#else
|
||||
GLToolbar::GLToolbar(GLToolbar::EType type)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
: m_type(type)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_name(name)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_enabled(false)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_icons_texture_dirty(true)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
{
|
||||
}
|
||||
|
||||
@ -128,8 +146,19 @@ GLToolbar::~GLToolbar()
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture)
|
||||
#else
|
||||
bool GLToolbar::init(const ItemsIconsTexture::Metadata& icons_texture, const BackgroundTexture::Metadata& background_texture)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (m_background_texture.texture.get_id() != 0)
|
||||
return true;
|
||||
|
||||
std::string path = resources_dir() + "/icons/";
|
||||
bool res = false;
|
||||
#else
|
||||
if (m_icons_texture.texture.get_id() != 0)
|
||||
return true;
|
||||
|
||||
@ -137,6 +166,7 @@ bool GLToolbar::init(const ItemsIconsTexture::Metadata& icons_texture, const Bac
|
||||
bool res = !icons_texture.filename.empty() && m_icons_texture.texture.load_from_file(path + icons_texture.filename, false);
|
||||
if (res)
|
||||
m_icons_texture.metadata = icons_texture;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
if (!background_texture.filename.empty())
|
||||
res = m_background_texture.texture.load_from_file(path + background_texture.filename, false);
|
||||
@ -192,11 +222,33 @@ void GLToolbar::set_gap_size(float size)
|
||||
m_layout.dirty = true;
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
void GLToolbar::set_icons_size(float size)
|
||||
{
|
||||
if (m_layout.icons_size != size)
|
||||
{
|
||||
m_layout.icons_size = size;
|
||||
m_layout.dirty = true;
|
||||
m_icons_texture_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GLToolbar::set_scale(float scale)
|
||||
{
|
||||
if (m_layout.scale != scale)
|
||||
{
|
||||
m_layout.scale = scale;
|
||||
m_layout.dirty = true;
|
||||
m_icons_texture_dirty = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void GLToolbar::set_icons_scale(float scale)
|
||||
{
|
||||
m_layout.icons_scale = scale;
|
||||
m_layout.dirty = true;
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
bool GLToolbar::is_enabled() const
|
||||
{
|
||||
@ -308,7 +360,6 @@ bool GLToolbar::is_item_disabled(const std::string& name) const
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
bool GLToolbar::is_item_visible(const std::string& name) const
|
||||
{
|
||||
for (GLToolbarItem* item : m_items)
|
||||
@ -346,7 +397,6 @@ void GLToolbar::set_item_visible(const std::string& name, bool visible)
|
||||
}
|
||||
|
||||
}
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
||||
{
|
||||
@ -417,6 +467,11 @@ void GLToolbar::render(const GLCanvas3D& parent) const
|
||||
if (!m_enabled || m_items.empty())
|
||||
return;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (m_icons_texture_dirty)
|
||||
generate_icons_texture();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
::glPushMatrix();
|
||||
@ -461,12 +516,20 @@ float GLToolbar::get_width_horizontal() const
|
||||
|
||||
float GLToolbar::get_width_vertical() const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale;
|
||||
#else
|
||||
return 2.0f * m_layout.border * m_layout.icons_scale + m_icons_texture.metadata.icon_size * m_layout.icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
float GLToolbar::get_height_horizontal() const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale;
|
||||
#else
|
||||
return 2.0f * m_layout.border * m_layout.icons_scale + m_icons_texture.metadata.icon_size * m_layout.icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
float GLToolbar::get_height_vertical() const
|
||||
@ -476,13 +539,29 @@ float GLToolbar::get_height_vertical() const
|
||||
|
||||
float GLToolbar::get_main_size() const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
float size = 2.0f * m_layout.border;
|
||||
for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
|
||||
{
|
||||
if (!m_items[i]->is_visible())
|
||||
continue;
|
||||
|
||||
if (m_items[i]->is_separator())
|
||||
size += m_layout.separator_size;
|
||||
else
|
||||
size += (float)m_layout.icons_size;
|
||||
}
|
||||
|
||||
if (m_items.size() > 1)
|
||||
size += ((float)m_items.size() - 1.0f) * m_layout.gap_size;
|
||||
|
||||
size *= m_layout.scale;
|
||||
#else
|
||||
float size = 2.0f * m_layout.border * m_layout.icons_scale;
|
||||
for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
|
||||
{
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!m_items[i]->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (m_items[i]->is_separator())
|
||||
size += m_layout.separator_size * m_layout.icons_scale;
|
||||
@ -492,6 +571,7 @@ float GLToolbar::get_main_size() const
|
||||
|
||||
if (m_items.size() > 1)
|
||||
size += ((float)m_items.size() - 1.0f) * m_layout.gap_size * m_layout.icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -502,12 +582,20 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
#else
|
||||
float factor = m_layout.icons_scale * inv_zoom;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
@ -522,10 +610,8 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
|
||||
|
||||
for (GLToolbarItem* item : m_items)
|
||||
{
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
left += separator_stride;
|
||||
@ -601,16 +687,23 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
#else
|
||||
float factor = m_layout.icons_scale * inv_zoom;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
|
||||
float separator_stride = scaled_separator_size + scaled_gap_size;
|
||||
float icon_stride = scaled_icons_size + scaled_gap_size;
|
||||
|
||||
@ -621,10 +714,8 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
|
||||
|
||||
for (GLToolbarItem* item : m_items)
|
||||
{
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
top -= separator_stride;
|
||||
@ -700,16 +791,23 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
#else
|
||||
float factor = m_layout.icons_scale * inv_zoom;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
|
||||
float separator_stride = scaled_separator_size + scaled_gap_size;
|
||||
float icon_stride = scaled_icons_size + scaled_gap_size;
|
||||
|
||||
@ -722,10 +820,8 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
|
||||
{
|
||||
++id;
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
left += separator_stride;
|
||||
@ -733,7 +829,7 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
|
||||
{
|
||||
float right = left + scaled_icons_size;
|
||||
float bottom = top - scaled_icons_size;
|
||||
|
||||
|
||||
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
||||
return id;
|
||||
|
||||
@ -750,12 +846,20 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = m_layout.scale * inv_zoom;
|
||||
#else
|
||||
float factor = m_layout.icons_scale * inv_zoom;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Size cnv_size = parent.get_canvas_size();
|
||||
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
@ -772,10 +876,8 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
|
||||
{
|
||||
++id;
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
top -= separator_stride;
|
||||
@ -796,17 +898,34 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
|
||||
|
||||
void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
unsigned int tex_id = m_icons_texture.get_id();
|
||||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
#else
|
||||
unsigned int tex_id = m_icons_texture.texture.get_id();
|
||||
int tex_size = m_icons_texture.texture.get_width();
|
||||
int tex_width = m_icons_texture.texture.get_width();
|
||||
int tex_height = m_icons_texture.texture.get_height();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
if ((tex_id == 0) || (tex_size <= 0))
|
||||
#if !ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
||||
return;
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = inv_zoom * m_layout.scale;
|
||||
#else
|
||||
float factor = inv_zoom * m_layout.icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
@ -907,19 +1026,26 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||
left += scaled_border;
|
||||
top -= scaled_border;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
||||
return;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
// renders icons
|
||||
for (const GLToolbarItem* item : m_items)
|
||||
{
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
left += separator_stride;
|
||||
else
|
||||
{
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, m_icons_texture.metadata.icon_border_size, m_icons_texture.metadata.icon_size, m_icons_texture.metadata.icon_gap_size);
|
||||
#if ENABLE_SVG_ICONS
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
|
||||
#else
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, m_icons_texture.metadata.icon_size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
left += icon_stride;
|
||||
}
|
||||
}
|
||||
@ -927,17 +1053,34 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||
|
||||
void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
unsigned int tex_id = m_icons_texture.get_id();
|
||||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
#else
|
||||
unsigned int tex_id = m_icons_texture.texture.get_id();
|
||||
int tex_size = m_icons_texture.texture.get_width();
|
||||
int tex_width = m_icons_texture.texture.get_width();
|
||||
int tex_height = m_icons_texture.texture.get_height();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
if ((tex_id == 0) || (tex_size <= 0))
|
||||
#if !ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
||||
return;
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
float zoom = parent.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float factor = inv_zoom * m_layout.scale;
|
||||
#else
|
||||
float factor = inv_zoom * m_layout.icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_layout.icons_size * factor;
|
||||
#else
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_layout.icons_scale * factor;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float scaled_separator_size = m_layout.separator_size * factor;
|
||||
float scaled_gap_size = m_layout.gap_size * factor;
|
||||
float scaled_border = m_layout.border * factor;
|
||||
@ -1038,23 +1181,68 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
||||
left += scaled_border;
|
||||
top -= scaled_border;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
||||
return;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
// renders icons
|
||||
for (const GLToolbarItem* item : m_items)
|
||||
{
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
if (!item->is_visible())
|
||||
continue;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
if (item->is_separator())
|
||||
top -= separator_stride;
|
||||
else
|
||||
{
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, m_icons_texture.metadata.icon_border_size, m_icons_texture.metadata.icon_size, m_icons_texture.metadata.icon_gap_size);
|
||||
#if ENABLE_SVG_ICONS
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
|
||||
#else
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, m_icons_texture.metadata.icon_size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
top -= icon_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool GLToolbar::generate_icons_texture() const
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/";
|
||||
std::vector<std::string> filenames;
|
||||
for (GLToolbarItem* item : m_items)
|
||||
{
|
||||
const std::string& icon_filename = item->get_icon_filename();
|
||||
if (!icon_filename.empty())
|
||||
filenames.push_back(path + icon_filename);
|
||||
}
|
||||
|
||||
std::vector<std::pair<int, bool>> states;
|
||||
if (m_name == "Top")
|
||||
{
|
||||
states.push_back(std::make_pair(1, false));
|
||||
states.push_back(std::make_pair(0, false));
|
||||
states.push_back(std::make_pair(2, false));
|
||||
states.push_back(std::make_pair(0, false));
|
||||
states.push_back(std::make_pair(0, false));
|
||||
}
|
||||
else if (m_name == "View")
|
||||
{
|
||||
states.push_back(std::make_pair(1, false));
|
||||
states.push_back(std::make_pair(1, true));
|
||||
states.push_back(std::make_pair(1, false));
|
||||
states.push_back(std::make_pair(0, false));
|
||||
states.push_back(std::make_pair(1, true));
|
||||
}
|
||||
|
||||
bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, (unsigned int)(m_layout.icons_size * m_layout.scale));
|
||||
if (res)
|
||||
m_icons_texture_dirty = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
@ -51,13 +51,14 @@ public:
|
||||
struct Data
|
||||
{
|
||||
std::string name;
|
||||
#if ENABLE_SVG_ICONS
|
||||
std::string icon_filename;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
std::string tooltip;
|
||||
unsigned int sprite_id;
|
||||
bool is_toggable;
|
||||
wxEventType action_event;
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
bool visible;
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
Data();
|
||||
};
|
||||
@ -74,6 +75,9 @@ public:
|
||||
void set_state(EState state) { m_state = state; }
|
||||
|
||||
const std::string& get_name() const { return m_data.name; }
|
||||
#if ENABLE_SVG_ICONS
|
||||
const std::string& get_icon_filename() const { return m_data.icon_filename; }
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
const std::string& get_tooltip() const { return m_data.tooltip; }
|
||||
|
||||
void do_action(wxEvtHandler *target);
|
||||
@ -84,18 +88,17 @@ public:
|
||||
bool is_pressed() const { return (m_state == Pressed) || (m_state == HoverPressed); }
|
||||
|
||||
bool is_toggable() const { return m_data.is_toggable; }
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
bool is_visible() const { return m_data.visible; }
|
||||
void set_visible(bool visible) { m_data.visible = visible; }
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
bool is_separator() const { return m_type == Separator; }
|
||||
|
||||
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const;
|
||||
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
|
||||
|
||||
private:
|
||||
GLTexture::Quad_UVs get_uvs(unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const;
|
||||
GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
|
||||
};
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
// items icon textures are assumed to be square and all with the same size in pixels, no internal check is done
|
||||
// icons are layed-out into the texture starting from the top-left corner in the same order as enum GLToolbarItem::EState
|
||||
// from left to right
|
||||
@ -107,10 +110,6 @@ struct ItemsIconsTexture
|
||||
std::string filename;
|
||||
// size of the square icons, in pixels
|
||||
unsigned int icon_size;
|
||||
// size of the border, in pixels
|
||||
unsigned int icon_border_size;
|
||||
// distance between two adjacent icons (to avoid filtering artifacts), in pixels
|
||||
unsigned int icon_gap_size;
|
||||
|
||||
Metadata();
|
||||
};
|
||||
@ -118,6 +117,7 @@ struct ItemsIconsTexture
|
||||
GLTexture texture;
|
||||
Metadata metadata;
|
||||
};
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
struct BackgroundTexture
|
||||
{
|
||||
@ -144,6 +144,10 @@ struct BackgroundTexture
|
||||
class GLToolbar
|
||||
{
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
static const float Default_Icons_Size;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
enum EType : unsigned char
|
||||
{
|
||||
Normal,
|
||||
@ -177,7 +181,12 @@ public:
|
||||
float border;
|
||||
float separator_size;
|
||||
float gap_size;
|
||||
#if ENABLE_SVG_ICONS
|
||||
float icons_size;
|
||||
float scale;
|
||||
#else
|
||||
float icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
float width;
|
||||
float height;
|
||||
@ -190,18 +199,34 @@ private:
|
||||
typedef std::vector<GLToolbarItem*> ItemsList;
|
||||
|
||||
EType m_type;
|
||||
#if ENABLE_SVG_ICONS
|
||||
std::string m_name;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
bool m_enabled;
|
||||
#if ENABLE_SVG_ICONS
|
||||
mutable GLTexture m_icons_texture;
|
||||
mutable bool m_icons_texture_dirty;
|
||||
#else
|
||||
ItemsIconsTexture m_icons_texture;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
BackgroundTexture m_background_texture;
|
||||
mutable Layout m_layout;
|
||||
|
||||
ItemsList m_items;
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLToolbar(EType type, const std::string& name);
|
||||
#else
|
||||
explicit GLToolbar(EType type);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
~GLToolbar();
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool init(const BackgroundTexture::Metadata& background_texture);
|
||||
#else
|
||||
bool init(const ItemsIconsTexture::Metadata& icons_texture, const BackgroundTexture::Metadata& background_texture);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
Layout::EType get_layout_type() const;
|
||||
void set_layout_type(Layout::EType type);
|
||||
@ -212,7 +237,12 @@ public:
|
||||
void set_border(float border);
|
||||
void set_separator_size(float size);
|
||||
void set_gap_size(float size);
|
||||
#if ENABLE_SVG_ICONS
|
||||
void set_icons_size(float size);
|
||||
void set_scale(float scale);
|
||||
#else
|
||||
void set_icons_scale(float scale);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool enable);
|
||||
@ -229,10 +259,8 @@ public:
|
||||
|
||||
bool is_item_pressed(const std::string& name) const;
|
||||
bool is_item_disabled(const std::string& name) const;
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
bool is_item_visible(const std::string& name) const;
|
||||
void set_item_visible(const std::string& name, bool visible);
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
|
||||
|
||||
@ -257,6 +285,10 @@ private:
|
||||
|
||||
void render_horizontal(const GLCanvas3D& parent) const;
|
||||
void render_vertical(const GLCanvas3D& parent) const;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool generate_icons_texture() const;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@ -123,6 +125,9 @@ void config_wizard(int reason)
|
||||
if (! wxGetApp().check_unsaved_changes())
|
||||
return;
|
||||
|
||||
// save selected preset before config wizard running
|
||||
const auto printer_preset_name = wxGetApp().preset_bundle->printers.get_edited_preset().name;
|
||||
|
||||
try {
|
||||
ConfigWizard wizard(nullptr, static_cast<ConfigWizard::RunReason>(reason));
|
||||
wizard.run(wxGetApp().preset_bundle, wxGetApp().preset_updater);
|
||||
@ -131,8 +136,21 @@ void config_wizard(int reason)
|
||||
show_error(nullptr, e.what());
|
||||
}
|
||||
|
||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||
wxGetApp().load_current_presets();
|
||||
// select old(before config wizard running) preset
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printer_preset_name);
|
||||
// If old preset if invisible now, then first visible preset will be selected
|
||||
// So, let control the case if multi-part object is on the scene and first visible preset is SLA
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA &&
|
||||
wxGetApp().obj_list()->has_multi_part_objects())
|
||||
{
|
||||
show_info(nullptr,
|
||||
_(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" +
|
||||
_(L("Please check and fix your object list.")),
|
||||
_(L("Attention!")));
|
||||
}
|
||||
|
||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||
// wxGetApp().load_current_presets(); // #ys_FIXME_to_delete presets are loaded now in select_preset function
|
||||
}
|
||||
|
||||
// opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)
|
||||
|
@ -177,33 +177,40 @@ bool GUI_App::OnInit()
|
||||
|
||||
if (this->plater() != nullptr)
|
||||
this->obj_manipul()->update_if_dirty();
|
||||
});
|
||||
|
||||
// On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...)
|
||||
// are shown before or in the same event callback with the main frame creation.
|
||||
// Therefore we schedule them for later using CallAfter.
|
||||
CallAfter([this]() {
|
||||
try {
|
||||
if (!preset_updater->config_update())
|
||||
mainframe->Close();
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, ex.what());
|
||||
// Preset updating & Configwizard are done after the above initializations,
|
||||
// and after MainFrame is created & shown.
|
||||
// The extra CallAfter() is needed because of Mac, where this is the only way
|
||||
// to popup a modal dialog on start without screwing combo boxes.
|
||||
// This is ugly but I honestly found not better way to do it.
|
||||
// Neither wxShowEvent nor wxWindowCreateEvent work reliably.
|
||||
static bool once = true;
|
||||
if (once) {
|
||||
once = false;
|
||||
|
||||
try {
|
||||
if (!preset_updater->config_update()) {
|
||||
mainframe->Close();
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, ex.what());
|
||||
}
|
||||
|
||||
CallAfter([this] {
|
||||
if (!config_wizard_startup(app_conf_exists)) {
|
||||
// Only notify if there was not wizard so as not to bother too much ...
|
||||
preset_updater->slic3r_update_notify();
|
||||
}
|
||||
preset_updater->sync(preset_bundle);
|
||||
});
|
||||
|
||||
load_current_presets();
|
||||
}
|
||||
});
|
||||
|
||||
CallAfter([this]() {
|
||||
if (!config_wizard_startup(app_conf_exists)) {
|
||||
// Only notify if there was not wizard so as not to bother too much ...
|
||||
preset_updater->slic3r_update_notify();
|
||||
}
|
||||
preset_updater->sync(preset_bundle);
|
||||
|
||||
load_current_presets();
|
||||
});
|
||||
|
||||
|
||||
mainframe->Show(true);
|
||||
return m_initialized = true;
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
||||
|
@ -38,6 +38,11 @@ FreqSettingsBundle FREQ_SETTINGS_BUNDLE_SLA =
|
||||
{ L("Pad and Support") , { "supports_enable", "pad_enable" } }
|
||||
};
|
||||
|
||||
static PrinterTechnology printer_technology()
|
||||
{
|
||||
return wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology();
|
||||
}
|
||||
|
||||
ObjectList::ObjectList(wxWindow* parent) :
|
||||
wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE),
|
||||
m_parent(parent)
|
||||
@ -259,7 +264,7 @@ void ObjectList::update_extruder_values_for_items(const int max_extruder)
|
||||
void ObjectList::update_objects_list_extruder_column(int extruders_count)
|
||||
{
|
||||
if (!this) return; // #ys_FIXME
|
||||
if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA)
|
||||
if (printer_technology() == ptSLA)
|
||||
extruders_count = 1;
|
||||
|
||||
wxDataViewChoiceRenderer* ch_render = dynamic_cast<wxDataViewChoiceRenderer*>(GetColumn(1)->GetRenderer());
|
||||
@ -376,7 +381,8 @@ void ObjectList::selection_changed()
|
||||
fix_multiselection_conflicts();
|
||||
|
||||
// update object selection on Plater
|
||||
update_selections_on_canvas();
|
||||
if (!m_prevent_canvas_selection_update)
|
||||
update_selections_on_canvas();
|
||||
|
||||
// to update the toolbar and info sizer
|
||||
if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
|
||||
@ -451,7 +457,7 @@ void ObjectList::show_context_menu()
|
||||
|
||||
wxMenu* menu = type & itInstance ? &m_menu_instance :
|
||||
m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
|
||||
wxGetApp().plater()->printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
|
||||
printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
|
||||
|
||||
if (!(type & itInstance))
|
||||
append_menu_item_settings(menu);
|
||||
@ -596,7 +602,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||
|
||||
std::vector<std::string> ObjectList::get_options(const bool is_part)
|
||||
{
|
||||
if (wxGetApp().plater()->printer_technology() == ptSLA) {
|
||||
if (printer_technology() == ptSLA) {
|
||||
SLAPrintObjectConfig full_sla_config;
|
||||
auto options = full_sla_config.keys();
|
||||
options.erase(find(options.begin(), options.end(), "layer_height"));
|
||||
@ -615,7 +621,7 @@ std::vector<std::string> ObjectList::get_options(const bool is_part)
|
||||
|
||||
const std::vector<std::string>& ObjectList::get_options_for_bundle(const wxString& bundle_name)
|
||||
{
|
||||
const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
const FreqSettingsBundle& bundle = printer_technology() == ptSLA ?
|
||||
FREQ_SETTINGS_BUNDLE_SLA : FREQ_SETTINGS_BUNDLE_FFF;
|
||||
|
||||
for (auto& it : bundle)
|
||||
@ -625,7 +631,7 @@ const std::vector<std::string>& ObjectList::get_options_for_bundle(const wxStrin
|
||||
}
|
||||
#if 0
|
||||
// if "Quick menu" is selected
|
||||
FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
FreqSettingsBundle& bundle_quick = printer_technology() == ptSLA ?
|
||||
m_freq_settings_sla: m_freq_settings_fff;
|
||||
|
||||
for (auto& it : bundle_quick)
|
||||
@ -643,7 +649,7 @@ void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const
|
||||
{
|
||||
auto options = get_options(is_part);
|
||||
|
||||
auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
|
||||
auto extruders_cnt = printer_technology() == ptSLA ? 1 :
|
||||
wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
|
||||
DynamicPrintConfig config;
|
||||
@ -704,7 +710,7 @@ void ObjectList::get_settings_choice(const wxString& category_name)
|
||||
if (selection_cnt > 0)
|
||||
{
|
||||
// Add selected items to the "Quick menu"
|
||||
FreqSettingsBundle& freq_settings = wxGetApp().plater()->printer_technology() == ptSLA ?
|
||||
FreqSettingsBundle& freq_settings = printer_technology() == ptSLA ?
|
||||
m_freq_settings_sla : m_freq_settings_fff;
|
||||
bool changed_existing = false;
|
||||
|
||||
@ -750,7 +756,9 @@ void ObjectList::get_settings_choice(const wxString& category_name)
|
||||
for (auto sel : selections)
|
||||
selected_options.push_back((*settings_list)[sel].first);
|
||||
|
||||
const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
const DynamicPrintConfig& from_config = printer_technology() == ptFFF ?
|
||||
wxGetApp().preset_bundle->prints.get_edited_preset().config :
|
||||
wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
|
||||
for (auto& setting : (*settings_list))
|
||||
{
|
||||
@ -1064,10 +1072,10 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
|
||||
void ObjectList::create_freq_settings_popupmenu(wxMenu *menu)
|
||||
{
|
||||
// Add default settings bundles
|
||||
const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptFFF ?
|
||||
const FreqSettingsBundle& bundle = printer_technology() == ptFFF ?
|
||||
FREQ_SETTINGS_BUNDLE_FFF : FREQ_SETTINGS_BUNDLE_SLA;
|
||||
|
||||
auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
|
||||
auto extruders_cnt = printer_technology() == ptSLA ? 1 :
|
||||
wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
|
||||
|
||||
for (auto& it : bundle) {
|
||||
@ -1080,7 +1088,7 @@ void ObjectList::create_freq_settings_popupmenu(wxMenu *menu)
|
||||
}
|
||||
#if 0
|
||||
// Add "Quick" settings bundles
|
||||
const FreqSettingsBundle& bundle_quick = wxGetApp().plater()->printer_technology() == ptFFF ?
|
||||
const FreqSettingsBundle& bundle_quick = printer_technology() == ptFFF ?
|
||||
m_freq_settings_fff : m_freq_settings_sla;
|
||||
|
||||
for (auto& it : bundle_quick) {
|
||||
@ -1173,10 +1181,94 @@ void ObjectList::load_part( ModelObject* model_object,
|
||||
|
||||
}
|
||||
|
||||
// Find volume transformation, so that the chained (instance_trafo * volume_trafo) will be as close to identity
|
||||
// as possible in least squares norm in regard to the 8 corners of bbox.
|
||||
// Bounding box is expected to be centered around zero in all axes.
|
||||
Geometry::Transformation volume_to_bed_transformation(const Geometry::Transformation &instance_transformation, const BoundingBoxf3 &bbox)
|
||||
{
|
||||
Geometry::Transformation out;
|
||||
|
||||
// Is the angle close to a multiple of 90 degrees?
|
||||
auto ninety_degrees = [](double a) {
|
||||
a = fmod(std::abs(a), 0.5 * PI);
|
||||
if (a > 0.25 * PI)
|
||||
a = 0.5 * PI - a;
|
||||
return a < 0.001;
|
||||
};
|
||||
if (instance_transformation.is_scaling_uniform()) {
|
||||
// No need to run the non-linear least squares fitting for uniform scaling.
|
||||
// Just set the inverse.
|
||||
out.set_from_transform(instance_transformation.get_matrix(true).inverse());
|
||||
}
|
||||
else if (ninety_degrees(instance_transformation.get_rotation().x()) && ninety_degrees(instance_transformation.get_rotation().y()) && ninety_degrees(instance_transformation.get_rotation().z()))
|
||||
{
|
||||
// Anisotropic scaling, rotation by multiples of ninety degrees.
|
||||
Eigen::Matrix3d instance_rotation_trafo =
|
||||
(Eigen::AngleAxisd(instance_transformation.get_rotation().z(), Vec3d::UnitZ()) *
|
||||
Eigen::AngleAxisd(instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
||||
Eigen::AngleAxisd(instance_transformation.get_rotation().x(), Vec3d::UnitX())).toRotationMatrix();
|
||||
Eigen::Matrix3d volume_rotation_trafo =
|
||||
(Eigen::AngleAxisd(-instance_transformation.get_rotation().x(), Vec3d::UnitX()) *
|
||||
Eigen::AngleAxisd(-instance_transformation.get_rotation().y(), Vec3d::UnitY()) *
|
||||
Eigen::AngleAxisd(-instance_transformation.get_rotation().z(), Vec3d::UnitZ())).toRotationMatrix();
|
||||
|
||||
// 8 corners of the bounding box.
|
||||
auto pts = Eigen::MatrixXd(8, 3);
|
||||
pts(0, 0) = bbox.min.x(); pts(0, 1) = bbox.min.y(); pts(0, 2) = bbox.min.z();
|
||||
pts(1, 0) = bbox.min.x(); pts(1, 1) = bbox.min.y(); pts(1, 2) = bbox.max.z();
|
||||
pts(2, 0) = bbox.min.x(); pts(2, 1) = bbox.max.y(); pts(2, 2) = bbox.min.z();
|
||||
pts(3, 0) = bbox.min.x(); pts(3, 1) = bbox.max.y(); pts(3, 2) = bbox.max.z();
|
||||
pts(4, 0) = bbox.max.x(); pts(4, 1) = bbox.min.y(); pts(4, 2) = bbox.min.z();
|
||||
pts(5, 0) = bbox.max.x(); pts(5, 1) = bbox.min.y(); pts(5, 2) = bbox.max.z();
|
||||
pts(6, 0) = bbox.max.x(); pts(6, 1) = bbox.max.y(); pts(6, 2) = bbox.min.z();
|
||||
pts(7, 0) = bbox.max.x(); pts(7, 1) = bbox.max.y(); pts(7, 2) = bbox.max.z();
|
||||
|
||||
// Corners of the bounding box transformed into the modifier mesh coordinate space, with inverse rotation applied to the modifier.
|
||||
auto qs = pts *
|
||||
(instance_rotation_trafo *
|
||||
Eigen::Scaling(instance_transformation.get_scaling_factor().cwiseProduct(instance_transformation.get_mirror())) *
|
||||
volume_rotation_trafo).inverse().transpose();
|
||||
// Fill in scaling based on least squares fitting of the bounding box corners.
|
||||
Vec3d scale;
|
||||
for (int i = 0; i < 3; ++ i)
|
||||
scale(i) = pts.col(i).dot(qs.col(i)) / pts.col(i).dot(pts.col(i));
|
||||
|
||||
out.set_rotation(Geometry::extract_euler_angles(volume_rotation_trafo));
|
||||
out.set_scaling_factor(Vec3d(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2))));
|
||||
out.set_mirror(Vec3d(scale(0) > 0 ? 1. : -1, scale(1) > 0 ? 1. : -1, scale(2) > 0 ? 1. : -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// General anisotropic scaling, general rotation.
|
||||
// Keep the modifier mesh in the instance coordinate system, so the modifier mesh will not be aligned with the world.
|
||||
// Scale it to get the required size.
|
||||
out.set_scaling_factor(instance_transformation.get_scaling_factor().cwiseInverse());
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void ObjectList::load_generic_subobject(const std::string& type_name, const ModelVolumeType type)
|
||||
{
|
||||
const auto obj_idx = get_selected_obj_idx();
|
||||
if (obj_idx < 0) return;
|
||||
if (obj_idx < 0)
|
||||
return;
|
||||
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
assert(obj_idx == selection.get_object_idx());
|
||||
|
||||
/** Any changes of the Object's composition is duplicated for all Object's Instances
|
||||
* So, It's enough to take a bounding box of a first selected Instance and calculate Part(generic_subobject) position
|
||||
*/
|
||||
int instance_idx = *selection.get_instance_idxs().begin();
|
||||
assert(instance_idx != -1);
|
||||
if (instance_idx == -1)
|
||||
return;
|
||||
|
||||
// Selected object
|
||||
ModelObject &model_object = *(*m_objects)[obj_idx];
|
||||
// Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
|
||||
BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
|
||||
|
||||
const wxString name = _(L("Generic")) + "-" + _(type_name);
|
||||
TriangleMesh mesh;
|
||||
@ -1185,48 +1277,48 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
||||
const auto& sz = BoundingBoxf(bed_shape).size();
|
||||
const auto side = 0.1 * std::max(sz(0), sz(1));
|
||||
|
||||
if (type_name == "Box") {
|
||||
if (type_name == "Box")
|
||||
// Sitting on the print bed, left front front corner at (0, 0).
|
||||
mesh = make_cube(side, side, side);
|
||||
// box sets the base coordinate at 0, 0, move to center of plate
|
||||
mesh.translate(-side * 0.5, -side * 0.5, 0);
|
||||
}
|
||||
else if (type_name == "Cylinder")
|
||||
mesh = make_cylinder(0.5*side, side);
|
||||
// Centered around 0, sitting on the print bed.
|
||||
// The cylinder has the same volume as the box above.
|
||||
mesh = make_cylinder(0.564 * side, side);
|
||||
else if (type_name == "Sphere")
|
||||
mesh = make_sphere(0.5*side, PI/18);
|
||||
else if (type_name == "Slab") {
|
||||
const auto& size = (*m_objects)[obj_idx]->bounding_box().size();
|
||||
mesh = make_cube(size(0)*1.5, size(1)*1.5, size(2)*0.5);
|
||||
// box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z
|
||||
mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, 0);
|
||||
}
|
||||
// Centered around 0, half the sphere below the print bed, half above.
|
||||
// The sphere has the same volume as the box above.
|
||||
mesh = make_sphere(0.62 * side, PI / 18);
|
||||
else if (type_name == "Slab")
|
||||
// Sitting on the print bed, left front front corner at (0, 0).
|
||||
mesh = make_cube(instance_bb.size().x()*1.5, instance_bb.size().y()*1.5, instance_bb.size().z()*0.5);
|
||||
mesh.repair();
|
||||
|
||||
auto new_volume = (*m_objects)[obj_idx]->add_volume(mesh);
|
||||
// Mesh will be centered when loading.
|
||||
ModelVolume *new_volume = model_object.add_volume(std::move(mesh));
|
||||
new_volume->set_type(type);
|
||||
|
||||
#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
new_volume->set_offset(Vec3d(0.0, 0.0, (*m_objects)[obj_idx]->origin_translation(2) - mesh.stl.stats.min(2)));
|
||||
new_volume->set_offset(Vec3d(0.0, 0.0, model_object.origin_translation(2) - mesh.stl.stats.min(2)));
|
||||
#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
#if !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
new_volume->center_geometry();
|
||||
#endif // !ENABLE_VOLUMES_CENTERING_FIXES
|
||||
|
||||
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
int instance_idx = selection.get_instance_idx();
|
||||
if (instance_idx != -1)
|
||||
{
|
||||
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const Transform3d& inst_m = v->get_instance_transformation().get_matrix(true);
|
||||
TriangleMesh vol_mesh(mesh);
|
||||
vol_mesh.transform(inst_m);
|
||||
Vec3d vol_shift = -vol_mesh.bounding_box().center();
|
||||
vol_mesh.translate((float)vol_shift(0), (float)vol_shift(1), (float)vol_shift(2));
|
||||
Vec3d world_mesh_bb_size = vol_mesh.bounding_box().size();
|
||||
BoundingBoxf3 inst_bb = (*m_objects)[obj_idx]->instance_bounding_box(instance_idx);
|
||||
Vec3d world_target = Vec3d(inst_bb.max(0), inst_bb.min(1), inst_bb.min(2)) + 0.5 * world_mesh_bb_size;
|
||||
new_volume->set_offset(inst_m.inverse() * (world_target - v->get_instance_offset()));
|
||||
// Transform the new modifier to be aligned with the print bed.
|
||||
const BoundingBoxf3 mesh_bb = new_volume->mesh.bounding_box();
|
||||
new_volume->set_transformation(volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
|
||||
// Set the modifier position.
|
||||
auto offset = (type_name == "Slab") ?
|
||||
// Slab: Lift to print bed
|
||||
Vec3d(0., 0., 0.5 * mesh_bb.size().z() + instance_bb.min.z() - v->get_instance_offset().z()) :
|
||||
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
|
||||
Vec3d(instance_bb.max(0), instance_bb.min(1), instance_bb.min(2)) + 0.5 * mesh_bb.size() - v->get_instance_offset();
|
||||
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
|
||||
}
|
||||
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
|
||||
|
||||
@ -2048,14 +2140,28 @@ bool ObjectList::has_multi_part_objects()
|
||||
|
||||
void ObjectList::update_settings_items()
|
||||
{
|
||||
m_prevent_canvas_selection_update = true;
|
||||
wxDataViewItemArray sel;
|
||||
GetSelections(sel); // stash selection
|
||||
|
||||
wxDataViewItemArray items;
|
||||
m_objects_model->GetChildren(wxDataViewItem(0), items);
|
||||
|
||||
for (auto& item : items) {
|
||||
const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item);
|
||||
select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item));
|
||||
|
||||
// If settings item was deleted from the list,
|
||||
// it's need to be deleted from selection array, if it was there
|
||||
if (settings_item != m_objects_model->GetSettingsItem(item) &&
|
||||
sel.Index(settings_item) != wxNOT_FOUND) {
|
||||
sel.Remove(settings_item);
|
||||
}
|
||||
}
|
||||
UnselectAll();
|
||||
|
||||
// restore selection:
|
||||
SetSelections(sel);
|
||||
m_prevent_canvas_selection_update = false;
|
||||
}
|
||||
|
||||
void ObjectList::update_object_menu()
|
||||
|
@ -127,6 +127,10 @@ class ObjectList : public wxDataViewCtrl
|
||||
bool m_prevent_update_extruder_in_config = false; // We use this flag to avoid updating of the extruder value in config
|
||||
// during updating of the extruder count.
|
||||
|
||||
bool m_prevent_canvas_selection_update = false; // This flag prevents changing selection on the canvas. See function
|
||||
// update_settings_items - updating canvas selection is undesirable,
|
||||
// because it would turn off the gizmos (mainly a problem for the SLA gizmo)
|
||||
|
||||
bool m_parts_changed = false;
|
||||
bool m_part_settings_changed = false;
|
||||
|
||||
|
@ -361,16 +361,21 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
const GLCanvas3D::Selection& selection = canvas->get_selection();
|
||||
|
||||
Vec3d delta_rotation = rotation - m_cache.rotation;
|
||||
GLCanvas3D::TransformationType transformation_type(GLCanvas3D::TransformationType::World_Relative_Joint);
|
||||
if (selection.is_single_full_instance() || selection.requires_local_axes())
|
||||
transformation_type.set_independent();
|
||||
if (selection.is_single_full_instance()) {
|
||||
//FIXME GLCanvas3D::Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
|
||||
// transformation_type.set_absolute();
|
||||
transformation_type.set_local();
|
||||
}
|
||||
|
||||
Vec3d rad_rotation;
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
rad_rotation(i) = Geometry::deg2rad(delta_rotation(i));
|
||||
}
|
||||
rad_rotation(i) = Geometry::deg2rad((transformation_type.absolute()) ? rotation(i) : rotation(i) - m_cache.rotation(i));
|
||||
|
||||
canvas->get_selection().start_dragging();
|
||||
canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance() || selection.requires_local_axes());
|
||||
canvas->get_selection().rotate(rad_rotation, transformation_type);
|
||||
canvas->do_rotate();
|
||||
|
||||
m_cache.rotation = rotation;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define slic3r_GUI_ObjectSettings_hpp_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <wx/panel.h>
|
||||
|
||||
class wxBoxSizer;
|
||||
|
@ -137,13 +137,11 @@ void View3D::mirror_selection(Axis axis)
|
||||
m_canvas->mirror_selection(axis);
|
||||
}
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
void View3D::update_toolbar_items_visibility()
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
m_canvas->update_toolbar_items_visibility();
|
||||
}
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
|
||||
void View3D::enable_toolbar_item(const std::string& name, bool enable)
|
||||
{
|
||||
@ -191,7 +189,8 @@ void View3D::reload_scene(bool refresh_immediately, bool force_full_scene_refres
|
||||
void View3D::render()
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
m_canvas->render();
|
||||
//m_canvas->render();
|
||||
m_canvas->set_as_dirty();
|
||||
}
|
||||
|
||||
Preview::Preview(wxWindow* parent, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process_func)
|
||||
@ -418,11 +417,14 @@ void Preview::load_print()
|
||||
load_print_as_sla();
|
||||
}
|
||||
|
||||
void Preview::reload_print(bool force)
|
||||
void Preview::reload_print(bool force, bool keep_volumes)
|
||||
{
|
||||
m_canvas->reset_volumes();
|
||||
m_canvas->reset_legend_texture();
|
||||
m_loaded = false;
|
||||
if (!keep_volumes)
|
||||
{
|
||||
m_canvas->reset_volumes();
|
||||
m_canvas->reset_legend_texture();
|
||||
m_loaded = false;
|
||||
}
|
||||
|
||||
if (!IsShown() && !force)
|
||||
return;
|
||||
@ -563,8 +565,12 @@ void Preview::create_double_slider()
|
||||
auto& config = wxGetApp().preset_bundle->project_config;
|
||||
((config.option<ConfigOptionFloats>("colorprint_heights"))->values) = (m_slider->GetTicksValues());
|
||||
m_schedule_background_process();
|
||||
bool color_print = !config.option<ConfigOptionFloats>("colorprint_heights")->values.empty();
|
||||
int type = m_choice_view_type->FindString(color_print ? _(L("Color Print")) : _(L("Feature type")) );
|
||||
|
||||
const wxString& choise = !config.option<ConfigOptionFloats>("colorprint_heights")->values.empty() ? _(L("Color Print")) :
|
||||
config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values.size() > 1 ?
|
||||
_(L("Tool")) : _(L("Feature type"));
|
||||
|
||||
int type = m_choice_view_type->FindString(choise);
|
||||
if (m_choice_view_type->GetSelection() != type) {
|
||||
m_choice_view_type->SetSelection(type);
|
||||
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
|
||||
@ -637,12 +643,13 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool for
|
||||
|
||||
const auto& config = wxGetApp().preset_bundle->project_config;
|
||||
const std::vector<double> &ticks_from_config = (config.option<ConfigOptionFloats>("colorprint_heights"))->values;
|
||||
|
||||
m_slider->SetTicksValues(ticks_from_config);
|
||||
|
||||
bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF);
|
||||
if (color_print_enable) {
|
||||
const auto& config = wxGetApp().preset_bundle->full_config();
|
||||
if (config.opt<ConfigOptionFloats>("nozzle_diameter")->values.size() > 1)
|
||||
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
if (cfg.opt<ConfigOptionFloats>("nozzle_diameter")->values.size() > 1)
|
||||
color_print_enable = false;
|
||||
}
|
||||
m_slider->EnableTickManipulation(color_print_enable);
|
||||
|
@ -60,9 +60,7 @@ public:
|
||||
void delete_selected();
|
||||
void mirror_selection(Axis axis);
|
||||
|
||||
#if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
void update_toolbar_items_visibility();
|
||||
#endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
|
||||
void enable_toolbar_item(const std::string& name, bool enable);
|
||||
int check_volumes_outside_state() const;
|
||||
|
||||
@ -129,7 +127,7 @@ public:
|
||||
void set_drop_target(wxDropTarget* target);
|
||||
|
||||
void load_print();
|
||||
void reload_print(bool force = false);
|
||||
void reload_print(bool force = false, bool keep_volumes = false);
|
||||
void refresh_print();
|
||||
|
||||
private:
|
||||
|
@ -239,32 +239,44 @@ bool ImGuiWrapper::checkbox(const wxString &label, bool &value)
|
||||
return ImGui::Checkbox(label_utf8.c_str(), &value);
|
||||
}
|
||||
|
||||
void ImGuiWrapper::text(const wxString &label)
|
||||
void ImGuiWrapper::text(const char *label)
|
||||
{
|
||||
auto label_utf8 = into_u8(label);
|
||||
ImGui::Text(label_utf8.c_str(), NULL);
|
||||
ImGui::Text(label, NULL);
|
||||
}
|
||||
|
||||
|
||||
bool ImGuiWrapper::combo(const wxString& label, const std::vector<wxString>& options, wxString& selection)
|
||||
void ImGuiWrapper::text(const std::string &label)
|
||||
{
|
||||
std::string selection_u8 = into_u8(selection);
|
||||
this->text(label.c_str());
|
||||
}
|
||||
|
||||
void ImGuiWrapper::text(const wxString &label)
|
||||
{
|
||||
this->text(into_u8(label).c_str());
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection)
|
||||
{
|
||||
// this is to force the label to the left of the widget:
|
||||
text(label);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginCombo("", selection_u8.c_str())) {
|
||||
for (const wxString& option : options) {
|
||||
std::string option_u8 = into_u8(option);
|
||||
bool is_selected = (selection_u8.empty()) ? false : (option_u8 == selection_u8);
|
||||
if (ImGui::Selectable(option_u8.c_str(), is_selected))
|
||||
selection = option_u8;
|
||||
|
||||
int selection_out = -1;
|
||||
bool res = false;
|
||||
|
||||
const char *selection_str = selection < options.size() ? options[selection].c_str() : "";
|
||||
if (ImGui::BeginCombo("", selection_str)) {
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (ImGui::Selectable(options[i].c_str(), i == selection)) {
|
||||
selection_out = i;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
return true;
|
||||
res = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
selection = selection_out;
|
||||
return res;
|
||||
}
|
||||
|
||||
void ImGuiWrapper::disabled_begin(bool disabled)
|
||||
@ -405,8 +417,8 @@ void ImGuiWrapper::init_style()
|
||||
|
||||
static const unsigned COL_GREY_DARK = 0x444444ff;
|
||||
static const unsigned COL_GREY_LIGHT = 0x666666ff;
|
||||
static const unsigned COL_ORANGE_DARK = 0xba5418ff;
|
||||
static const unsigned COL_ORANGE_LIGHT = 0xff6f22ff;
|
||||
static const unsigned COL_ORANGE_DARK = 0xc16737ff;
|
||||
static const unsigned COL_ORANGE_LIGHT = 0xff7d38ff;
|
||||
|
||||
// Generics
|
||||
set_color(ImGuiCol_TitleBgActive, COL_ORANGE_DARK);
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
bool update_mouse_data(wxMouseEvent &evt);
|
||||
bool update_key_data(wxKeyEvent &evt);
|
||||
|
||||
float get_style_scaling() const { return m_style_scaling; }
|
||||
|
||||
void new_frame();
|
||||
void render();
|
||||
|
||||
@ -57,8 +59,10 @@ public:
|
||||
bool input_double(const std::string &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);
|
||||
void text(const std::string &label);
|
||||
void text(const wxString &label);
|
||||
bool combo(const wxString& label, const std::vector<wxString>& options, wxString& current_selection);
|
||||
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
|
||||
|
||||
void disabled_begin(bool disabled);
|
||||
void disabled_end();
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|