1st installment of svg icons for toolbars and gizmos
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 |
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 |
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 |
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 |
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 |
@ -163,7 +163,7 @@ public:
|
||||
{
|
||||
dir_ = OptDir::MIN;
|
||||
return static_cast<Subclass*>(this)->template optimize<Func, Args...>(
|
||||
objectfunction, initvals, Bound<Args>()... );
|
||||
forward<Func>(objectfunction), initvals, Bound<Args>()... );
|
||||
}
|
||||
|
||||
template<class...Args, class Func>
|
||||
@ -171,7 +171,7 @@ public:
|
||||
{
|
||||
dir_ = OptDir::MIN;
|
||||
return static_cast<Subclass*>(this)->template optimize<Func, Args...>(
|
||||
objectfunction,
|
||||
forward<Func>(objectfunction),
|
||||
Input<Args...>(),
|
||||
Bound<Args>()... );
|
||||
}
|
||||
@ -184,7 +184,7 @@ public:
|
||||
{
|
||||
dir_ = OptDir::MAX;
|
||||
return static_cast<Subclass*>(this)->template optimize<Func, Args...>(
|
||||
objectfunction, initvals, bounds... );
|
||||
forward<Func>(objectfunction), initvals, bounds... );
|
||||
}
|
||||
|
||||
template<class Func, class...Args>
|
||||
@ -193,7 +193,7 @@ public:
|
||||
{
|
||||
dir_ = OptDir::MAX;
|
||||
return static_cast<Subclass*>(this)->template optimize<Func, Args...>(
|
||||
objectfunction, initvals, Bound<Args>()... );
|
||||
forward<Func>(objectfunction), initvals, Bound<Args>()... );
|
||||
}
|
||||
|
||||
template<class...Args, class Func>
|
||||
@ -201,7 +201,7 @@ public:
|
||||
{
|
||||
dir_ = OptDir::MAX;
|
||||
return static_cast<Subclass*>(this)->template optimize<Func, Args...>(
|
||||
objectfunction,
|
||||
forward<Func>(objectfunction),
|
||||
Input<Args...>(),
|
||||
Bound<Args>()... );
|
||||
}
|
||||
|
@ -2730,6 +2730,17 @@ void PrintConfigDef::init_sla_params()
|
||||
def->cli = "";
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(1.0);
|
||||
|
||||
def = this->add("pad_wall_slope", coFloat);
|
||||
def->label = L("Pad wall slope");
|
||||
def->category = L("Pad");
|
||||
def->tooltip = L("The slope of the pad wall relative to the bed plane. "
|
||||
"90 degrees means straight walls.");
|
||||
def->sidetext = L("degrees");
|
||||
def->cli = "";
|
||||
def->min = 45;
|
||||
def->max = 90;
|
||||
def->default_value = new ConfigOptionFloat(45.0);
|
||||
}
|
||||
|
||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||
|
@ -1028,6 +1028,9 @@ public:
|
||||
// The smoothing radius of the pad edges
|
||||
ConfigOptionFloat pad_edge_radius /*= 1*/;
|
||||
|
||||
// The slope of the pad wall...
|
||||
ConfigOptionFloat pad_wall_slope;
|
||||
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
@ -1053,6 +1056,7 @@ protected:
|
||||
OPT_PTR(pad_wall_height);
|
||||
OPT_PTR(pad_max_merge_distance);
|
||||
OPT_PTR(pad_edge_radius);
|
||||
OPT_PTR(pad_wall_slope);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -601,8 +601,8 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
const double thickness = cfg.min_wall_thickness_mm;
|
||||
const double wingheight = cfg.min_wall_height_mm;
|
||||
const double fullheight = wingheight + thickness;
|
||||
const double tilt = PI/4;
|
||||
const double wingdist = wingheight / std::tan(tilt);
|
||||
const double slope = cfg.wall_slope;
|
||||
const double wingdist = wingheight / std::tan(slope);
|
||||
|
||||
// scaled values
|
||||
const coord_t s_thickness = mm(thickness);
|
||||
@ -627,15 +627,22 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
auto outer_base = concaveh;
|
||||
outer_base.holes.clear();
|
||||
offset(outer_base, s_safety_dist + s_wingdist + s_thickness);
|
||||
auto inner_base = outer_base;
|
||||
offset(inner_base, -(s_thickness + s_wingdist));
|
||||
|
||||
|
||||
ExPolygon bottom_poly = outer_base;
|
||||
bottom_poly.holes.clear();
|
||||
if(s_wingdist > 0) offset(bottom_poly, -s_wingdist);
|
||||
|
||||
// Punching a hole in the top plate for the cavity
|
||||
ExPolygon top_poly;
|
||||
ExPolygon middle_base;
|
||||
ExPolygon inner_base;
|
||||
top_poly.contour = outer_base.contour;
|
||||
|
||||
if(wingheight > 0) {
|
||||
inner_base = outer_base;
|
||||
offset(inner_base, -(s_thickness + s_wingdist + s_eradius));
|
||||
|
||||
middle_base = outer_base;
|
||||
offset(middle_base, -s_thickness);
|
||||
top_poly.holes.emplace_back(middle_base.contour);
|
||||
@ -682,10 +689,10 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
thrcl,
|
||||
ob, wh));
|
||||
|
||||
// Now that we have the rounded edge connencting the top plate with
|
||||
// Now that we have the rounded edge connecting the top plate with
|
||||
// the outer side walls, we can generate and merge the sidewall geometry
|
||||
pool.merge(walls(ob.contour, inner_base.contour, wh, -fullheight,
|
||||
(s_thickness + s_wingdist) * SCALING_FACTOR, thrcl));
|
||||
pool.merge(walls(ob.contour, bottom_poly.contour, wh, -fullheight,
|
||||
wingdist, thrcl));
|
||||
|
||||
if(wingheight > 0) {
|
||||
// Generate the smoothed edge geometry
|
||||
@ -700,14 +707,14 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
// Next is the cavity walls connecting to the top plate's
|
||||
// artificially created hole.
|
||||
pool.merge(walls(inner_base.contour, ob.contour, -wingheight,
|
||||
wh, -s_safety_dist * SCALING_FACTOR, thrcl));
|
||||
wh, -wingdist, thrcl));
|
||||
}
|
||||
|
||||
// Now we need to triangulate the top and bottom plates as well as the
|
||||
// cavity bottom plate which is the same as the bottom plate but it is
|
||||
// elevated by the thickness.
|
||||
pool.merge(triangulate_expolygon_3d(top_poly));
|
||||
pool.merge(triangulate_expolygon_3d(inner_base, -fullheight, true));
|
||||
pool.merge(triangulate_expolygon_3d(bottom_poly, -fullheight, true));
|
||||
|
||||
if(wingheight > 0)
|
||||
pool.merge(triangulate_expolygon_3d(inner_base, -wingheight));
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -27,15 +28,17 @@ struct PoolConfig {
|
||||
double min_wall_height_mm = 5;
|
||||
double max_merge_distance_mm = 50;
|
||||
double edge_radius_mm = 1;
|
||||
double wall_slope = std::atan(1.0); // Universal constant for Pi/4
|
||||
|
||||
ThrowOnCancel throw_on_cancel = [](){};
|
||||
|
||||
inline PoolConfig() {}
|
||||
inline PoolConfig(double wt, double wh, double md, double er):
|
||||
inline PoolConfig(double wt, double wh, double md, double er, double slope):
|
||||
min_wall_thickness_mm(wt),
|
||||
min_wall_height_mm(wh),
|
||||
max_merge_distance_mm(md),
|
||||
edge_radius_mm(er) {}
|
||||
edge_radius_mm(er),
|
||||
wall_slope(slope) {}
|
||||
};
|
||||
|
||||
/// Calculate the pool for the mesh for SLA printing
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
#include <libslic3r/Model.hpp>
|
||||
|
||||
#include <libnest2d/optimizers/nlopt/simplex.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
@ -594,7 +595,7 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
||||
double r_back,
|
||||
double width,
|
||||
const EigenMesh3D& m,
|
||||
unsigned samples = 8,
|
||||
unsigned samples = 16,
|
||||
double safety_distance = 0.001)
|
||||
{
|
||||
// method based on:
|
||||
@ -620,9 +621,20 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
||||
std::vector<double> phis(samples);
|
||||
for(size_t i = 0; i < phis.size(); ++i) phis[i] = i*2*PI/phis.size();
|
||||
|
||||
a(Z) = -(v(X)*a(X) + v(Y)*a(Y)) / v(Z);
|
||||
|
||||
b = a.cross(v);
|
||||
// We have to address the case when the direction vector v (same as dir)
|
||||
// is coincident with one of the world axes. In this case two of its
|
||||
// components will be completely zero and one is 1.0. Our method becomes
|
||||
// dangerous here due to division with zero. Instead, vector 'a' can be an
|
||||
// element-wise rotated version of 'v'
|
||||
auto chk1 = [] (double val) { return std::abs(std::abs(val) - 1) < 1e-20; };
|
||||
if(chk1(v(X)) || chk1(v(Y)) || chk1(v(Z))) {
|
||||
a = {v(Z), v(X), v(Y)};
|
||||
b = {v(Y), v(Z), v(X)};
|
||||
}
|
||||
else {
|
||||
a(Z) = -(v(Y)*a(Y)) / v(Z); a.normalize();
|
||||
b = a.cross(v);
|
||||
}
|
||||
|
||||
// Now a and b vectors are perpendicular to v and to each other. Together
|
||||
// they define the plane where we have to iterate with the given angles
|
||||
@ -647,18 +659,14 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
||||
s(Z) + rpscos * a(Z) + rpssin * b(Z));
|
||||
|
||||
// Point ps is not on mesh but can be inside or outside as well. This
|
||||
// would cause many problems with ray-casting. So we query the closest
|
||||
// point on the mesh to this.
|
||||
// auto psq = m.signed_distance(ps);
|
||||
// would cause many problems with ray-casting. To detect the position we
|
||||
// will use the ray-casting result (which has an is_inside predicate).
|
||||
|
||||
// This is the point on the circle on the back sphere
|
||||
Vec3d p(c(X) + rpbcos * a(X) + rpbsin * b(X),
|
||||
c(Y) + rpbcos * a(Y) + rpbsin * b(Y),
|
||||
c(Z) + rpbcos * a(Z) + rpbsin * b(Z));
|
||||
|
||||
// Vec3d n = (p - psq.point_on_mesh()).normalized();
|
||||
// phi = m.query_ray_hit(psq.point_on_mesh() + sd*n, n);
|
||||
|
||||
Vec3d n = (p - ps).normalized();
|
||||
auto hr = m.query_ray_hit(ps + sd*n, n);
|
||||
|
||||
@ -693,8 +701,18 @@ double bridge_mesh_intersect(const Vec3d& s,
|
||||
Vec3d a(0, 1, 0), b;
|
||||
const double& sd = safety_distance;
|
||||
|
||||
a(Z) = -(dir(X)*a(X) + dir(Y)*a(Y)) / dir(Z);
|
||||
b = a.cross(dir);
|
||||
// INFO: for explanation of the method used here, see the previous method's
|
||||
// comments.
|
||||
|
||||
auto chk1 = [] (double val) { return std::abs(std::abs(val) - 1) < 1e-20; };
|
||||
if(chk1(dir(X)) || chk1(dir(Y)) || chk1(dir(Z))) {
|
||||
a = {dir(Z), dir(X), dir(Y)};
|
||||
b = {dir(Y), dir(Z), dir(X)};
|
||||
}
|
||||
else {
|
||||
a(Z) = -(dir(Y)*a(Y)) / dir(Z); a.normalize();
|
||||
b = a.cross(dir);
|
||||
}
|
||||
|
||||
// circle portions
|
||||
std::vector<double> phis(samples);
|
||||
@ -1156,16 +1174,16 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
//...
|
||||
};
|
||||
|
||||
// t-hrow i-f c-ance-l-ed: It will be called many times so a shorthand will
|
||||
// throw if canceled: It will be called many times so a shorthand will
|
||||
// come in handy.
|
||||
auto& tifcl = ctl.cancelfn;
|
||||
auto& thr = ctl.cancelfn;
|
||||
|
||||
// Filtering step: here we will discard inappropriate support points and
|
||||
// decide the future of the appropriate ones. We will check if a pinhead
|
||||
// is applicable and adjust its angle at each support point.
|
||||
// We will also merge the support points that are just too close and can be
|
||||
// considered as one.
|
||||
auto filterfn = [tifcl] (
|
||||
auto filterfn = [thr] (
|
||||
const SupportConfig& cfg,
|
||||
const PointSet& points,
|
||||
const EigenMesh3D& mesh,
|
||||
@ -1179,9 +1197,9 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// first one
|
||||
auto aliases =
|
||||
cluster(points,
|
||||
[tifcl](const SpatElement& p, const SpatElement& se)
|
||||
[thr](const SpatElement& p, const SpatElement& se)
|
||||
{
|
||||
tifcl();
|
||||
thr();
|
||||
return distance(p.first, se.first) < D_SP;
|
||||
}, 2);
|
||||
|
||||
@ -1192,10 +1210,10 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
filt_pts.row(count++) = points.row(a.front());
|
||||
}
|
||||
|
||||
tifcl();
|
||||
thr();
|
||||
|
||||
// calculate the normals to the triangles belonging to filtered points
|
||||
auto nmls = sla::normals(filt_pts, mesh, cfg.head_front_radius_mm, tifcl);
|
||||
auto nmls = sla::normals(filt_pts, mesh, cfg.head_front_radius_mm, thr);
|
||||
|
||||
head_norm.resize(count, 3);
|
||||
head_pos.resize(count, 3);
|
||||
@ -1207,9 +1225,15 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// not be enough space for the pinhead. Filtering is applied for
|
||||
// these reasons.
|
||||
|
||||
using libnest2d::opt::bound;
|
||||
using libnest2d::opt::initvals;
|
||||
using libnest2d::opt::SimplexOptimizer;
|
||||
using libnest2d::opt::StopCriteria;
|
||||
static const unsigned MAX_TRIES = 100;
|
||||
|
||||
int pcount = 0, hlcount = 0;
|
||||
for(int i = 0; i < count; i++) {
|
||||
tifcl();
|
||||
thr();
|
||||
auto n = nmls.row(i);
|
||||
|
||||
// for all normals we generate the spherical coordinates and
|
||||
@ -1230,32 +1254,67 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// We saturate the polar angle to 3pi/4
|
||||
polar = std::max(polar, 3*PI / 4);
|
||||
|
||||
// Reassemble the now corrected normal
|
||||
Vec3d nn(std::cos(azimuth) * std::sin(polar),
|
||||
std::sin(azimuth) * std::sin(polar),
|
||||
std::cos(polar));
|
||||
|
||||
nn.normalize();
|
||||
|
||||
// save the head (pinpoint) position
|
||||
Vec3d hp = filt_pts.row(i);
|
||||
|
||||
// the full width of the head
|
||||
double w = cfg.head_width_mm +
|
||||
cfg.head_back_radius_mm +
|
||||
2*cfg.head_front_radius_mm;
|
||||
|
||||
// We should shoot a ray in the direction of the pinhead and
|
||||
// see if there is enough space for it
|
||||
double t = pinhead_mesh_intersect(
|
||||
hp, // touching point
|
||||
nn,
|
||||
cfg.head_front_radius_mm, // approx the radius
|
||||
cfg.head_back_radius_mm,
|
||||
w,
|
||||
mesh);
|
||||
// Reassemble the now corrected normal
|
||||
auto nn = Vec3d(std::cos(azimuth) * std::sin(polar),
|
||||
std::sin(azimuth) * std::sin(polar),
|
||||
std::cos(polar)).normalized();
|
||||
|
||||
if(t > w || std::isinf(t)) {
|
||||
// check available distance
|
||||
double t = pinhead_mesh_intersect(
|
||||
hp, // touching point
|
||||
nn, // normal
|
||||
cfg.head_front_radius_mm,
|
||||
cfg.head_back_radius_mm,
|
||||
w,
|
||||
mesh);
|
||||
|
||||
if(t <= w) {
|
||||
// Let's try to optimize this angle, there might be a viable
|
||||
// normal that doesn't collide with the model geometry and
|
||||
// its very close to the default.
|
||||
|
||||
StopCriteria stc;
|
||||
stc.max_iterations = MAX_TRIES;
|
||||
stc.relative_score_difference = 1e-3;
|
||||
stc.stop_score = w; // space greater than w is enough
|
||||
SimplexOptimizer solver(stc);
|
||||
|
||||
auto oresult = solver.optimize_max(
|
||||
[&mesh, &cfg, w, hp](double plr, double azm)
|
||||
{
|
||||
auto n = Vec3d(std::cos(azm) * std::sin(plr),
|
||||
std::sin(azm) * std::sin(plr),
|
||||
std::cos(plr)).normalized();
|
||||
|
||||
double score = pinhead_mesh_intersect(
|
||||
hp, n,
|
||||
cfg.head_front_radius_mm,
|
||||
cfg.head_back_radius_mm,
|
||||
w,
|
||||
mesh);
|
||||
return score;
|
||||
},
|
||||
initvals(polar, azimuth), // let's start with what we have
|
||||
bound(3*PI/4, PI), // Must not exceed the tilt limit
|
||||
bound(-PI, PI) // azimuth can be a full range search
|
||||
);
|
||||
|
||||
t = oresult.score;
|
||||
polar = std::get<0>(oresult.optimum);
|
||||
azimuth = std::get<1>(oresult.optimum);
|
||||
nn = Vec3d(std::cos(azimuth) * std::sin(polar),
|
||||
std::sin(azimuth) * std::sin(polar),
|
||||
std::cos(polar)).normalized();
|
||||
}
|
||||
|
||||
if(t > w) {
|
||||
head_pos.row(pcount) = hp;
|
||||
|
||||
// save the verified and corrected normal
|
||||
@ -1263,6 +1322,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
|
||||
++pcount;
|
||||
} else if( polar >= 3*PI/4 ) {
|
||||
|
||||
// Headless supports do not tilt like the headed ones so
|
||||
// the normal should point almost to the ground.
|
||||
headless_norm.row(hlcount) = nn;
|
||||
@ -1279,7 +1339,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
|
||||
// Pinhead creation: based on the filtering results, the Head objects will
|
||||
// be constructed (together with their triangle meshes).
|
||||
auto pinheadfn = [tifcl] (
|
||||
auto pinheadfn = [thr] (
|
||||
const SupportConfig& cfg,
|
||||
PointSet& head_pos,
|
||||
PointSet& nmls,
|
||||
@ -1292,7 +1352,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
/* ******************************************************** */
|
||||
|
||||
for (int i = 0; i < head_pos.rows(); ++i) {
|
||||
tifcl();
|
||||
thr();
|
||||
result.add_head(
|
||||
cfg.head_back_radius_mm,
|
||||
cfg.head_front_radius_mm,
|
||||
@ -1311,7 +1371,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// will process it. Also, the pillars will be grouped into clusters that can
|
||||
// be interconnected with bridges. Elements of these groups may or may not
|
||||
// be interconnected. Here we only run the clustering algorithm.
|
||||
auto classifyfn = [tifcl] (
|
||||
auto classifyfn = [thr] (
|
||||
const SupportConfig& cfg,
|
||||
const EigenMesh3D& mesh,
|
||||
PointSet& head_pos,
|
||||
@ -1320,7 +1380,8 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
std::vector<double>& gndheight,
|
||||
ClusteredPoints& ground_clusters,
|
||||
Result& result
|
||||
) {
|
||||
)
|
||||
{
|
||||
|
||||
/* ******************************************************** */
|
||||
/* Classification */
|
||||
@ -1331,11 +1392,11 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
gndidx.reserve(size_t(head_pos.rows()));
|
||||
nogndidx.reserve(size_t(head_pos.rows()));
|
||||
|
||||
// First we search decide which heads reach the ground and can be full
|
||||
// First we decide which heads reach the ground and can be full
|
||||
// pillars and which shall be connected to the model surface (or search
|
||||
// a suitable path around the surface that leads to the ground -- TODO)
|
||||
for(unsigned i = 0; i < head_pos.rows(); i++) {
|
||||
tifcl();
|
||||
thr();
|
||||
auto& head = result.head(i);
|
||||
|
||||
Vec3d dir(0, 0, -1);
|
||||
@ -1344,9 +1405,38 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
double t = std::numeric_limits<double>::infinity();
|
||||
double hw = head.width_mm;
|
||||
|
||||
|
||||
{
|
||||
// using libnest2d::opt::Method;
|
||||
// using libnest2d::opt::bound;
|
||||
// using libnest2d::opt::Optimizer;
|
||||
// using libnest2d::opt::TOptimizer;
|
||||
// using libnest2d::opt::StopCriteria;
|
||||
|
||||
// auto stopcond = [] () { return false; };
|
||||
// static const unsigned max_tries = 100;
|
||||
|
||||
// auto objfunc =
|
||||
// [&head](double polar, double azimuth, double width)
|
||||
// {
|
||||
// Vec3d nn(std::cos(azimuth) * std::sin(polar),
|
||||
// std::sin(azimuth) * std::sin(polar),
|
||||
// std::cos(polar));
|
||||
|
||||
|
||||
// };
|
||||
|
||||
// StopCriteria stc;
|
||||
// stc.max_iterations = max_tries;
|
||||
// stc.relative_score_difference = 1e-3;
|
||||
// stc.stop_condition = stopcond;
|
||||
// TOptimizer<Method::L_SIMPLEX> solver(stc);
|
||||
}
|
||||
|
||||
|
||||
// We will try to assign a pillar to all the pinheads. If a pillar
|
||||
// would pierce the model surface, we will try to adjust slightly
|
||||
// the head with so that the pillar can be deployed.
|
||||
// the head width so that the pillar can be deployed.
|
||||
while(!accept && head.width_mm > 0) {
|
||||
|
||||
Vec3d startpoint = head.junction_point();
|
||||
@ -1358,11 +1448,18 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
double tprec = ray_mesh_intersect(startpoint, dir, mesh);
|
||||
|
||||
if(std::isinf(tprec) && !std::isinf(t)) {
|
||||
// This is a damned case where the pillar melds into the
|
||||
// This is a damned case where the pillar melts into the
|
||||
// model but its center ray can reach the ground. We can
|
||||
// not route this to the ground nor to the model surface.
|
||||
head.width_mm = hw + (ri % 2? -1 : 1) * ri * head.r_back_mm;
|
||||
} else {
|
||||
if(!std::isinf(t) && !std::isinf(tprec) &&
|
||||
std::abs(tprec - t) > hw)
|
||||
{
|
||||
// In this case the head would scratch the model body
|
||||
BOOST_LOG_TRIVIAL(warning) << "Head scratch detected.";
|
||||
}
|
||||
|
||||
accept = true; t = tprec;
|
||||
|
||||
auto id = head.id;
|
||||
@ -1417,9 +1514,9 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
ground_clusters =
|
||||
cluster(
|
||||
gnd,
|
||||
[d_base, tifcl](const SpatElement& p, const SpatElement& s)
|
||||
[d_base, thr](const SpatElement& p, const SpatElement& s)
|
||||
{
|
||||
tifcl();
|
||||
thr();
|
||||
return distance(Vec2d(p.first(X), p.first(Y)),
|
||||
Vec2d(s.first(X), s.first(Y))) < d_base;
|
||||
}, 3); // max 3 heads to connect to one centroid
|
||||
@ -1492,7 +1589,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// a full pillar (ground connected). Some will connect to a nearby pillar
|
||||
// using a bridge. The max number of such side-heads for a central pillar
|
||||
// is limited to avoid bad weight distribution.
|
||||
auto routing_ground_fn = [gnd_head_pt, interconnect, tifcl](
|
||||
auto routing_ground_fn = [gnd_head_pt, interconnect, thr](
|
||||
const SupportConfig& cfg,
|
||||
const ClusteredPoints& gnd_clusters,
|
||||
const IndexSet& gndidx,
|
||||
@ -1508,7 +1605,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
cl_centroids.reserve(gnd_clusters.size());
|
||||
|
||||
SpatIndex pheadindex; // spatial index for the junctions
|
||||
for(auto& cl : gnd_clusters) { tifcl();
|
||||
for(auto& cl : gnd_clusters) { thr();
|
||||
// place all the centroid head positions into the index. We will
|
||||
// query for alternative pillar positions. If a sidehead cannot
|
||||
// connect to the cluster centroid, we have to search for another
|
||||
@ -1519,9 +1616,9 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
|
||||
// get the current cluster centroid
|
||||
long lcid = cluster_centroid(cl, gnd_head_pt,
|
||||
[tifcl](const Vec3d& p1, const Vec3d& p2)
|
||||
[thr](const Vec3d& p1, const Vec3d& p2)
|
||||
{
|
||||
tifcl();
|
||||
thr();
|
||||
return distance(Vec2d(p1(X), p1(Y)), Vec2d(p2(X), p2(Y)));
|
||||
});
|
||||
|
||||
@ -1542,7 +1639,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// sidepoints with the cluster centroid (which is a ground pillar)
|
||||
// or a nearby pillar if the centroid is unreachable.
|
||||
size_t ci = 0;
|
||||
for(auto cl : gnd_clusters) { tifcl();
|
||||
for(auto cl : gnd_clusters) { thr();
|
||||
|
||||
auto cidx = cl_centroids[ci];
|
||||
cl_centroids[ci++] = cl[cidx];
|
||||
@ -1566,12 +1663,12 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// is distributed more effectively on the pillar.
|
||||
|
||||
auto search_nearest =
|
||||
[&tifcl, &cfg, &result, &emesh, maxbridgelen, gndlvl, pradius]
|
||||
[&thr, &cfg, &result, &emesh, maxbridgelen, gndlvl, pradius]
|
||||
(SpatIndex& spindex, const Vec3d& jsh)
|
||||
{
|
||||
long nearest_id = -1;
|
||||
const double max_len = maxbridgelen / 2;
|
||||
while(nearest_id < 0 && !spindex.empty()) { tifcl();
|
||||
while(nearest_id < 0 && !spindex.empty()) { thr();
|
||||
// loop until a suitable head is not found
|
||||
// if there is a pillar closer than the cluster center
|
||||
// (this may happen as the clustering is not perfect)
|
||||
@ -1610,7 +1707,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
return nearest_id;
|
||||
};
|
||||
|
||||
for(auto c : cl) { tifcl();
|
||||
for(auto c : cl) { thr();
|
||||
auto& sidehead = result.head(gndidx[c]);
|
||||
sidehead.transform();
|
||||
|
||||
@ -1676,7 +1773,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
ClusterEl ring;
|
||||
|
||||
while(!rem.empty()) { // loop until all the points belong to some ring
|
||||
tifcl();
|
||||
thr();
|
||||
std::sort(rem.begin(), rem.end());
|
||||
|
||||
auto newring = pts_convex_hull(rem,
|
||||
@ -1688,7 +1785,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
if(!ring.empty()) {
|
||||
// inner ring is now in 'newring' and outer ring is in 'ring'
|
||||
SpatIndex innerring;
|
||||
for(unsigned i : newring) { tifcl();
|
||||
for(unsigned i : newring) { thr();
|
||||
const Pillar& pill = result.head_pillar(gndidx[i]);
|
||||
assert(pill.id >= 0);
|
||||
innerring.insert(pill.endpoint, unsigned(pill.id));
|
||||
@ -1697,7 +1794,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// For all pillars in the outer ring find the closest in the
|
||||
// inner ring and connect them. This will create the spider web
|
||||
// fashioned connections between pillars
|
||||
for(unsigned i : ring) { tifcl();
|
||||
for(unsigned i : ring) { thr();
|
||||
const Pillar& outerpill = result.head_pillar(gndidx[i]);
|
||||
auto res = innerring.nearest(outerpill.endpoint, 1);
|
||||
if(res.empty()) continue;
|
||||
@ -1723,7 +1820,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
next != ring.end();
|
||||
++it, ++next)
|
||||
{
|
||||
tifcl();
|
||||
thr();
|
||||
const Pillar& pillar = result.head_pillar(gndidx[*it]);
|
||||
const Pillar& nextpillar = result.head_pillar(gndidx[*next]);
|
||||
interconnect(pillar, nextpillar, emesh, result);
|
||||
@ -1738,19 +1835,19 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
}
|
||||
};
|
||||
|
||||
// Step: routing the pinheads that are would connect to the model surface
|
||||
// Step: routing the pinheads that would connect to the model surface
|
||||
// along the Z axis downwards. For now these will actually be connected with
|
||||
// the model surface with a flipped pinhead. In the future here we could use
|
||||
// some smart algorithms to search for a safe path to the ground or to a
|
||||
// nearby pillar that can hold the supported weight.
|
||||
auto routing_nongnd_fn = [tifcl](
|
||||
auto routing_nongnd_fn = [thr](
|
||||
const SupportConfig& cfg,
|
||||
const std::vector<double>& gndheight,
|
||||
const IndexSet& nogndidx,
|
||||
Result& result)
|
||||
{
|
||||
// TODO: connect these to the ground pillars if possible
|
||||
for(auto idx : nogndidx) { tifcl();
|
||||
for(auto idx : nogndidx) { thr();
|
||||
double gh = gndheight[idx];
|
||||
double base_width = cfg.head_width_mm;
|
||||
|
||||
@ -1807,7 +1904,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
// Step: process the support points where there is not enough space for a
|
||||
// full pinhead. In this case we will use a rounded sphere as a touching
|
||||
// point and use a thinner bridge (let's call it a stick).
|
||||
auto process_headless = [tifcl](
|
||||
auto process_headless = [thr](
|
||||
const SupportConfig& cfg,
|
||||
const PointSet& headless_pts,
|
||||
const PointSet& headless_norm,
|
||||
@ -1822,7 +1919,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||
|
||||
// We will sink the pins into the model surface for a distance of 1/3 of
|
||||
// the pin radius
|
||||
for(int i = 0; i < headless_pts.rows(); i++) { tifcl();
|
||||
for(int i = 0; i < headless_pts.rows(); i++) { thr();
|
||||
Vec3d sph = headless_pts.row(i); // Exact support position
|
||||
Vec3d n = headless_norm.row(i); // mesh outward normal
|
||||
Vec3d sp = sph - n * HWIDTH_MM; // stick head start point
|
||||
|
@ -205,9 +205,11 @@ template<class Vec> double distance(const Vec& pp1, const Vec& pp2) {
|
||||
return std::sqrt(p.transpose() * p);
|
||||
}
|
||||
|
||||
PointSet normals(const PointSet& points, const EigenMesh3D& mesh,
|
||||
PointSet normals(const PointSet& points,
|
||||
const EigenMesh3D& mesh,
|
||||
double eps,
|
||||
std::function<void()> throw_on_cancel) {
|
||||
std::function<void()> throw_on_cancel)
|
||||
{
|
||||
if(points.rows() == 0 || mesh.V().rows() == 0 || mesh.F().rows() == 0)
|
||||
return {};
|
||||
|
||||
@ -228,7 +230,7 @@ PointSet normals(const PointSet& points, const EigenMesh3D& mesh,
|
||||
const Vec3d& p3 = mesh.V().row(trindex(2));
|
||||
|
||||
// We should check if the point lies on an edge of the hosting triangle.
|
||||
// If it does than all the other triangles using the same two points
|
||||
// If it does then all the other triangles using the same two points
|
||||
// have to be searched and the final normal should be some kind of
|
||||
// aggregation of the participating triangle normals. We should also
|
||||
// consider the cases where the support point lies right on a vertex
|
||||
|
@ -415,49 +415,73 @@ void SLAPrint::set_task(const TaskParams ¶ms)
|
||||
n_object_steps = (int)slaposCount;
|
||||
|
||||
if (params.single_model_object.valid()) {
|
||||
// Find the print object to be processed with priority.
|
||||
SLAPrintObject *print_object = nullptr;
|
||||
size_t idx_print_object = 0;
|
||||
for (; idx_print_object < m_objects.size(); ++idx_print_object)
|
||||
for (; idx_print_object < m_objects.size(); ++ idx_print_object)
|
||||
if (m_objects[idx_print_object]->model_object()->id() == params.single_model_object) {
|
||||
print_object = m_objects[idx_print_object];
|
||||
break;
|
||||
}
|
||||
assert(print_object != nullptr);
|
||||
bool shall_cancel = false;
|
||||
for (int istep = 0; istep < n_object_steps; ++istep)
|
||||
if (! print_object->m_stepmask[istep]) {
|
||||
shall_cancel = true;
|
||||
// Find out whether the priority print object is being currently processed.
|
||||
bool running = false;
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep) {
|
||||
if (! print_object->m_stepmask[istep])
|
||||
// Step was skipped, cancel.
|
||||
break;
|
||||
if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) {
|
||||
// No step was skipped, and a wanted step is being processed. Don't cancel.
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
bool running = false;
|
||||
if (!shall_cancel) {
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep)
|
||||
if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!running)
|
||||
if (! running)
|
||||
this->call_cancel_callback();
|
||||
|
||||
// Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway.
|
||||
if (params.single_model_instance_only) {
|
||||
// Suppress all the steps of other instances.
|
||||
for (SLAPrintObject *po : m_objects)
|
||||
for (int istep = 0; istep < (int)slaposCount; ++istep)
|
||||
for (int istep = 0; istep < (int)slaposCount; ++ istep)
|
||||
po->m_stepmask[istep] = false;
|
||||
}
|
||||
else if (!running) {
|
||||
} else if (! running) {
|
||||
// Swap the print objects, so that the selected print_object is first in the row.
|
||||
// At this point the background processing must be stopped, so it is safe to shuffle print objects.
|
||||
if (idx_print_object != 0)
|
||||
std::swap(m_objects.front(), m_objects[idx_print_object]);
|
||||
}
|
||||
// and set the steps for the current object.
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep)
|
||||
print_object->m_stepmask[istep] = true;
|
||||
for (int istep = n_object_steps; istep < (int)slaposCount; ++istep)
|
||||
for (int istep = n_object_steps; istep < (int)slaposCount; ++ istep)
|
||||
print_object->m_stepmask[istep] = false;
|
||||
}
|
||||
} else {
|
||||
// Slicing all objects.
|
||||
bool running = false;
|
||||
for (SLAPrintObject *print_object : m_objects)
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep) {
|
||||
if (! print_object->m_stepmask[istep]) {
|
||||
// Step may have been skipped. Restart.
|
||||
goto loop_end;
|
||||
}
|
||||
if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) {
|
||||
// This step is running, and the state cannot be changed due to the this->state_mutex() being locked.
|
||||
// It is safe to manipulate m_stepmask of other SLAPrintObjects and SLAPrint now.
|
||||
running = true;
|
||||
goto loop_end;
|
||||
}
|
||||
}
|
||||
loop_end:
|
||||
if (! running)
|
||||
this->call_cancel_callback();
|
||||
for (SLAPrintObject *po : m_objects) {
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep)
|
||||
po->m_stepmask[istep] = true;
|
||||
for (int istep = n_object_steps; istep < (int)slaposCount; ++ istep)
|
||||
po->m_stepmask[istep] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.to_object_step != -1 || params.to_print_step != -1) {
|
||||
// Limit the print steps.
|
||||
@ -484,7 +508,7 @@ void SLAPrint::finalize()
|
||||
std::string SLAPrint::output_filename() const
|
||||
{
|
||||
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
|
||||
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "zip", &config);
|
||||
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "sl1", &config);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -727,11 +751,13 @@ void SLAPrint::process()
|
||||
double wt = po.m_config.pad_wall_thickness.getFloat();
|
||||
double h = po.m_config.pad_wall_height.getFloat();
|
||||
double md = po.m_config.pad_max_merge_distance.getFloat();
|
||||
double er = po.m_config.pad_edge_radius.getFloat();
|
||||
// Radius is disabled for now...
|
||||
double er = 0; // po.m_config.pad_edge_radius.getFloat();
|
||||
double tilt = po.m_config.pad_wall_slope.getFloat() * PI / 180.0;
|
||||
double lh = po.m_config.layer_height.getFloat();
|
||||
double elevation = po.m_config.support_object_elevation.getFloat();
|
||||
if(!po.m_config.supports_enable.getBool()) elevation = 0;
|
||||
sla::PoolConfig pcfg(wt, h, md, er);
|
||||
sla::PoolConfig pcfg(wt, h, md, er, tilt);
|
||||
|
||||
ExPolygons bp;
|
||||
double pad_h = sla::get_pad_fullheight(pcfg);
|
||||
@ -742,8 +768,7 @@ void SLAPrint::process()
|
||||
|
||||
if(elevation < pad_h) {
|
||||
// we have to count with the model geometry for the base plate
|
||||
sla::base_plate(trmesh, bp, float(pad_h), float(lh),
|
||||
thrfn);
|
||||
sla::base_plate(trmesh, bp, float(pad_h), float(lh), thrfn);
|
||||
}
|
||||
|
||||
pcfg.throw_on_cancel = thrfn;
|
||||
@ -1344,6 +1369,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
|| opt_key == "pad_wall_thickness"
|
||||
|| opt_key == "pad_wall_height"
|
||||
|| opt_key == "pad_max_merge_distance"
|
||||
|| opt_key == "pad_wall_slope"
|
||||
|| opt_key == "pad_edge_radius") {
|
||||
steps.emplace_back(slaposBasePool);
|
||||
} else {
|
||||
|
@ -57,9 +57,7 @@
|
||||
|
||||
// Printbed textures generated from svg files
|
||||
#define ENABLE_TEXTURES_FROM_SVG (1 && ENABLE_1_42_0_ALPHA7)
|
||||
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
// Toolbars, Gizmos and other GUI icons imported from svg files
|
||||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA7)
|
||||
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
// Toolbars and Gizmos use icons imported from svg files
|
||||
#define ENABLE_SVG_ICONS (1 && ENABLE_TEXTURES_FROM_SVG)
|
||||
|
||||
#endif // _technologies_h_
|
||||
|
@ -150,7 +150,7 @@ void BackgroundSlicingProcess::process_sla()
|
||||
if (this->set_step_started(bspsGCodeFinalize)) {
|
||||
if (! m_export_path.empty()) {
|
||||
m_sla_print->export_raster<SLAZipFmt>(m_export_path);
|
||||
m_print->set_status(100, "Zip file exported to " + m_export_path);
|
||||
m_print->set_status(100, "Masked SLA file exported to " + m_export_path);
|
||||
} else if (! m_upload_job.empty()) {
|
||||
prepare_upload();
|
||||
} else {
|
||||
|
@ -631,8 +631,13 @@ void Choice::set_value(const boost::any& value, bool change_event)
|
||||
break;
|
||||
++idx;
|
||||
}
|
||||
idx == m_opt.enum_values.size() ?
|
||||
dynamic_cast<wxComboBox*>(window)->SetValue(text_value) :
|
||||
if (idx == m_opt.enum_values.size()) {
|
||||
// For editable Combobox under OSX is needed to set selection to -1 explicitly,
|
||||
// otherwise selection doesn't be changed
|
||||
dynamic_cast<wxComboBox*>(window)->SetSelection(-1);
|
||||
dynamic_cast<wxComboBox*>(window)->SetValue(text_value);
|
||||
}
|
||||
else
|
||||
dynamic_cast<wxComboBox*>(window)->SetSelection(idx);
|
||||
break;
|
||||
}
|
||||
|
@ -2405,20 +2405,37 @@ void GLCanvas3D::Selection::_ensure_on_bed()
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
const float GLCanvas3D::Gizmos::Default_Icons_Size = 64;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
GLCanvas3D::Gizmos::Gizmos()
|
||||
: m_enabled(false)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_icons_texture_dirty(true)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_current(Undefined)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_overlay_icons_size(Default_Icons_Size)
|
||||
, m_overlay_scale(1.0f)
|
||||
, m_overlay_border(5.0f)
|
||||
, m_overlay_gap_y(5.0f)
|
||||
{
|
||||
}
|
||||
#else
|
||||
{
|
||||
set_overlay_scale(1.0);
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
GLCanvas3D::Gizmos::~Gizmos()
|
||||
{
|
||||
_reset();
|
||||
reset();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
{
|
||||
#if !ENABLE_SVG_ICONS
|
||||
m_icons_texture.metadata.filename = "gizmos.png";
|
||||
m_icons_texture.metadata.icon_size = 64;
|
||||
|
||||
@ -2426,10 +2443,11 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
{
|
||||
if (!m_icons_texture.texture.load_from_file(resources_dir() + "/icons/" + m_icons_texture.metadata.filename, false))
|
||||
{
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
m_background_texture.metadata.filename = "toolbar_background.png";
|
||||
m_background_texture.metadata.left = 16;
|
||||
@ -2441,12 +2459,16 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
{
|
||||
if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false))
|
||||
{
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoBase* gizmo = new GLGizmoMove3D(parent, "add.svg", 0);
|
||||
#else
|
||||
GLGizmoBase* gizmo = new GLGizmoMove3D(parent, 0);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
@ -2455,7 +2477,11 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Move, gizmo));
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
gizmo = new GLGizmoScale3D(parent, "remove.svg", 1);
|
||||
#else
|
||||
gizmo = new GLGizmoScale3D(parent, 1);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
@ -2464,49 +2490,65 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Scale, gizmo));
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
gizmo = new GLGizmoRotate3D(parent, "delete_all.svg", 2);
|
||||
#else
|
||||
gizmo = new GLGizmoRotate3D(parent, 2);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
{
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gizmo->init())
|
||||
{
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
gizmo = new GLGizmoFlatten(parent, "arrange.svg", 3);
|
||||
#else
|
||||
gizmo = new GLGizmoFlatten(parent, 3);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
if (!gizmo->init()) {
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
gizmo = new GLGizmoCut(parent, "instance_add.svg", 4);
|
||||
#else
|
||||
gizmo = new GLGizmoCut(parent, 4);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
if (!gizmo->init()) {
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Cut, gizmo));
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
gizmo = new GLGizmoSlaSupports(parent, "instance_remove.svg", 5);
|
||||
#else
|
||||
gizmo = new GLGizmoSlaSupports(parent, 5);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (gizmo == nullptr)
|
||||
return false;
|
||||
|
||||
if (!gizmo->init()) {
|
||||
_reset();
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2525,11 +2567,30 @@ void GLCanvas3D::Gizmos::set_enabled(bool enable)
|
||||
m_enabled = enable;
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
void GLCanvas3D::Gizmos::set_overlay_icon_size(float size)
|
||||
{
|
||||
if (m_overlay_icons_size != size)
|
||||
{
|
||||
m_overlay_icons_size = size;
|
||||
m_icons_texture_dirty = true;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
void GLCanvas3D::Gizmos::set_overlay_scale(float scale)
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (m_overlay_scale != scale)
|
||||
{
|
||||
m_overlay_scale = scale;
|
||||
m_icons_texture_dirty = true;
|
||||
}
|
||||
#else
|
||||
m_overlay_icons_scale = scale;
|
||||
m_overlay_border = 5.0f * scale;
|
||||
m_overlay_gap_y = 5.0f * scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection)
|
||||
@ -2540,24 +2601,39 @@ std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, con
|
||||
return name;
|
||||
|
||||
float cnv_h = (float)canvas.get_canvas_size().get_height();
|
||||
float height = _get_total_overlay_height();
|
||||
float height = get_total_overlay_height();
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
|
||||
float scaled_border = m_overlay_border * m_overlay_scale;
|
||||
float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
|
||||
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
|
||||
float top_y = 0.5f * (cnv_h - height) + scaled_border;
|
||||
#else
|
||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
|
||||
#else
|
||||
bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (inside)
|
||||
name = it->second->get_name();
|
||||
|
||||
if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On))
|
||||
it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
top_y += scaled_stride_y;
|
||||
#else
|
||||
top_y += (scaled_icons_size + m_overlay_gap_y);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
return name;
|
||||
@ -2569,17 +2645,29 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec
|
||||
return;
|
||||
|
||||
float cnv_h = (float)canvas.get_canvas_size().get_height();
|
||||
float height = _get_total_overlay_height();
|
||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||
float height = get_total_overlay_height();
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
|
||||
float scaled_border = m_overlay_border * m_overlay_scale;
|
||||
float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
|
||||
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
|
||||
float top_y = 0.5f * (cnv_h - height) + scaled_border;
|
||||
#else
|
||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
|
||||
#else
|
||||
bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
if (it->second->is_activable(selection) && inside)
|
||||
{
|
||||
if ((it->second->get_state() == GLGizmoBase::On))
|
||||
@ -2596,7 +2684,11 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec
|
||||
else
|
||||
it->second->set_state(GLGizmoBase::Off);
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
top_y += scaled_stride_y;
|
||||
#else
|
||||
top_y += (scaled_icons_size + m_overlay_gap_y);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
GizmosMap::iterator it = m_gizmos.find(m_current);
|
||||
@ -2667,20 +2759,36 @@ bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const
|
||||
return false;
|
||||
|
||||
float cnv_h = (float)canvas.get_canvas_size().get_height();
|
||||
float height = _get_total_overlay_height();
|
||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||
float height = get_total_overlay_height();
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
|
||||
float scaled_border = m_overlay_border * m_overlay_scale;
|
||||
float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
|
||||
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
|
||||
float top_y = 0.5f * (cnv_h - height) + scaled_border;
|
||||
#else
|
||||
float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
|
||||
#else
|
||||
if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
return true;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
top_y += scaled_stride_y;
|
||||
#else
|
||||
top_y += (scaled_icons_size + m_overlay_gap_y);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -2691,7 +2799,7 @@ bool GLCanvas3D::Gizmos::grabber_contains_mouse() const
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
return (curr != nullptr) ? (curr->get_hover_id() != -1) : false;
|
||||
}
|
||||
|
||||
@ -2700,7 +2808,7 @@ void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, const Selection& select
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos, shift_down), selection);
|
||||
}
|
||||
@ -2715,7 +2823,7 @@ bool GLCanvas3D::Gizmos::is_running() const
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
|
||||
}
|
||||
|
||||
@ -2765,7 +2873,7 @@ bool GLCanvas3D::Gizmos::is_dragging() const
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
return (curr != nullptr) ? curr->is_dragging() : false;
|
||||
}
|
||||
|
||||
@ -2774,7 +2882,7 @@ void GLCanvas3D::Gizmos::start_dragging(const GLCanvas3D::Selection& selection)
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
curr->start_dragging(selection);
|
||||
}
|
||||
@ -2784,7 +2892,7 @@ void GLCanvas3D::Gizmos::stop_dragging()
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
curr->stop_dragging();
|
||||
}
|
||||
@ -2884,7 +2992,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selec
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
_render_current_gizmo(selection);
|
||||
do_render_current_gizmo(selection);
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D::Selection& selection) const
|
||||
@ -2892,7 +3000,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D:
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
curr->render_for_picking(selection);
|
||||
}
|
||||
@ -2902,12 +3010,17 @@ void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const GLCanvas
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (m_icons_texture_dirty)
|
||||
generate_icons_texture();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity();
|
||||
|
||||
_render_overlay(canvas, selection);
|
||||
do_render_overlay(canvas, selection);
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
@ -2921,7 +3034,7 @@ void GLCanvas3D::Gizmos::create_external_gizmo_widgets(wxWindow *parent)
|
||||
}
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
void GLCanvas3D::Gizmos::_reset()
|
||||
void GLCanvas3D::Gizmos::reset()
|
||||
{
|
||||
for (GizmosMap::value_type& gizmo : m_gizmos)
|
||||
{
|
||||
@ -2932,7 +3045,7 @@ void GLCanvas3D::Gizmos::_reset()
|
||||
m_gizmos.clear();
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
|
||||
void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
|
||||
{
|
||||
if (m_gizmos.empty())
|
||||
return;
|
||||
@ -2944,15 +3057,19 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva
|
||||
float zoom = canvas.get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
|
||||
float height = _get_total_overlay_height();
|
||||
float height = get_total_overlay_height();
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_border = m_overlay_border * m_overlay_scale * inv_zoom;
|
||||
#else
|
||||
float scaled_border = m_overlay_border * inv_zoom;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
float top_x = (-0.5f * cnv_w) * inv_zoom;
|
||||
float top_y = (0.5f * height) * inv_zoom;
|
||||
|
||||
float left = top_x;
|
||||
float top = top_y;
|
||||
float right = left + _get_total_overlay_width() * inv_zoom;
|
||||
float right = left + get_total_overlay_width() * inv_zoom;
|
||||
float bottom = top - height * inv_zoom;
|
||||
|
||||
// renders background
|
||||
@ -3021,6 +3138,16 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
top_x += scaled_border;
|
||||
top_y -= scaled_border;
|
||||
float scaled_gap_y = m_overlay_gap_y * m_overlay_scale * inv_zoom;
|
||||
|
||||
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale * inv_zoom;
|
||||
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
|
||||
unsigned int icons_texture_id = m_icons_texture.get_id();
|
||||
unsigned int texture_size = m_icons_texture.get_width();
|
||||
#else
|
||||
top_x += m_overlay_border * inv_zoom;
|
||||
top_y -= m_overlay_border * inv_zoom;
|
||||
float scaled_gap_y = m_overlay_gap_y * inv_zoom;
|
||||
@ -3028,8 +3155,14 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale * inv_zoom;
|
||||
unsigned int icons_texture_id = m_icons_texture.texture.get_id();
|
||||
unsigned int texture_size = m_icons_texture.texture.get_width();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float inv_texture_size = (texture_size != 0) ? 1.0f / (float)texture_size : 0.0f;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if ((icons_texture_id == 0) || (texture_size <= 0))
|
||||
return;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
@ -3038,7 +3171,11 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva
|
||||
unsigned int sprite_id = it->second->get_sprite_id();
|
||||
GLGizmoBase::EState state = it->second->get_state();
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
float uv_icon_size = m_overlay_icons_size * inv_texture_size;
|
||||
#else
|
||||
float uv_icon_size = (float)m_icons_texture.metadata.icon_size * inv_texture_size;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
float top = sprite_id * uv_icon_size;
|
||||
float left = state * uv_icon_size;
|
||||
float bottom = top + uv_icon_size;
|
||||
@ -3047,48 +3184,98 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanva
|
||||
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { left, bottom }, { right, bottom }, { right, top }, { left, top } });
|
||||
#if ENABLE_IMGUI
|
||||
if (it->second->get_state() == GLGizmoBase::On)
|
||||
#if ENABLE_SVG_ICONS
|
||||
it->second->render_input_window(2.0f * scaled_border + scaled_icons_size * zoom, 0.5f * cnv_h - top_y * zoom, selection);
|
||||
#else
|
||||
it->second->render_input_window(2.0f * m_overlay_border + scaled_icons_size * zoom, 0.5f * cnv_h - top_y * zoom, selection);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
#endif // ENABLE_IMGUI
|
||||
#if ENABLE_SVG_ICONS
|
||||
top_y -= scaled_stride_y;
|
||||
#else
|
||||
top_y -= (scaled_icons_size + scaled_gap_y);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::_render_current_gizmo(const GLCanvas3D::Selection& selection) const
|
||||
void GLCanvas3D::Gizmos::do_render_current_gizmo(const GLCanvas3D::Selection& selection) const
|
||||
{
|
||||
GLGizmoBase* curr = _get_current();
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
curr->render(selection);
|
||||
}
|
||||
|
||||
float GLCanvas3D::Gizmos::_get_total_overlay_height() const
|
||||
float GLCanvas3D::Gizmos::get_total_overlay_height() const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
|
||||
float scaled_border = m_overlay_border * m_overlay_scale;
|
||||
float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
|
||||
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
|
||||
float height = 2.0f * scaled_border;
|
||||
#else
|
||||
float height = 2.0f * m_overlay_border;
|
||||
|
||||
float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if ((it->second == nullptr) || !it->second->is_selectable())
|
||||
continue;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
height += scaled_stride_y;
|
||||
#else
|
||||
height += (scaled_icons_size + m_overlay_gap_y);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
return height - scaled_gap_y;
|
||||
#else
|
||||
return height - m_overlay_gap_y;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
float GLCanvas3D::Gizmos::_get_total_overlay_width() const
|
||||
float GLCanvas3D::Gizmos::get_total_overlay_width() const
|
||||
{
|
||||
float max_icon_width = std::max(max_icon_width, (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale);
|
||||
return max_icon_width + 2.0f * m_overlay_border;
|
||||
#if ENABLE_SVG_ICONS
|
||||
return (2.0f * m_overlay_border + m_overlay_icons_size) * m_overlay_scale;
|
||||
#else
|
||||
return (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale + 2.0f * m_overlay_border;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
}
|
||||
|
||||
GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
|
||||
GLGizmoBase* GLCanvas3D::Gizmos::get_current() const
|
||||
{
|
||||
GizmosMap::const_iterator it = m_gizmos.find(m_current);
|
||||
return (it != m_gizmos.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool GLCanvas3D::Gizmos::generate_icons_texture() const
|
||||
{
|
||||
std::string path = resources_dir() + "/icons/";
|
||||
std::vector<std::string> filenames;
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
if (it->second != nullptr)
|
||||
{
|
||||
const std::string& svg_file = it->second->get_svg_file();
|
||||
if (!svg_file.empty())
|
||||
filenames.push_back(path + svg_file);
|
||||
}
|
||||
}
|
||||
|
||||
bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, GLGizmoBase::Num_States, (unsigned int)(m_overlay_icons_size * m_overlay_scale));
|
||||
if (res)
|
||||
m_icons_texture_dirty = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 9, 91, 134 };
|
||||
const unsigned char GLCanvas3D::WarningTexture::Opacity = 255;
|
||||
|
||||
@ -3197,7 +3384,7 @@ bool GLCanvas3D::WarningTexture::_generate(const std::string& msg, const GLCanva
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
::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);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return true;
|
||||
@ -3450,7 +3637,7 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
::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);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return true;
|
||||
@ -4054,7 +4241,9 @@ void GLCanvas3D::render()
|
||||
_render_gizmos_overlay();
|
||||
_render_warning_texture();
|
||||
_render_legend_texture();
|
||||
#if !ENABLE_SVG_ICONS
|
||||
_resize_toolbars();
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
_render_toolbar();
|
||||
_render_view_toolbar();
|
||||
if (m_layers_editing.last_object_id >= 0)
|
||||
@ -4647,7 +4836,19 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
switch (keyCode)
|
||||
{
|
||||
// key ESC
|
||||
case WXK_ESCAPE: { m_gizmos.reset_all_states(); m_dirty = true; break; }
|
||||
case WXK_ESCAPE: {
|
||||
if (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::DiscardChanges))
|
||||
m_gizmos.reset_all_states();
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case WXK_RETURN: {
|
||||
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ApplyChanges))
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
case WXK_BACK: // the low cost Apple solutions are not equipped with a Delete key, use Backspace instead.
|
||||
#else /* __APPLE__ */
|
||||
@ -4670,11 +4871,25 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||
case '-': { post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, -1)); break; }
|
||||
case '?': { post_event(SimpleEvent(EVT_GLCANVAS_QUESTION_MARK)); break; }
|
||||
case 'A':
|
||||
case 'a': { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; }
|
||||
case 'a': {
|
||||
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) {
|
||||
if (m_gizmos.mouse_event(SLAGizmoEventType::AutomaticGeneration))
|
||||
m_dirty = true;
|
||||
}
|
||||
else
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE));
|
||||
break;
|
||||
}
|
||||
case 'B':
|
||||
case 'b': { zoom_to_bed(); break; }
|
||||
case 'I':
|
||||
case 'i': { set_camera_zoom(1.0f); break; }
|
||||
case 'M':
|
||||
case 'm': {
|
||||
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ManualEditing))
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
case 'O':
|
||||
case 'o': { set_camera_zoom(-1.0f); break; }
|
||||
case 'Z':
|
||||
@ -4769,6 +4984,54 @@ void GLCanvas3D::on_timer(wxTimerEvent& evt)
|
||||
_perform_layer_editing_action();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// #define SLIC3R_DEBUG_MOUSE_EVENTS
|
||||
#endif
|
||||
|
||||
#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
|
||||
std::string format_mouse_event_debug_message(const wxMouseEvent &evt)
|
||||
{
|
||||
static int idx = 0;
|
||||
char buf[2048];
|
||||
std::string out;
|
||||
sprintf(buf, "Mouse Event %d - ", idx ++);
|
||||
out = buf;
|
||||
|
||||
if (evt.Entering())
|
||||
out += "Entering ";
|
||||
if (evt.Leaving())
|
||||
out += "Leaving ";
|
||||
if (evt.Dragging())
|
||||
out += "Dragging ";
|
||||
if (evt.Moving())
|
||||
out += "Moving ";
|
||||
if (evt.Magnify())
|
||||
out += "Magnify ";
|
||||
if (evt.LeftDown())
|
||||
out += "LeftDown ";
|
||||
if (evt.LeftUp())
|
||||
out += "LeftUp ";
|
||||
if (evt.LeftDClick())
|
||||
out += "LeftDClick ";
|
||||
if (evt.MiddleDown())
|
||||
out += "MiddleDown ";
|
||||
if (evt.MiddleUp())
|
||||
out += "MiddleUp ";
|
||||
if (evt.MiddleDClick())
|
||||
out += "MiddleDClick ";
|
||||
if (evt.RightDown())
|
||||
out += "RightDown ";
|
||||
if (evt.RightUp())
|
||||
out += "RightUp ";
|
||||
if (evt.RightDClick())
|
||||
out += "RightDClick ";
|
||||
|
||||
sprintf(buf, "(%d, %d)", evt.GetX(), evt.GetY());
|
||||
out += buf;
|
||||
return out;
|
||||
}
|
||||
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
||||
|
||||
void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
{
|
||||
#if ENABLE_RETINA_GL
|
||||
@ -4784,15 +5047,27 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
if (imgui->update_mouse_data(evt)) {
|
||||
m_mouse.position = evt.Leaving() ? Vec2d(-1.0, -1.0) : pos.cast<double>();
|
||||
render();
|
||||
return;
|
||||
#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
|
||||
printf((format_mouse_event_debug_message(evt) + " - Consumed by ImGUI\n").c_str());
|
||||
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
bool on_enter_workaround = false;
|
||||
if (! evt.Entering() && ! evt.Leaving() && m_mouse.position.x() == -1.0) {
|
||||
// Workaround for SPE-832: There seems to be a mouse event sent to the window before evt.Entering()
|
||||
m_mouse.position = pos.cast<double>();
|
||||
render();
|
||||
}
|
||||
#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
|
||||
printf((format_mouse_event_debug_message(evt) + " - OnEnter workaround\n").c_str());
|
||||
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
||||
on_enter_workaround = true;
|
||||
} else {
|
||||
#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
|
||||
printf((format_mouse_event_debug_message(evt) + " - other\n").c_str());
|
||||
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
||||
}
|
||||
|
||||
if (m_picking_enabled)
|
||||
_set_current();
|
||||
@ -5240,6 +5515,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
else
|
||||
evt.Skip();
|
||||
|
||||
if (on_enter_workaround)
|
||||
m_mouse.position = Vec2d(-1., -1.);
|
||||
}
|
||||
|
||||
void GLCanvas3D::on_paint(wxPaintEvent& evt)
|
||||
@ -5588,14 +5866,11 @@ bool GLCanvas3D::_init_toolbar()
|
||||
if (!m_toolbar.is_enabled())
|
||||
return true;
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
ItemsIconsTexture::Metadata icons_data;
|
||||
icons_data.filename = "toolbar.png";
|
||||
icons_data.icon_size = 37;
|
||||
|
||||
// icons_data.filename = "toolbar141.png";
|
||||
// icons_data.icon_size = 52;
|
||||
// icons_data.icon_border_size = 0;
|
||||
// icons_data.icon_gap_size = 0;
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
BackgroundTexture::Metadata background_data;
|
||||
background_data.filename = "toolbar_background.png";
|
||||
@ -5604,7 +5879,11 @@ bool GLCanvas3D::_init_toolbar()
|
||||
background_data.right = 16;
|
||||
background_data.bottom = 16;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (!m_toolbar.init(background_data))
|
||||
#else
|
||||
if (!m_toolbar.init(icons_data, background_data))
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
{
|
||||
// unable to init the toolbar texture, disable it
|
||||
m_toolbar.set_enabled(false);
|
||||
@ -5621,6 +5900,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
GLToolbarItem::Data item;
|
||||
|
||||
item.name = "add";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "add.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]";
|
||||
item.sprite_id = 0;
|
||||
item.action_event = EVT_GLTOOLBAR_ADD;
|
||||
@ -5628,6 +5910,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "delete";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "remove.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Delete") + " [Del]";
|
||||
item.sprite_id = 1;
|
||||
item.action_event = EVT_GLTOOLBAR_DELETE;
|
||||
@ -5635,6 +5920,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "deleteall";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "delete_all.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
|
||||
item.sprite_id = 2;
|
||||
item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
|
||||
@ -5642,6 +5930,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "arrange";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "arrange.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Arrange [A]");
|
||||
item.sprite_id = 3;
|
||||
item.action_event = EVT_GLTOOLBAR_ARRANGE;
|
||||
@ -5652,6 +5943,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "more";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "instance_add.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Add instance [+]");
|
||||
item.sprite_id = 4;
|
||||
item.action_event = EVT_GLTOOLBAR_MORE;
|
||||
@ -5659,6 +5953,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "fewer";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "instance_remove.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Remove instance [-]");
|
||||
item.sprite_id = 5;
|
||||
item.action_event = EVT_GLTOOLBAR_FEWER;
|
||||
@ -5669,6 +5966,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "splitobjects";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "split_objects.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Split to objects");
|
||||
item.sprite_id = 6;
|
||||
item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS;
|
||||
@ -5676,6 +5976,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "splitvolumes";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "split_parts.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Split to parts");
|
||||
item.sprite_id = 8;
|
||||
item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES;
|
||||
@ -5686,6 +5989,9 @@ bool GLCanvas3D::_init_toolbar()
|
||||
return false;
|
||||
|
||||
item.name = "layersediting";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "layers.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Layers editing");
|
||||
item.sprite_id = 7;
|
||||
item.is_toggable = true;
|
||||
@ -6177,11 +6483,63 @@ void GLCanvas3D::_render_gizmos_overlay() const
|
||||
|
||||
void GLCanvas3D::_render_toolbar() const
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
#if ENABLE_RETINA_GL
|
||||
m_toolbar.set_scale(m_retina_helper->get_scale_factor());
|
||||
#else
|
||||
m_toolbar.set_scale(m_canvas->GetContentScaleFactor());
|
||||
#endif // ENABLE_RETINA_GL
|
||||
|
||||
Size cnv_size = get_canvas_size();
|
||||
float zoom = get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
|
||||
GLToolbar::Layout::EOrientation orientation = m_toolbar.get_layout_orientation();
|
||||
|
||||
float top = 0.0f;
|
||||
float left = 0.0f;
|
||||
switch (m_toolbar.get_layout_type())
|
||||
{
|
||||
default:
|
||||
case GLToolbar::Layout::Horizontal:
|
||||
{
|
||||
// centers the toolbar on the top edge of the 3d scene
|
||||
if (orientation == GLToolbar::Layout::Top)
|
||||
{
|
||||
top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
|
||||
left = -0.5f * m_toolbar.get_width() * inv_zoom;
|
||||
}
|
||||
else
|
||||
{
|
||||
top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar->get_height()) * inv_zoom;
|
||||
left = -0.5f * m_toolbar.get_width() * inv_zoom;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GLToolbar::Layout::Vertical:
|
||||
{
|
||||
// centers the toolbar on the right edge of the 3d scene
|
||||
if (orientation == GLToolbar::Layout::Left)
|
||||
{
|
||||
top = 0.5f * m_toolbar.get_height() * inv_zoom;
|
||||
left = (-0.5f * (float)cnv_size.get_width()) * inv_zoom;
|
||||
}
|
||||
else
|
||||
{
|
||||
top = 0.5f * m_toolbar.get_height() * inv_zoom;
|
||||
left = (0.5f * (float)cnv_size.get_width() - m_toolbar.get_width()) * inv_zoom;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_toolbar.set_position(top, left);
|
||||
#else
|
||||
#if ENABLE_RETINA_GL
|
||||
m_toolbar.set_icons_scale(m_retina_helper->get_scale_factor());
|
||||
#else
|
||||
m_toolbar.set_icons_scale(m_canvas->GetContentScaleFactor());
|
||||
#endif /* __WXMSW__ */
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
m_toolbar.render(*this);
|
||||
}
|
||||
@ -6189,11 +6547,28 @@ void GLCanvas3D::_render_toolbar() const
|
||||
void GLCanvas3D::_render_view_toolbar() const
|
||||
{
|
||||
if (m_view_toolbar != nullptr) {
|
||||
#if ENABLE_SVG_ICONS
|
||||
#if ENABLE_RETINA_GL
|
||||
m_view_toolbar->set_scale(m_retina_helper->get_scale_factor());
|
||||
#else
|
||||
m_view_toolbar->set_scale(m_canvas->GetContentScaleFactor());
|
||||
#endif // ENABLE_RETINA_GL
|
||||
|
||||
Size cnv_size = get_canvas_size();
|
||||
float zoom = get_camera_zoom();
|
||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||
|
||||
// places the toolbar on the bottom-left corner of the 3d scene
|
||||
float top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar->get_height()) * inv_zoom;
|
||||
float left = -0.5f * (float)cnv_size.get_width() * inv_zoom;
|
||||
m_view_toolbar->set_position(top, left);
|
||||
#else
|
||||
#if ENABLE_RETINA_GL
|
||||
m_view_toolbar->set_icons_scale(m_retina_helper->get_scale_factor());
|
||||
#else
|
||||
m_view_toolbar->set_icons_scale(m_canvas->GetContentScaleFactor());
|
||||
#endif /* __WXMSW__ */
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
m_view_toolbar->render(*this);
|
||||
}
|
||||
}
|
||||
@ -7682,6 +8057,7 @@ bool GLCanvas3D::_is_any_volume_outside() const
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
void GLCanvas3D::_resize_toolbars() const
|
||||
{
|
||||
Size cnv_size = get_canvas_size();
|
||||
@ -7749,6 +8125,7 @@ void GLCanvas3D::_resize_toolbars() const
|
||||
m_view_toolbar->set_position(top, left);
|
||||
}
|
||||
}
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
const Print* GLCanvas3D::fff_print() const
|
||||
{
|
||||
|
@ -125,7 +125,11 @@ enum class SLAGizmoEventType {
|
||||
Dragging,
|
||||
Delete,
|
||||
SelectAll,
|
||||
ShiftUp
|
||||
ShiftUp,
|
||||
ApplyChanges,
|
||||
DiscardChanges,
|
||||
AutomaticGeneration,
|
||||
ManualEditing
|
||||
};
|
||||
|
||||
|
||||
@ -631,6 +635,10 @@ private:
|
||||
class Gizmos
|
||||
{
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
static const float Default_Icons_Size;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
enum EType : unsigned char
|
||||
{
|
||||
Undefined,
|
||||
@ -647,11 +655,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;
|
||||
|
||||
@ -664,6 +682,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);
|
||||
@ -713,15 +734,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
|
||||
@ -1092,7 +1117,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);
|
||||
|
||||
|
@ -157,11 +157,18 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& svg_file, 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_svg_file(svg_file)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, m_sprite_id(sprite_id)
|
||||
, m_hover_id(-1)
|
||||
, m_dragging(false)
|
||||
@ -305,7 +312,11 @@ const unsigned int GLGizmoRotate::SnapRegionsCount = 8;
|
||||
const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius
|
||||
|
||||
GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
|
||||
#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)
|
||||
@ -322,7 +333,11 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
|
||||
}
|
||||
|
||||
GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other)
|
||||
#if ENABLE_SVG_ICONS
|
||||
: GLGizmoBase(other.m_parent, other.m_svg_file, 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)
|
||||
@ -694,8 +709,13 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
||||
return transform(mouse_ray, m).intersect_plane(0.0);
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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);
|
||||
@ -774,8 +794,13 @@ void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D:
|
||||
|
||||
const float GLGizmoScale3D::Offset = 5.0f;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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())
|
||||
@ -1120,8 +1145,13 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||
|
||||
const double GLGizmoMove3D::Offset = 10.0;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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())
|
||||
@ -1357,8 +1387,13 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
||||
::glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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())
|
||||
{
|
||||
@ -1696,8 +1731,13 @@ Vec3d GLGizmoFlatten::get_flattening_normal() const
|
||||
return out;
|
||||
}
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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();
|
||||
@ -1886,12 +1926,6 @@ bool GLGizmoSlaSupports::is_mesh_update_necessary() const
|
||||
|
||||
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
|
||||
// return false;
|
||||
|
||||
// following should detect direct mesh changes (can be removed after the mesh is made completely immutable):
|
||||
/*const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex();
|
||||
Vec3d first_point((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]);
|
||||
if (first_point != m_source_data.mesh_first_point)
|
||||
return true;*/
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::update_mesh()
|
||||
@ -1967,139 +2001,161 @@ Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
|
||||
// concludes that the event was not intended for it, it should return false.
|
||||
bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
|
||||
{
|
||||
if (!m_editing_mode)
|
||||
return false;
|
||||
if (m_editing_mode) {
|
||||
|
||||
// left down - show the selection rectangle:
|
||||
if (action == SLAGizmoEventType::LeftDown && shift_down) {
|
||||
if (m_hover_id == -1) {
|
||||
m_selection_rectangle_active = true;
|
||||
m_selection_rectangle_start_corner = mouse_position;
|
||||
// left down - show the selection rectangle:
|
||||
if (action == SLAGizmoEventType::LeftDown && shift_down) {
|
||||
if (m_hover_id == -1) {
|
||||
m_selection_rectangle_active = true;
|
||||
m_selection_rectangle_start_corner = mouse_position;
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
m_canvas_width = m_parent.get_canvas_size().get_width();
|
||||
m_canvas_height = m_parent.get_canvas_size().get_height();
|
||||
}
|
||||
else
|
||||
select_point(m_hover_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// dragging the selection rectangle:
|
||||
if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) {
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
m_canvas_width = m_parent.get_canvas_size().get_width();
|
||||
m_canvas_height = m_parent.get_canvas_size().get_height();
|
||||
}
|
||||
else
|
||||
select_point(m_hover_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// dragging the selection rectangle:
|
||||
if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) {
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
return true;
|
||||
}
|
||||
|
||||
// mouse up without selection rectangle - place point on the mesh:
|
||||
if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) {
|
||||
if (m_ignore_up_event) {
|
||||
m_ignore_up_event = false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int instance_id = m_parent.get_selection().get_instance_idx();
|
||||
if (m_old_instance_id != instance_id)
|
||||
{
|
||||
bool something_selected = (m_old_instance_id != -1);
|
||||
m_old_instance_id = instance_id;
|
||||
if (something_selected)
|
||||
// mouse up without selection rectangle - place point on the mesh:
|
||||
if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) {
|
||||
if (m_ignore_up_event) {
|
||||
m_ignore_up_event = false;
|
||||
return false;
|
||||
}
|
||||
if (instance_id == -1)
|
||||
return false;
|
||||
|
||||
// If there is some selection, don't add new point and deselect everything instead.
|
||||
if (m_selection_empty) {
|
||||
Vec3f new_pos;
|
||||
try {
|
||||
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case
|
||||
m_editing_mode_cache.emplace_back(std::make_pair(sla::SupportPoint(new_pos, m_new_point_head_diameter/2.f, false), false));
|
||||
m_unsaved_changes = true;
|
||||
}
|
||||
catch (...) { // not clicked on object
|
||||
return true; // prevents deselection of the gizmo by GLCanvas3D
|
||||
|
||||
int instance_id = m_parent.get_selection().get_instance_idx();
|
||||
if (m_old_instance_id != instance_id)
|
||||
{
|
||||
bool something_selected = (m_old_instance_id != -1);
|
||||
m_old_instance_id = instance_id;
|
||||
if (something_selected)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
select_point(NoPoints);
|
||||
if (instance_id == -1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// left up with selection rectangle - select points inside the rectangle:
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp)
|
||||
&& m_selection_rectangle_active) {
|
||||
if (action == SLAGizmoEventType::ShiftUp)
|
||||
m_ignore_up_event = true;
|
||||
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
|
||||
GLint viewport[4];
|
||||
::glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
GLdouble modelview_matrix[16];
|
||||
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
|
||||
GLdouble projection_matrix[16];
|
||||
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
|
||||
|
||||
const GLCanvas3D::Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
double z_offset = volume->get_sla_shift_z();
|
||||
|
||||
// bounding box created from the rectangle corners - will take care of order of the corners
|
||||
BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast<int>()), Point(m_selection_rectangle_end_corner.cast<int>())});
|
||||
|
||||
const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true);
|
||||
// we'll recover current look direction from the modelview matrix (in world coords)...
|
||||
Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]);
|
||||
// ...and transform it to model coords.
|
||||
direction_to_camera = (instance_matrix_no_translation.inverse().cast<float>() * direction_to_camera).normalized().eval();
|
||||
|
||||
// Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh:
|
||||
for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i) {
|
||||
const sla::SupportPoint &support_point = m_editing_mode_cache[i].first;
|
||||
Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
|
||||
pos(2) += z_offset;
|
||||
GLdouble out_x, out_y, out_z;
|
||||
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
|
||||
out_y = m_canvas_height - out_y;
|
||||
|
||||
if (rectangle.contains(Point(out_x, out_y))) {
|
||||
bool is_obscured = false;
|
||||
// Cast a ray in the direction of the camera and look for intersection with the mesh:
|
||||
std::vector<igl::Hit> hits;
|
||||
// Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies.
|
||||
if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera * (support_point.head_front_radius + EPSILON), direction_to_camera, hits))
|
||||
// FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction.
|
||||
// Also, the threshold is in mesh coordinates, not in actual dimensions.
|
||||
if (hits.size() > 1 || hits.front().t > 0.001f)
|
||||
is_obscured = true;
|
||||
|
||||
if (!is_obscured)
|
||||
select_point(i);
|
||||
// If there is some selection, don't add new point and deselect everything instead.
|
||||
if (m_selection_empty) {
|
||||
Vec3f new_pos;
|
||||
try {
|
||||
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new point in that case
|
||||
m_editing_mode_cache.emplace_back(std::make_pair(sla::SupportPoint(new_pos, m_new_point_head_diameter/2.f, false), false));
|
||||
m_unsaved_changes = true;
|
||||
}
|
||||
catch (...) { // not clicked on object
|
||||
return true; // prevents deselection of the gizmo by GLCanvas3D
|
||||
}
|
||||
}
|
||||
else
|
||||
select_point(NoPoints);
|
||||
|
||||
return true;
|
||||
}
|
||||
m_selection_rectangle_active = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::Delete) {
|
||||
// delete key pressed
|
||||
delete_selected_points();
|
||||
return true;
|
||||
}
|
||||
// left up with selection rectangle - select points inside the rectangle:
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp)
|
||||
&& m_selection_rectangle_active) {
|
||||
if (action == SLAGizmoEventType::ShiftUp)
|
||||
m_ignore_up_event = true;
|
||||
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
|
||||
GLint viewport[4];
|
||||
::glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
GLdouble modelview_matrix[16];
|
||||
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
|
||||
GLdouble projection_matrix[16];
|
||||
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
|
||||
|
||||
if (action == SLAGizmoEventType::RightDown) {
|
||||
if (m_hover_id != -1) {
|
||||
select_point(NoPoints);
|
||||
select_point(m_hover_id);
|
||||
const GLCanvas3D::Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
double z_offset = volume->get_sla_shift_z();
|
||||
|
||||
// bounding box created from the rectangle corners - will take care of order of the corners
|
||||
BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast<int>()), Point(m_selection_rectangle_end_corner.cast<int>())});
|
||||
|
||||
const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true);
|
||||
// we'll recover current look direction from the modelview matrix (in world coords)...
|
||||
Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]);
|
||||
// ...and transform it to model coords.
|
||||
direction_to_camera = (instance_matrix_no_translation.inverse().cast<float>() * direction_to_camera).normalized().eval();
|
||||
|
||||
// Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh:
|
||||
for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i) {
|
||||
const sla::SupportPoint &support_point = m_editing_mode_cache[i].first;
|
||||
Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
|
||||
pos(2) += z_offset;
|
||||
GLdouble out_x, out_y, out_z;
|
||||
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z);
|
||||
out_y = m_canvas_height - out_y;
|
||||
|
||||
if (rectangle.contains(Point(out_x, out_y))) {
|
||||
bool is_obscured = false;
|
||||
// Cast a ray in the direction of the camera and look for intersection with the mesh:
|
||||
std::vector<igl::Hit> hits;
|
||||
// Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies.
|
||||
if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera * (support_point.head_front_radius + EPSILON), direction_to_camera, hits))
|
||||
// FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction.
|
||||
// Also, the threshold is in mesh coordinates, not in actual dimensions.
|
||||
if (hits.size() > 1 || hits.front().t > 0.001f)
|
||||
is_obscured = true;
|
||||
|
||||
if (!is_obscured)
|
||||
select_point(i);
|
||||
}
|
||||
}
|
||||
m_selection_rectangle_active = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::Delete) {
|
||||
// delete key pressed
|
||||
delete_selected_points();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (action == SLAGizmoEventType::ApplyChanges) {
|
||||
editing_mode_apply_changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::DiscardChanges) {
|
||||
editing_mode_discard_changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::RightDown) {
|
||||
if (m_hover_id != -1) {
|
||||
select_point(NoPoints);
|
||||
select_point(m_hover_id);
|
||||
delete_selected_points();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::SelectAll) {
|
||||
select_point(AllPoints);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::SelectAll) {
|
||||
select_point(AllPoints);
|
||||
return true;
|
||||
if (!m_editing_mode) {
|
||||
if (action == SLAGizmoEventType::AutomaticGeneration) {
|
||||
auto_generate();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::ManualEditing) {
|
||||
switch_to_editing_mode();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -2186,7 +2242,6 @@ RENDER_AGAIN:
|
||||
|
||||
bool force_refresh = false;
|
||||
bool remove_selected = false;
|
||||
bool old_editing_state = m_editing_mode;
|
||||
|
||||
if (m_editing_mode) {
|
||||
m_imgui->text(_(L("Left mouse click - add point")));
|
||||
@ -2230,9 +2285,6 @@ RENDER_AGAIN:
|
||||
if (apply_changes) {
|
||||
editing_mode_apply_changes();
|
||||
force_refresh = true;
|
||||
// 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);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
bool discard_changes = m_imgui->button(_(L("Discard changes")));
|
||||
@ -2250,70 +2302,24 @@ RENDER_AGAIN:
|
||||
ImGui::SameLine();
|
||||
value_changed |= ImGui::InputDouble("%", &m_density, 0.0f, 0.0f, "%.f");*/
|
||||
|
||||
bool generate = m_imgui->button(_(L("Auto-generate points")));
|
||||
bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
|
||||
|
||||
if (generate) {
|
||||
#if SLAGIZMO_IMGUI_MODAL
|
||||
ImGui::OpenPopup(_(L("Warning")));
|
||||
m_show_modal = true;
|
||||
force_refresh = true;
|
||||
#else
|
||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L(
|
||||
"Autogeneration will erase all manually edited points.\n\n"
|
||||
"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) {
|
||||
m_model_object->sla_support_points.clear();
|
||||
m_editing_mode_cache.clear();
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if SLAGIZMO_IMGUI_MODAL
|
||||
if (m_show_modal) {
|
||||
if (ImGui::BeginPopupModal(_(L("Warning")), &m_show_modal/*, ImGuiWindowFlags_NoDecoration*/))
|
||||
{
|
||||
m_imgui->text(_(L("Autogeneration will erase all manually edited points.")));
|
||||
m_imgui->text("");
|
||||
m_imgui->text(_(L("Are you sure you want to do it?")));
|
||||
if (generate)
|
||||
auto_generate();
|
||||
|
||||
if (m_imgui->button(_(L("Continue"))))
|
||||
{
|
||||
ImGui::CloseCurrentPopup();
|
||||
m_show_modal = false;
|
||||
|
||||
m_model_object->sla_support_points.clear();
|
||||
m_editing_mode_cache.clear();
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(_(L("Cancel")))) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
m_show_modal = false;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (!m_show_modal)
|
||||
force_refresh = true;
|
||||
}
|
||||
#endif
|
||||
m_imgui->text("");
|
||||
m_imgui->text("");
|
||||
bool editing_clicked = m_imgui->button(_(L("Manual editing")));
|
||||
if (editing_clicked) {
|
||||
editing_mode_reload_cache();
|
||||
m_editing_mode = true;
|
||||
}
|
||||
if (m_imgui->button(_(L("Manual editing [M]"))))
|
||||
switch_to_editing_mode();
|
||||
}
|
||||
|
||||
m_imgui->end();
|
||||
|
||||
if (m_editing_mode != old_editing_state) { // user just toggled between editing/non-editing mode
|
||||
if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode
|
||||
m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode);
|
||||
force_refresh = true;
|
||||
}
|
||||
|
||||
m_old_editing_state = m_editing_mode;
|
||||
|
||||
if (remove_selected) {
|
||||
force_refresh = false;
|
||||
@ -2379,18 +2385,13 @@ void GLGizmoSlaSupports::on_set_state()
|
||||
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
m_editing_mode = false; // so it is not active next time the gizmo opens
|
||||
|
||||
#if SLAGIZMO_IMGUI_MODAL
|
||||
if (m_show_modal) {
|
||||
m_show_modal = false;
|
||||
on_render_input_window(0,0,m_parent.get_selection()); // this is necessary to allow ImGui to terminate the modal dialog correctly
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
m_old_state = m_state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
|
||||
{
|
||||
if (m_hover_id != -1) {
|
||||
@ -2399,6 +2400,8 @@ void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selectio
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::select_point(int i)
|
||||
{
|
||||
if (i == AllPoints || i == NoPoints) {
|
||||
@ -2412,6 +2415,8 @@ void GLGizmoSlaSupports::select_point(int i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::editing_mode_discard_changes()
|
||||
{
|
||||
m_editing_mode_cache.clear();
|
||||
@ -2421,6 +2426,8 @@ void GLGizmoSlaSupports::editing_mode_discard_changes()
|
||||
m_unsaved_changes = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
@ -2432,8 +2439,14 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::editing_mode_reload_cache()
|
||||
{
|
||||
m_editing_mode_cache.clear();
|
||||
@ -2442,6 +2455,8 @@ void GLGizmoSlaSupports::editing_mode_reload_cache()
|
||||
m_unsaved_changes = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::get_data_from_backend()
|
||||
{
|
||||
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
||||
@ -2459,6 +2474,34 @@ void GLGizmoSlaSupports::get_data_from_backend()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::auto_generate()
|
||||
{
|
||||
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L(
|
||||
"Autogeneration will erase all manually edited points.\n\n"
|
||||
"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) {
|
||||
m_model_object->sla_support_points.clear();
|
||||
m_editing_mode_cache.clear();
|
||||
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::switch_to_editing_mode()
|
||||
{
|
||||
editing_mode_reload_cache();
|
||||
m_editing_mode = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// GLGizmoCut
|
||||
|
||||
class GLGizmoCutPanel : public wxPanel
|
||||
@ -2506,8 +2549,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 };
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id)
|
||||
: GLGizmoBase(parent, svg_file, 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
|
||||
|
@ -87,6 +87,9 @@ protected:
|
||||
int m_group_id;
|
||||
EState m_state;
|
||||
int m_shortcut_key;
|
||||
#if ENABLE_SVG_ICONS
|
||||
std::string m_svg_file;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
unsigned int m_sprite_id;
|
||||
int m_hover_id;
|
||||
bool m_dragging;
|
||||
@ -99,7 +102,11 @@ protected:
|
||||
#endif // ENABLE_IMGUI
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoBase(GLCanvas3D& parent, const std::string& svg_file, unsigned int sprite_id);
|
||||
#else
|
||||
GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
virtual ~GLGizmoBase() {}
|
||||
|
||||
bool init() { return on_init(); }
|
||||
@ -115,6 +122,10 @@ 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_svg_file() const { return m_svg_file; }
|
||||
#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(); }
|
||||
|
||||
@ -242,7 +253,11 @@ class GLGizmoRotate3D : public GLGizmoBase
|
||||
std::vector<GLGizmoRotate> m_gizmos;
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& svg_file, 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)); }
|
||||
@ -313,7 +328,11 @@ class GLGizmoScale3D : public GLGizmoBase
|
||||
BoundingBoxf3 m_starting_box;
|
||||
|
||||
public:
|
||||
GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id);
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoScale3D(GLCanvas3D& parent, const std::string& svg_file, 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; }
|
||||
@ -360,7 +379,11 @@ class GLGizmoMove3D : public GLGizmoBase
|
||||
GLUquadricObj* m_quadric;
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoMove3D(GLCanvas3D& parent, const std::string& svg_file, 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; }
|
||||
@ -415,7 +438,11 @@ private:
|
||||
bool is_plane_update_necessary() const;
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoFlatten(GLCanvas3D& parent, const std::string& svg_file, 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;
|
||||
@ -436,6 +463,7 @@ protected:
|
||||
};
|
||||
|
||||
#define SLAGIZMO_IMGUI_MODAL 0
|
||||
|
||||
class GLGizmoSlaSupports : public GLGizmoBase
|
||||
{
|
||||
private:
|
||||
@ -453,7 +481,7 @@ private:
|
||||
igl::AABB<Eigen::MatrixXf,3> m_AABB;
|
||||
|
||||
struct SourceDataSummary {
|
||||
Vec3d mesh_first_point;
|
||||
Geometry::Transformation transformation;
|
||||
};
|
||||
|
||||
// This holds information to decide whether recalculation is necessary:
|
||||
@ -462,7 +490,11 @@ private:
|
||||
mutable Vec3d m_starting_center;
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& svg_file, 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);
|
||||
@ -487,6 +519,7 @@ private:
|
||||
|
||||
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.;
|
||||
@ -500,9 +533,6 @@ private:
|
||||
bool m_unsaved_changes = false;
|
||||
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)
|
||||
#if SLAGIZMO_IMGUI_MODAL
|
||||
bool m_show_modal = false;
|
||||
#endif
|
||||
int m_canvas_width;
|
||||
int m_canvas_height;
|
||||
|
||||
@ -517,6 +547,8 @@ private:
|
||||
void editing_mode_discard_changes();
|
||||
void editing_mode_reload_cache();
|
||||
void get_data_from_backend();
|
||||
void auto_generate();
|
||||
void switch_to_editing_mode();
|
||||
|
||||
protected:
|
||||
void on_set_state() override;
|
||||
@ -555,7 +587,11 @@ class GLGizmoCut : public GLGizmoBase
|
||||
#endif // not ENABLE_IMGUI
|
||||
|
||||
public:
|
||||
#if ENABLE_SVG_ICONS
|
||||
GLGizmoCut(GLCanvas3D& parent, const std::string& svg_file, 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);
|
||||
|
@ -120,13 +120,13 @@ bool GLTexture::load_from_file(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);
|
||||
|
||||
@ -137,6 +137,106 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps)
|
||||
}
|
||||
#endif // ENABLE_TEXTURES_FROM_SVG
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, unsigned int num_states, unsigned int sprite_size_px)
|
||||
{
|
||||
static int pass = 0;
|
||||
++pass;
|
||||
|
||||
reset();
|
||||
|
||||
if (filenames.empty() || (num_states == 0) || (sprite_size_px == 0))
|
||||
return false;
|
||||
|
||||
m_width = (int)sprite_size_px * std::max((int)(num_states), (int)(filenames.size()));
|
||||
m_height = m_width;
|
||||
int n_pixels = m_width * m_height;
|
||||
|
||||
if (n_pixels <= 0)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
std::vector<unsigned char> sprite_data(sprite_size_px * sprite_size_px * 4, 0);
|
||||
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
if (rast == nullptr)
|
||||
{
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
int sprite_id = -1;
|
||||
for (const std::string& filename : filenames)
|
||||
{
|
||||
++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_size_px * 4);
|
||||
|
||||
int sprite_offset_px = sprite_id * sprite_size_px * m_width;
|
||||
for (unsigned int i = 0; i < num_states; ++i)
|
||||
{
|
||||
int state_offset_px = sprite_offset_px + i * sprite_size_px;
|
||||
for (int j = 0; j < sprite_size_px; ++j)
|
||||
{
|
||||
int data_offset = (state_offset_px + j * m_width) * 4;
|
||||
::memcpy((void*)&data.data()[data_offset], (const void*)&sprite_data.data()[j * sprite_size_px * 4], sprite_size_px * 4);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
::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 = filenames.front();
|
||||
|
||||
wxImage output(m_width, m_height);
|
||||
output.InitAlpha();
|
||||
|
||||
for (int h = 0; h < m_height; ++h)
|
||||
{
|
||||
for (int w = 0; w < m_width; ++w)
|
||||
{
|
||||
int px = h * m_width + w;
|
||||
int px_byte = px * 4;
|
||||
output.SetRGB(w, h, data.data()[px_byte + 0], data.data()[px_byte + 1], data.data()[px_byte + 2]);
|
||||
output.SetAlpha(w, h, data.data()[px_byte + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
output.SaveFile("C:/prusa/slic3r/svg_icons/temp/test_" + std::to_string(pass) + ".png", wxBITMAP_TYPE_PNG);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
void GLTexture::reset()
|
||||
{
|
||||
if (m_id != 0)
|
||||
@ -265,13 +365,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 +440,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);
|
||||
|
||||
|
@ -41,6 +41,9 @@ namespace GUI {
|
||||
#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
|
||||
#if ENABLE_SVG_ICONS
|
||||
bool load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, unsigned int num_states, unsigned int sprite_size_px);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
void reset();
|
||||
|
||||
unsigned int get_id() const { return m_id; }
|
||||
|
@ -32,6 +32,9 @@ wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
|
||||
|
||||
GLToolbarItem::Data::Data()
|
||||
: name("")
|
||||
#if ENABLE_SVG_ICONS
|
||||
, svg_file("")
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
, tooltip("")
|
||||
, sprite_id(-1)
|
||||
, is_toggable(false)
|
||||
@ -78,11 +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)
|
||||
{
|
||||
}
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
BackgroundTexture::Metadata::Metadata()
|
||||
: filename("")
|
||||
@ -93,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)
|
||||
@ -101,7 +110,12 @@ 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)
|
||||
@ -111,6 +125,9 @@ GLToolbar::Layout::Layout()
|
||||
GLToolbar::GLToolbar(GLToolbar::EType type)
|
||||
: m_type(type)
|
||||
, m_enabled(false)
|
||||
#if ENABLE_SVG_ICONS
|
||||
, m_icons_texture_dirty(true)
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
{
|
||||
}
|
||||
|
||||
@ -122,8 +139,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;
|
||||
|
||||
@ -131,6 +159,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);
|
||||
@ -186,11 +215,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
|
||||
{
|
||||
@ -411,6 +462,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();
|
||||
@ -455,12 +511,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
|
||||
@ -470,6 +534,26 @@ 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 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;
|
||||
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)
|
||||
{
|
||||
@ -486,6 +570,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;
|
||||
}
|
||||
@ -496,12 +581,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;
|
||||
@ -595,12 +688,20 @@ 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;
|
||||
@ -693,12 +794,20 @@ 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;
|
||||
@ -742,12 +851,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;
|
||||
@ -788,17 +905,32 @@ 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_size = m_icons_texture.get_width();
|
||||
#else
|
||||
unsigned int tex_id = m_icons_texture.texture.get_id();
|
||||
int tex_size = m_icons_texture.texture.get_width();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
#if !ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_size <= 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;
|
||||
@ -899,6 +1031,11 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||
left += scaled_border;
|
||||
top -= scaled_border;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if ((tex_id == 0) || (tex_size <= 0))
|
||||
return;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
// renders icons
|
||||
for (const GLToolbarItem* item : m_items)
|
||||
{
|
||||
@ -911,7 +1048,11 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||
left += separator_stride;
|
||||
else
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, (unsigned int)m_layout.icons_size);
|
||||
#else
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, m_icons_texture.metadata.icon_size);
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
left += icon_stride;
|
||||
}
|
||||
}
|
||||
@ -919,17 +1060,30 @@ 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_size = m_icons_texture.get_width();
|
||||
#else
|
||||
unsigned int tex_id = m_icons_texture.texture.get_id();
|
||||
int tex_size = m_icons_texture.texture.get_width();
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
|
||||
if ((tex_id == 0) || (tex_size <= 0))
|
||||
return;
|
||||
|
||||
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;
|
||||
@ -1042,11 +1196,35 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
||||
top -= separator_stride;
|
||||
else
|
||||
{
|
||||
#if ENABLE_SVG_ICONS
|
||||
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, (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_size, 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& svg_file = item->get_svg_file();
|
||||
if (!svg_file.empty())
|
||||
filenames.push_back(path + svg_file);
|
||||
}
|
||||
|
||||
bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, GLToolbarItem::Num_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,6 +51,9 @@ public:
|
||||
struct Data
|
||||
{
|
||||
std::string name;
|
||||
#if ENABLE_SVG_ICONS
|
||||
std::string svg_file;
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
std::string tooltip;
|
||||
unsigned int sprite_id;
|
||||
bool is_toggable;
|
||||
@ -74,6 +77,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_svg_file() const { return m_data.svg_file; }
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
const std::string& get_tooltip() const { return m_data.tooltip; }
|
||||
|
||||
void do_action(wxEvtHandler *target);
|
||||
@ -96,6 +102,7 @@ private:
|
||||
GLTexture::Quad_UVs get_uvs(unsigned int texture_size, 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
|
||||
@ -114,6 +121,7 @@ struct ItemsIconsTexture
|
||||
GLTexture texture;
|
||||
Metadata metadata;
|
||||
};
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
struct BackgroundTexture
|
||||
{
|
||||
@ -140,6 +148,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,
|
||||
@ -173,7 +185,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;
|
||||
@ -187,7 +204,12 @@ private:
|
||||
|
||||
EType m_type;
|
||||
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;
|
||||
|
||||
@ -197,7 +219,11 @@ public:
|
||||
explicit GLToolbar(EType type);
|
||||
~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);
|
||||
@ -208,7 +234,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);
|
||||
@ -253,6 +284,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
|
||||
|
@ -56,7 +56,7 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
|
||||
|
||||
/* FT_INI */ "INI files (*.ini)|*.ini;*.INI",
|
||||
/* FT_SVG */ "SVG files (*.svg)|*.svg;*.SVG",
|
||||
/* FT_PNGZIP */"Zipped PNG files (*.dwz)|*.dwz;*.DWZ", // This is lame, but that's what we use for SLA
|
||||
/* FT_PNGZIP */"Masked SLA files (*.sl1)|*.sl1;*.SL1",
|
||||
};
|
||||
|
||||
std::string out = defaults[file_type];
|
||||
|
@ -405,8 +405,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);
|
||||
|
@ -557,9 +557,6 @@ void MainFrame::quick_slice(const int qs)
|
||||
}
|
||||
else if (qs & qsSaveAs) {
|
||||
// The following line may die if the output_filename_format template substitution fails.
|
||||
// output_file = sprint->output_filepath;
|
||||
// if (export_svg)
|
||||
// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /;
|
||||
auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")),
|
||||
wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file),
|
||||
qs & qsExportSVG ? file_wildcards(FT_SVG) : file_wildcards(FT_GCODE),
|
||||
@ -575,11 +572,9 @@ void MainFrame::quick_slice(const int qs)
|
||||
wxGetApp().app_config->update_last_output_dir(get_dir_name(output_file));
|
||||
}
|
||||
else if (qs & qsExportPNG) {
|
||||
// output_file = sprint->output_filepath;
|
||||
// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .zip / ;
|
||||
auto dlg = new wxFileDialog(this, _(L("Save zip file as:")),
|
||||
wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)),
|
||||
get_base_name(output_file), "*.zip", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
get_base_name(output_file), "*.sl1", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (dlg->ShowModal() != wxID_OK) {
|
||||
dlg->Destroy();
|
||||
return;
|
||||
|
@ -2142,6 +2142,8 @@ void Plater::priv::export_gcode(fs::path output_path, PrintHostJob upload_job)
|
||||
background_process.schedule_upload(std::move(upload_job));
|
||||
}
|
||||
|
||||
// If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
|
||||
this->background_process.set_task(PrintBase::TaskParams());
|
||||
this->restart_background_process(priv::UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT);
|
||||
}
|
||||
|
||||
@ -2449,8 +2451,15 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
|
||||
|
||||
sidebar->obj_list()->append_menu_item_settings(menu);
|
||||
|
||||
if (q != nullptr)
|
||||
if (q != nullptr) {
|
||||
#ifdef __linux__
|
||||
// For some reason on Linux the menu isn't displayed if position is specified
|
||||
// (even though the position is sane).
|
||||
q->PopupMenu(menu);
|
||||
#else
|
||||
q->PopupMenu(menu, (int)evt.data.x(), (int)evt.data.y());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
|
||||
@ -2614,9 +2623,11 @@ bool Plater::priv::complit_init_part_menu()
|
||||
|
||||
void Plater::priv::init_view_toolbar()
|
||||
{
|
||||
#if !ENABLE_SVG_ICONS
|
||||
ItemsIconsTexture::Metadata icons_data;
|
||||
icons_data.filename = "view_toolbar.png";
|
||||
icons_data.icon_size = 64;
|
||||
#endif // !ENABLE_SVG_ICONS
|
||||
|
||||
BackgroundTexture::Metadata background_data;
|
||||
background_data.filename = "toolbar_background.png";
|
||||
@ -2625,7 +2636,11 @@ void Plater::priv::init_view_toolbar()
|
||||
background_data.right = 16;
|
||||
background_data.bottom = 16;
|
||||
|
||||
#if ENABLE_SVG_ICONS
|
||||
if (!view_toolbar.init(background_data))
|
||||
#else
|
||||
if (!view_toolbar.init(icons_data, background_data))
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
return;
|
||||
|
||||
view_toolbar.set_layout_orientation(GLToolbar::Layout::Bottom);
|
||||
@ -2635,6 +2650,9 @@ void Plater::priv::init_view_toolbar()
|
||||
GLToolbarItem::Data item;
|
||||
|
||||
item.name = "3D";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "add.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]";
|
||||
item.sprite_id = 0;
|
||||
item.action_event = EVT_GLVIEWTOOLBAR_3D;
|
||||
@ -2643,6 +2661,9 @@ void Plater::priv::init_view_toolbar()
|
||||
return;
|
||||
|
||||
item.name = "Preview";
|
||||
#if ENABLE_SVG_ICONS
|
||||
item.svg_file = "remove.svg";
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]";
|
||||
item.sprite_id = 1;
|
||||
item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW;
|
||||
@ -3066,6 +3087,8 @@ void Plater::reslice()
|
||||
unsigned int state = this->p->update_background_process(true);
|
||||
if (state & priv::UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE)
|
||||
this->p->view3D->reload_scene(false);
|
||||
// If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
|
||||
this->p->background_process.set_task(PrintBase::TaskParams());
|
||||
// Only restarts if the state is valid.
|
||||
this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART);
|
||||
}
|
||||
|
@ -465,6 +465,7 @@ const std::vector<std::string>& Preset::sla_print_options()
|
||||
"pad_wall_height",
|
||||
"pad_max_merge_distance",
|
||||
"pad_edge_radius",
|
||||
"pad_wall_slope",
|
||||
"output_filename_format",
|
||||
"default_sla_print_profile",
|
||||
"compatible_printers",
|
||||
|
@ -3288,7 +3288,9 @@ void TabSLAPrint::build()
|
||||
optgroup->append_single_option_line("pad_wall_thickness");
|
||||
optgroup->append_single_option_line("pad_wall_height");
|
||||
optgroup->append_single_option_line("pad_max_merge_distance");
|
||||
optgroup->append_single_option_line("pad_edge_radius");
|
||||
// TODO: Disabling this parameter for the beta release
|
||||
// optgroup->append_single_option_line("pad_edge_radius");
|
||||
optgroup->append_single_option_line("pad_wall_slope");
|
||||
|
||||
page = add_options_page(_(L("Output options")), "page_white_go.png");
|
||||
optgroup = page->new_optgroup(_(L("Output file")));
|
||||
|