Merge remote-tracking branch 'origin/master' into ys_msw_dpi

This commit is contained in:
YuSanka 2019-04-14 13:49:22 +02:00
commit df7ada0199
104 changed files with 2162 additions and 410 deletions

View file

@ -49,6 +49,10 @@ foreach (_cache_var ${_cache_vars})
endif () endif ()
endforeach() endforeach()
if (SLIC3R_GUI)
add_definitions(-DSLIC3R_GUI)
endif ()
if (MSVC) if (MSVC)
if (SLIC3R_MSVC_COMPILE_PARALLEL) if (SLIC3R_MSVC_COMPILE_PARALLEL)
add_compile_options(/MP) add_compile_options(/MP)

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="add_x5F_copies">
<g>
<path fill="#808080" d="M8,2c3.31,0,6,2.69,6,6s-2.69,6-6,6s-6-2.69-6-6S4.69,2,8,2 M8,1C4.13,1,1,4.13,1,8s3.13,7,7,7s7-3.13,7-7
S11.87,1,8,1L8,1z"/>
</g>
<g>
<path fill="#ED6B21" d="M12,8.75H4C3.59,8.75,3.25,8.41,3.25,8S3.59,7.25,4,7.25h8c0.41,0,0.75,0.34,0.75,0.75S12.41,8.75,12,8.75
z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,12.75c-0.41,0-0.75-0.34-0.75-0.75V4c0-0.41,0.34-0.75,0.75-0.75S8.75,3.59,8.75,4v8
C8.75,12.41,8.41,12.75,8,12.75z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 846 B

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="add_x5F_modifer">
<path fill="#808080" d="M10.98,9.78c-0.29,0-0.52,0.23-0.52,0.52v2.09v1.04c0,0.29-0.23,0.52-0.52,0.52H2.62
c-0.29,0-0.53-0.24-0.53-0.53L2.04,6.12c0-0.14,0.05-0.27,0.15-0.37c0.1-0.1,0.23-0.15,0.37-0.15l3.19,0v0
c0.29,0,0.52-0.23,0.52-0.52S6.04,4.55,5.75,4.55H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81,0.16-1.11,0.46
C1.16,5.31,1,5.71,1,6.13l0.04,7.31C1.05,14.3,1.75,15,2.62,15h7.31c0.86,0,1.57-0.7,1.57-1.57v-1.04V10.3
C11.5,10.01,11.27,9.78,10.98,9.78z"/>
<circle fill="#ED6B21" cx="11" cy="5" r="3.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 894 B

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="add_x5F_part">
<g>
<path fill="#ED6B21" d="M11,8.5c-0.28,0-0.5-0.22-0.5-0.5V2c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v6
C11.5,8.28,11.28,8.5,11,8.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M14,5.5H8C7.72,5.5,7.5,5.28,7.5,5S7.72,4.5,8,4.5h6c0.28,0,0.5,0.22,0.5,0.5S14.28,5.5,14,5.5z"/>
</g>
<path fill="#808080" d="M10.98,9.78c-0.29,0-0.52,0.23-0.52,0.52v2.09v1.04c0,0.29-0.23,0.52-0.52,0.52H2.62
c-0.29,0-0.53-0.24-0.53-0.53L2.04,6.12c0-0.14,0.05-0.27,0.15-0.37c0.1-0.1,0.23-0.15,0.37-0.15l3.19,0v0
c0.29,0,0.52-0.23,0.52-0.52S6.04,4.55,5.75,4.55H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81,0.16-1.11,0.46
C1.16,5.31,1,5.71,1,6.13l0.04,7.31C1.05,14.3,1.75,15,2.62,15h7.31c0.86,0,1.57-0.7,1.57-1.57v-1.04V10.3
C11.5,10.01,11.27,9.78,10.98,9.78z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="advanced_x2B_">
<path fill="#808080" d="M10.98,9.78c-0.29,0-0.52,0.23-0.52,0.52v2.09v1.04c0,0.29-0.23,0.52-0.52,0.52H2.62
c-0.29,0-0.53-0.24-0.53-0.53L2.04,6.12c0-0.14,0.05-0.27,0.15-0.37c0.1-0.1,0.23-0.15,0.37-0.15l3.19,0v0
c0.29,0,0.52-0.23,0.52-0.52S6.04,4.55,5.75,4.55H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81,0.16-1.11,0.46
C1.16,5.31,1,5.71,1,6.13l0.04,7.31C1.05,14.3,1.75,15,2.62,15h7.31c0.86,0,1.57-0.7,1.57-1.57v-1.04V10.3
C11.5,10.01,11.27,9.78,10.98,9.78z"/>
<path fill="#ED6B21" d="M13.56,5.38c-0.01-0.13,0.06-0.33,0.15-0.43l0.13-0.15c0.09-0.1,0.12-0.29,0.07-0.42l-0.2-0.48
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.32-0.1-0.41-0.2c-0.09-0.1-0.37-0.45-0.38-0.59l-0.01-0.2
c-0.01-0.14-0.12-0.29-0.25-0.35l-0.48-0.2c-0.13-0.05-0.32-0.02-0.42,0.07L11.06,2.3c-0.1,0.09-0.3,0.16-0.44,0.15
s-0.57-0.06-0.68-0.15L9.79,2.16C9.69,2.07,9.5,2.04,9.37,2.1L8.89,2.3C8.76,2.35,8.65,2.5,8.64,2.64l-0.01,0.2
c-0.01,0.14-0.1,0.32-0.2,0.41c-0.1,0.09-0.45,0.37-0.59,0.38l-0.2,0.01C7.5,3.65,7.35,3.76,7.3,3.89L7.1,4.37
C7.04,4.5,7.07,4.69,7.16,4.79L7.3,4.94c0.09,0.1,0.16,0.3,0.15,0.44C7.44,5.51,7.38,5.95,7.29,6.06L7.16,6.21
C7.07,6.31,7.04,6.5,7.1,6.63l0.2,0.48C7.35,7.24,7.5,7.35,7.64,7.36l0.2,0.01c0.14,0.01,0.32,0.1,0.41,0.2
c0.09,0.1,0.37,0.45,0.38,0.59l0.01,0.2C8.65,8.5,8.76,8.65,8.89,8.7l0.48,0.2C9.5,8.96,9.69,8.93,9.79,8.84L9.94,8.7
c0.1-0.09,0.3-0.16,0.44-0.15c0.14,0.01,0.57,0.06,0.68,0.15l0.15,0.13c0.1,0.09,0.29,0.12,0.42,0.07l0.48-0.2
c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.32,0.2-0.41s0.45-0.37,0.59-0.38l0.2-0.01c0.14-0.01,0.29-0.12,0.35-0.25
l0.2-0.48c0.05-0.13,0.02-0.32-0.07-0.42L13.7,6.06C13.61,5.95,13.56,5.51,13.56,5.38z M10.5,7.55c-1.13,0-2.05-0.92-2.05-2.05
s0.92-2.05,2.05-2.05s2.05,0.92,2.05,2.05S11.63,7.55,10.5,7.55z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="browse">
<path fill="#ED6B21" d="M8.49,2.43c-1.71-1.71-4.49-1.71-6.2,0s-1.71,4.49,0,6.2c1.59,1.59,4.1,1.7,5.82,0.34l1.48,1.48
c0,0-0.36,0.36,0,0.73s3.65,3.65,3.65,3.65s0.36,0.36,0.73,0c0.36-0.36,0.73-0.73,0.73-0.73s0.36-0.36,0-0.73s-3.65-3.65-3.65-3.65
c-0.36-0.36-0.73,0-0.73,0L8.83,8.25C10.19,6.52,10.08,4.02,8.49,2.43z M8.1,8.25c-1.5,1.5-3.93,1.5-5.43,0s-1.5-3.93,0-5.43
s3.93-1.5,5.43,0S9.6,6.75,8.1,8.25z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 777 B

37
resources/icons/copy.svg Normal file
View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="copy">
<g>
<path fill="#ED6B21" d="M115.76,51.2l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.17,118.23,53.67,115.76,51.2z M111.42,54.04h-6.57
v-6.57L111.42,54.04z M115.01,112.47c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.42
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54
V112.47z"/>
<path fill="#ED6B21" d="M53.97,59.13h35.72c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H53.97c-1.4,0-2.54,1.14-2.54,2.54
S52.56,59.13,53.97,59.13z"/>
<path fill="#ED6B21" d="M104.93,69.29H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,69.29,104.93,69.29z"/>
<path fill="#ED6B21" d="M104.93,84.53H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,84.53,104.93,84.53z"/>
<path fill="#ED6B21" d="M104.93,99.77H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,99.77,104.93,99.77z"/>
</g>
<g>
<path fill="#FFFFFF" d="M85.27,20.71l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h17.78c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H15.94c-1.4,0-2.54-1.14-2.54-2.54V15.94
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46V26.1c0,1.4,1.14,2.54,2.54,2.54h12.45c0.16,0.49,0.25,0.93,0.25,1.27
v3.81c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54v-3.81C89.61,27.14,87.75,23.19,85.27,20.71z M74.37,16.99l6.57,6.57
h-6.57V16.99z"/>
<path fill="#FFFFFF" d="M59.21,23.56H23.48c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h35.72c1.4,0,2.54-1.14,2.54-2.54
S60.61,23.56,59.21,23.56z"/>
<path fill="#FFFFFF" d="M28.73,38.8h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,38.8,28.73,38.8z"/>
<path fill="#FFFFFF" d="M28.73,54.04h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,54.04,28.73,54.04z"/>
<path fill="#FFFFFF" d="M28.73,69.29h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,69.29,28.73,69.29z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="copy">
<g>
<path fill="#ED6B21" d="M115.76,51.2l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.17,118.23,53.67,115.76,51.2z M111.42,54.04h-6.57
v-6.57L111.42,54.04z M115.01,112.47c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.42
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54
V112.47z"/>
<path fill="#ED6B21" d="M53.97,59.13h35.72c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H53.97c-1.4,0-2.54,1.14-2.54,2.54
S52.56,59.13,53.97,59.13z"/>
<path fill="#ED6B21" d="M104.93,69.29H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,69.29,104.93,69.29z"/>
<path fill="#ED6B21" d="M104.93,84.53H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,84.53,104.93,84.53z"/>
<path fill="#ED6B21" d="M104.93,99.77H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,99.77,104.93,99.77z"/>
</g>
<g>
<path fill="#808080" d="M85.27,20.71l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h17.78c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H15.94c-1.4,0-2.54-1.14-2.54-2.54V15.94
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46V26.1c0,1.4,1.14,2.54,2.54,2.54h12.45c0.16,0.49,0.25,0.93,0.25,1.27
v3.81c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54v-3.81C89.61,27.14,87.75,23.19,85.27,20.71z M74.37,16.99l6.57,6.57
h-6.57V16.99z"/>
<path fill="#808080" d="M59.21,23.56H23.48c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h35.72c1.4,0,2.54-1.14,2.54-2.54
S60.61,23.56,59.21,23.56z"/>
<path fill="#808080" d="M28.73,38.8h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,38.8,28.73,38.8z"/>
<path fill="#808080" d="M28.73,54.04h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,54.04,28.73,54.04z"/>
<path fill="#808080" d="M28.73,69.29h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54
S30.13,69.29,28.73,69.29z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="delete">
<g>
<path fill="#ED6B21" d="M13,10c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2v3c0,1.1,0.9,2,2,2h6c1.1,0,2-0.9,2-2V10z"/>
</g>
<g>
<path fill="#808080" d="M12,5.01c0.25,0,0.47,0.09,0.62,0.26c0.15,0.17,0.22,0.4,0.2,0.64l-0.64,7.01C12.13,13.49,11.58,14,11,14
H5c-0.58,0-1.13-0.51-1.19-1.08L3.18,5.91c-0.02-0.25,0.05-0.47,0.2-0.64C3.53,5.1,3.75,5.01,4,5.01H12 M12,4.01H4
c-1.1,0-1.92,0.9-1.82,1.99l0.64,7.01C2.92,14.1,3.9,15,5,15h6c1.1,0,2.08-0.9,2.18-1.99L13.82,6C13.92,4.91,13.1,4.01,12,4.01
L12,4.01z"/>
</g>
<g>
<path fill="#808080" d="M13,3.5H3C2.72,3.5,2.5,3.28,2.5,3S2.72,2.5,3,2.5h10c0.28,0,0.5,0.22,0.5,0.5S13.28,3.5,13,3.5z"/>
</g>
<g>
<path fill="#808080" d="M10,2.5H6C5.72,2.5,5.5,2.28,5.5,2S5.72,1.5,6,1.5h4c0.28,0,0.5,0.22,0.5,0.5S10.28,2.5,10,2.5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View 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="#808080" 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="#808080" 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="#808080" 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="#808080" 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="#808080" 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

8
resources/icons/dot.svg Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#808080" cx="8" cy="8" r="3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#FFFFFF" cx="8" cy="8" r="3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="editor">
<g>
<path fill="none" stroke="#101010" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M118.68,8.83L92.1,37.03c-0.75,0.8-2.27,1.46-3.37,1.46H9.44"/>
</g>
<g>
<line fill="none" stroke="#101010" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="90.72" y1="118.69" x2="90.72" y2="38.81"/>
</g>
<g>
<path fill="none" stroke="#101010" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M119.88,91.51v-81.4c0-1.1-0.9-2-2-2H42.92c-1.1,0-2.66,0.61-3.47,1.36L9.59,37.13c-0.81,0.75-1.47,2.26-1.47,3.36v77.39
c0,1.1,0.9,2,2,2h78.61c1.1,0,2.65-0.63,3.44-1.39l27.67-26.82"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<g>
<path fill="#ED6B21" d="M8,11c-0.55,0-1-0.45-1-1V7c0-0.55,0.45-1,1-1s1,0.45,1,1v3C9,10.55,8.55,11,8,11z"/>
</g>
<g>
<circle fill="#ED6B21" cx="8" cy="13" r="1"/>
</g>
<g>
<path fill="#ED6B21" d="M15,15.5H1c-0.18,0-0.34-0.09-0.43-0.24c-0.09-0.15-0.09-0.34-0.01-0.49l7-13c0.17-0.32,0.71-0.32,0.88,0
l7,13c0.08,0.16,0.08,0.34-0.01,0.49C15.34,15.41,15.18,15.5,15,15.5z M1.84,14.5h12.33L8,3.05L1.84,14.5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 781 B

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="export_x5F_config">
<path fill="#808080" d="M14.22,6.61c-0.25-0.12-0.52-0.43-0.6-0.68s-0.32-1.09-0.23-1.35l0.12-0.35c0.09-0.26,0-0.63-0.2-0.83
L12.6,2.7c-0.19-0.19-0.57-0.28-0.83-0.2l-0.35,0.12c-0.26,0.09-0.67,0.06-0.91-0.05s-1-0.54-1.12-0.79L9.22,1.45
C9.1,1.2,8.77,1,8.5,1h-1C7.22,1,6.9,1.2,6.78,1.45L6.61,1.78C6.49,2.02,6.18,2.3,5.93,2.38S4.84,2.7,4.58,2.62L4.23,2.5
C3.97,2.41,3.6,2.5,3.4,2.7L2.7,3.4C2.5,3.6,2.41,3.97,2.5,4.23l0.12,0.35C2.7,4.84,2.68,5.25,2.57,5.49s-0.54,1-0.79,1.12
L1.45,6.78C1.2,6.9,1,7.22,1,7.5v1c0,0.27,0.2,0.6,0.45,0.72l0.33,0.17c0.25,0.12,0.52,0.43,0.6,0.68s0.32,1.09,0.23,1.35
L2.5,11.77c-0.09,0.26,0,0.63,0.2,0.83L3.4,13.3c0.19,0.19,0.57,0.28,0.83,0.2l0.35-0.12c0.26-0.09,0.67-0.06,0.91,0.05
s1,0.54,1.12,0.79l0.17,0.33C6.9,14.8,7.22,15,7.5,15h1c0.27,0,0.6-0.2,0.72-0.45l0.17-0.33c0.12-0.25,0.43-0.52,0.68-0.6
s1.09-0.32,1.35-0.23l0.35,0.12c0.26,0.09,0.63,0,0.83-0.2l0.71-0.71c0.19-0.19,0.28-0.57,0.2-0.83l-0.12-0.35
c-0.09-0.26-0.06-0.67,0.05-0.91s0.54-1,0.79-1.12l0.33-0.17C14.8,9.1,15,8.77,15,8.5v-1c0-0.28-0.2-0.6-0.45-0.72L14.22,6.61z
M8,13c-2.76,0-5-2.24-5-5s2.24-5,5-5s5,2.24,5,5S10.76,13,8,13z"/>
<path fill="#ED6B21" d="M11.65,8.35c0.19-0.19,0.19-0.51,0-0.71L8.92,4.92C8.73,4.73,8.57,4.8,8.57,5.07v1.29
c0,0.28-0.22,0.5-0.5,0.5H4.5C4.22,6.86,4,7.08,4,7.36v1.29c0,0.27,0.22,0.5,0.5,0.5h3.57c0.28,0,0.5,0.22,0.5,0.5v1.29
c0,0.27,0.16,0.34,0.35,0.15L11.65,8.35z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="export_x5F_config_x5F_bundle">
<g>
<path fill="#808080" d="M1.2,12.61c0.11,0.08,0.21,0.22,0.23,0.31c0.02,0.09,0.04,0.43-0.03,0.55s-0.05,0.31,0.03,0.42l0.12,0.17
c0.08,0.11,0.25,0.19,0.39,0.17c0.13-0.02,0.3,0.01,0.38,0.06s0.33,0.28,0.37,0.41c0.04,0.13,0.18,0.25,0.32,0.27l0.21,0.04
c0.14,0.02,0.31-0.05,0.39-0.16s0.22-0.21,0.31-0.23c0.09-0.02,0.43-0.04,0.55,0.03c0.12,0.06,0.31,0.05,0.42-0.03l0.17-0.12
c0.11-0.08,0.19-0.25,0.17-0.39c-0.02-0.13,0.01-0.3,0.06-0.38s0.28-0.33,0.41-0.37c0.13-0.04,0.25-0.18,0.27-0.32l0.04-0.21
c0.02-0.14-0.05-0.31-0.16-0.39c-0.11-0.08-0.21-0.22-0.23-0.31c-0.02-0.09-0.04-0.43,0.03-0.55c0.06-0.12,0.05-0.31-0.03-0.42
L5.5,10.98c-0.08-0.11-0.25-0.19-0.39-0.17c-0.13,0.02-0.3-0.01-0.38-0.06c-0.08-0.05-0.33-0.28-0.37-0.41
c-0.04-0.13-0.18-0.25-0.32-0.27l-0.21-0.04c-0.14-0.02-0.31,0.05-0.39,0.16s-0.22,0.21-0.31,0.23S2.7,10.46,2.58,10.4
c-0.12-0.06-0.31-0.05-0.42,0.03l-0.17,0.12c-0.11,0.08-0.19,0.25-0.17,0.39s-0.01,0.3-0.06,0.38c-0.05,0.08-0.28,0.33-0.41,0.37
c-0.13,0.04-0.25,0.18-0.27,0.32l-0.04,0.21C1.02,12.36,1.09,12.53,1.2,12.61z M3.71,11.42c0.61,0.1,1.02,0.68,0.92,1.28
c-0.1,0.61-0.68,1.02-1.28,0.92c-0.61-0.1-1.02-0.68-0.92-1.28C2.53,11.73,3.1,11.32,3.71,11.42z"/>
</g>
<g>
<path fill="#808080" d="M10.39,4.47c0.13,0.03,0.28,0.13,0.33,0.21c0.05,0.08,0.19,0.38,0.18,0.52s0.07,0.3,0.19,0.38l0.18,0.11
c0.12,0.07,0.31,0.08,0.42,0.01c0.12-0.07,0.28-0.11,0.38-0.09c0.09,0.02,0.41,0.13,0.5,0.24c0.09,0.1,0.26,0.17,0.4,0.13
l0.21-0.05c0.13-0.03,0.27-0.16,0.3-0.29c0.03-0.13,0.13-0.28,0.21-0.33c0.08-0.05,0.38-0.19,0.52-0.18
c0.13,0.01,0.3-0.07,0.38-0.19l0.11-0.18c0.07-0.12,0.08-0.31,0.01-0.42c-0.07-0.12-0.11-0.28-0.09-0.38
c0.02-0.09,0.13-0.41,0.24-0.5c0.1-0.09,0.17-0.26,0.13-0.4l-0.05-0.21c-0.03-0.13-0.16-0.27-0.29-0.3
c-0.13-0.03-0.28-0.13-0.33-0.21s-0.19-0.38-0.18-0.52c0.01-0.13-0.07-0.3-0.19-0.38l-0.18-0.11c-0.12-0.07-0.31-0.08-0.42-0.01
c-0.12,0.07-0.28,0.11-0.38,0.09c-0.09-0.02-0.41-0.13-0.5-0.24c-0.09-0.1-0.26-0.17-0.4-0.13L11.87,1.1
c-0.13,0.03-0.27,0.16-0.3,0.29s-0.13,0.28-0.21,0.33s-0.38,0.19-0.52,0.18s-0.3,0.07-0.38,0.19l-0.11,0.18
c-0.07,0.12-0.08,0.31-0.01,0.42c0.07,0.12,0.11,0.28,0.09,0.38s-0.13,0.41-0.24,0.5c-0.1,0.09-0.17,0.26-0.13,0.4l0.05,0.21
C10.13,4.3,10.26,4.44,10.39,4.47z M12.27,2.43c0.6-0.13,1.2,0.24,1.33,0.84c0.13,0.6-0.24,1.2-0.84,1.33
c-0.6,0.13-1.2-0.24-1.33-0.84C11.3,3.16,11.67,2.56,12.27,2.43z"/>
</g>
<g>
<path fill="#808080" d="M1.85,4.19C1.8,4.32,1.66,4.47,1.53,4.53L1.15,4.71C1.02,4.77,0.92,4.93,0.91,5.06L0.89,5.92
c0,0.14,0.09,0.3,0.21,0.37l0.37,0.2C1.6,6.55,1.73,6.71,1.77,6.84l0.17,0.44C2,7.41,2,7.62,1.96,7.75l-0.15,0.4
C1.76,8.28,1.8,8.47,1.89,8.57l0.58,0.62c0.09,0.1,0.28,0.15,0.41,0.11L3.3,9.17c0.13-0.04,0.34-0.02,0.46,0.04l0.43,0.2
c0.13,0.05,0.28,0.19,0.34,0.32l0.18,0.39c0.06,0.12,0.22,0.23,0.35,0.23l0.85,0.03c0.14,0,0.3-0.09,0.37-0.21l0.2-0.37
c0.07-0.12,0.23-0.25,0.36-0.29l0.44-0.17c0.13-0.06,0.33-0.06,0.46-0.02l0.4,0.15C8.28,9.5,8.47,9.47,8.57,9.37l0.62-0.58
c0.1-0.09,0.15-0.28,0.11-0.41L9.17,7.97C9.13,7.84,9.16,7.63,9.22,7.51l0.2-0.43c0.05-0.13,0.19-0.28,0.32-0.34l0.39-0.18
c0.12-0.06,0.23-0.22,0.23-0.35l0.03-0.85c0-0.14-0.09-0.3-0.21-0.37l-0.37-0.2C9.67,4.71,9.54,4.55,9.49,4.42L9.33,3.98
C9.27,3.85,9.26,3.64,9.31,3.52l0.15-0.4C9.5,2.99,9.47,2.8,9.37,2.7L8.79,2.08c-0.09-0.1-0.28-0.15-0.41-0.11L7.97,2.09
C7.84,2.13,7.63,2.11,7.51,2.05l-0.43-0.2C6.94,1.8,6.79,1.66,6.73,1.53L6.56,1.15C6.5,1.02,6.34,0.92,6.2,0.91L5.35,0.89
c-0.14,0-0.3,0.09-0.37,0.21l-0.2,0.37C4.71,1.6,4.55,1.73,4.42,1.77L3.98,1.94C3.85,2,3.64,2,3.52,1.96l-0.4-0.15
C2.99,1.76,2.8,1.8,2.7,1.89L2.08,2.48c-0.1,0.09-0.15,0.28-0.11,0.41L2.09,3.3c0.04,0.13,0.02,0.34-0.04,0.46L1.85,4.19z
M6.75,3.15c1.37,0.62,1.98,2.23,1.36,3.6s-2.23,1.98-3.6,1.36C3.15,7.5,2.54,5.89,3.15,4.52S5.38,2.54,6.75,3.15z"/>
</g>
<g>
<path fill="#ED6B21" d="M14.65,11.78c0.19-0.19,0.19-0.51,0-0.71l-2.72-2.72c-0.19-0.19-0.35-0.13-0.35,0.15v1.29
c0,0.28-0.22,0.5-0.5,0.5H8.49c-0.28,0-0.5,0.23-0.5,0.5v1.29c0,0.28,0.22,0.5,0.5,0.5h2.58c0.28,0,0.5,0.23,0.5,0.5v1.29
c0,0.28,0.16,0.34,0.35,0.15L14.65,11.78z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="export_x5F_gcode">
<g>
<path fill="#808080" d="M5.02,7.17H9v3.08c0,2.6-1.23,3.72-4.05,3.72S1,12.85,1,10.29V5.54C1,3.12,2.09,2,4.95,2S9,3,9,5.54H6.88
c0-1.11-0.28-1.66-1.92-1.66c-1.54,0-1.83,0.69-1.83,1.77v4.65c0,1.12,0.29,1.77,1.83,1.77c1.54,0,2.08-0.65,2.08-1.82V9.09H5.02
V7.17z"/>
</g>
<path fill="#ED6B21" d="M14.65,8.35c0.19-0.19,0.19-0.51,0-0.71l-4.29-4.29C10.16,3.16,10,3.22,10,3.5v9
c0,0.27,0.16,0.34,0.35,0.15L14.65,8.35z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 804 B

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="export_x5F_plater">
<path fill="#808080" d="M13,2c0.55,0,1,0.45,1,1V13c0,0.55-0.45,1-1,1H3c-0.55,0-1-0.45-1-1V3c0-0.55,0.45-1,1-1H13 M13,1H3
c-1.1,0-2,0.89-2,2V13c0,1.1,0.89,2,2,2H13c1.1,0,2-0.89,2-2V3C15,1.89,14.11,1,13,1L13,1z"/>
<path fill="#ED6B21" d="M11.65,8.35c0.19-0.19,0.19-0.51,0-0.71L8.92,4.92C8.73,4.73,8.57,4.8,8.57,5.07v1.29
c0,0.28-0.22,0.5-0.5,0.5H4.5C4.22,6.86,4,7.08,4,7.36v1.29c0,0.27,0.22,0.5,0.5,0.5h3.57c0.28,0,0.5,0.22,0.5,0.5v1.29
c0,0.27,0.16,0.34,0.35,0.15L11.65,8.35z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 863 B

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="import_x5F_config">
<g>
<path fill="#808080" d="M14.22,6.61c-0.25-0.12-0.52-0.43-0.6-0.68s-0.32-1.09-0.23-1.35l0.12-0.35c0.09-0.26,0-0.63-0.2-0.83
L12.6,2.7c-0.19-0.19-0.57-0.28-0.83-0.2l-0.35,0.12c-0.26,0.09-0.67,0.06-0.91-0.05s-1-0.54-1.12-0.79L9.22,1.45
C9.1,1.2,8.77,1,8.5,1h-1C7.22,1,6.9,1.2,6.78,1.45L6.61,1.78C6.49,2.02,6.18,2.3,5.93,2.38S4.84,2.7,4.58,2.62L4.23,2.5
C3.97,2.41,3.6,2.5,3.4,2.7L2.7,3.4C2.5,3.6,2.41,3.97,2.5,4.23l0.12,0.35C2.7,4.84,2.68,5.25,2.57,5.49s-0.54,1-0.79,1.12
L1.45,6.78C1.2,6.9,1,7.22,1,7.5v1c0,0.27,0.2,0.6,0.45,0.72l0.33,0.17c0.25,0.12,0.52,0.43,0.6,0.68s0.32,1.09,0.23,1.35
L2.5,11.77c-0.09,0.26,0,0.63,0.2,0.83L3.4,13.3c0.19,0.19,0.57,0.28,0.83,0.2l0.35-0.12c0.26-0.09,0.67-0.06,0.91,0.05
s1,0.54,1.12,0.79l0.17,0.33C6.9,14.8,7.22,15,7.5,15h1c0.27,0,0.6-0.2,0.72-0.45l0.17-0.33c0.12-0.25,0.43-0.52,0.68-0.6
s1.09-0.32,1.35-0.23l0.35,0.12c0.26,0.09,0.63,0,0.83-0.2l0.71-0.71c0.19-0.19,0.28-0.57,0.2-0.83l-0.12-0.35
c-0.09-0.26-0.06-0.67,0.05-0.91s0.54-1,0.79-1.12l0.33-0.17C14.8,9.1,15,8.77,15,8.5v-1c0-0.28-0.2-0.6-0.45-0.72L14.22,6.61z
M8,13c-2.76,0-5-2.24-5-5s2.24-5,5-5s5,2.24,5,5S10.76,13,8,13z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,12c-0.55,0-1-0.45-1-1V5c0-0.55,0.45-1,1-1s1,0.45,1,1v6C9,11.55,8.55,12,8,12z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,9H5C4.45,9,4,8.55,4,8s0.45-1,1-1h6c0.55,0,1,0.45,1,1S11.55,9,11,9z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="import_x5F_config_x5F_bundle">
<g>
<g>
<path fill="#808080" d="M1.2,12.61c0.11,0.08,0.21,0.22,0.23,0.31c0.02,0.09,0.04,0.43-0.03,0.55s-0.05,0.31,0.03,0.42l0.12,0.17
c0.08,0.11,0.25,0.19,0.39,0.17c0.13-0.02,0.3,0.01,0.38,0.06s0.33,0.28,0.37,0.41c0.04,0.13,0.18,0.25,0.32,0.27l0.21,0.04
c0.14,0.02,0.31-0.05,0.39-0.16s0.22-0.21,0.31-0.23c0.09-0.02,0.43-0.04,0.55,0.03c0.12,0.06,0.31,0.05,0.42-0.03l0.17-0.12
c0.11-0.08,0.19-0.25,0.17-0.39c-0.02-0.13,0.01-0.3,0.06-0.38s0.28-0.33,0.41-0.37c0.13-0.04,0.25-0.18,0.27-0.32l0.04-0.21
c0.02-0.14-0.05-0.31-0.16-0.39c-0.11-0.08-0.21-0.22-0.23-0.31c-0.02-0.09-0.04-0.43,0.03-0.55c0.06-0.12,0.05-0.31-0.03-0.42
L5.5,10.98c-0.08-0.11-0.25-0.19-0.39-0.17c-0.13,0.02-0.3-0.01-0.38-0.06c-0.08-0.05-0.33-0.28-0.37-0.41
c-0.04-0.13-0.18-0.25-0.32-0.27l-0.21-0.04c-0.14-0.02-0.31,0.05-0.39,0.16s-0.22,0.21-0.31,0.23S2.7,10.46,2.58,10.4
c-0.12-0.06-0.31-0.05-0.42,0.03l-0.17,0.12c-0.11,0.08-0.19,0.25-0.17,0.39s-0.01,0.3-0.06,0.38c-0.05,0.08-0.28,0.33-0.41,0.37
c-0.13,0.04-0.25,0.18-0.27,0.32l-0.04,0.21C1.02,12.36,1.09,12.53,1.2,12.61z M3.71,11.42c0.61,0.1,1.02,0.68,0.92,1.28
c-0.1,0.61-0.68,1.02-1.28,0.92c-0.61-0.1-1.02-0.68-0.92-1.28C2.53,11.73,3.1,11.32,3.71,11.42z"/>
</g>
</g>
<g>
<g>
<path fill="#808080" d="M10.39,4.47c0.13,0.03,0.28,0.13,0.33,0.21c0.05,0.08,0.19,0.38,0.18,0.52s0.07,0.3,0.19,0.38l0.18,0.11
c0.12,0.07,0.31,0.08,0.42,0.01c0.12-0.07,0.28-0.11,0.38-0.09c0.09,0.02,0.41,0.13,0.5,0.24c0.09,0.1,0.26,0.17,0.4,0.13
l0.21-0.05c0.13-0.03,0.27-0.16,0.3-0.29c0.03-0.13,0.13-0.28,0.21-0.33c0.08-0.05,0.38-0.19,0.52-0.18
c0.13,0.01,0.3-0.07,0.38-0.19l0.11-0.18c0.07-0.12,0.08-0.31,0.01-0.42c-0.07-0.12-0.11-0.28-0.09-0.38
c0.02-0.09,0.13-0.41,0.24-0.5c0.1-0.09,0.17-0.26,0.13-0.4l-0.05-0.21c-0.03-0.13-0.16-0.27-0.29-0.3
c-0.13-0.03-0.28-0.13-0.33-0.21s-0.19-0.38-0.18-0.52c0.01-0.13-0.07-0.3-0.19-0.38l-0.18-0.11c-0.12-0.07-0.31-0.08-0.42-0.01
c-0.12,0.07-0.28,0.11-0.38,0.09c-0.09-0.02-0.41-0.13-0.5-0.24c-0.09-0.1-0.26-0.17-0.4-0.13L11.87,1.1
c-0.13,0.03-0.27,0.16-0.3,0.29s-0.13,0.28-0.21,0.33s-0.38,0.19-0.52,0.18s-0.3,0.07-0.38,0.19l-0.11,0.18
c-0.07,0.12-0.08,0.31-0.01,0.42c0.07,0.12,0.11,0.28,0.09,0.38s-0.13,0.41-0.24,0.5c-0.1,0.09-0.17,0.26-0.13,0.4l0.05,0.21
C10.13,4.3,10.26,4.44,10.39,4.47z M12.27,2.43c0.6-0.13,1.2,0.24,1.33,0.84c0.13,0.6-0.24,1.2-0.84,1.33
c-0.6,0.13-1.2-0.24-1.33-0.84C11.3,3.16,11.67,2.56,12.27,2.43z"/>
</g>
</g>
<g>
<g>
<path fill="#808080" d="M1.85,4.19C1.8,4.32,1.66,4.47,1.53,4.53L1.15,4.71C1.02,4.77,0.92,4.93,0.91,5.06L0.89,5.92
c0,0.14,0.09,0.3,0.21,0.37l0.37,0.2C1.6,6.55,1.73,6.71,1.77,6.84l0.17,0.44C2,7.41,2,7.62,1.96,7.75l-0.15,0.4
C1.76,8.28,1.8,8.47,1.89,8.57l0.58,0.62c0.09,0.1,0.28,0.15,0.41,0.11L3.3,9.17c0.13-0.04,0.34-0.02,0.46,0.04l0.43,0.2
c0.13,0.05,0.28,0.19,0.34,0.32l0.18,0.39c0.06,0.12,0.22,0.23,0.35,0.23l0.85,0.03c0.14,0,0.3-0.09,0.37-0.21l0.2-0.37
c0.07-0.12,0.23-0.25,0.36-0.29l0.44-0.17c0.13-0.06,0.33-0.06,0.46-0.02l0.4,0.15C8.28,9.5,8.47,9.47,8.57,9.37l0.62-0.58
c0.1-0.09,0.15-0.28,0.11-0.41L9.17,7.97C9.13,7.84,9.16,7.63,9.22,7.51l0.2-0.43c0.05-0.13,0.19-0.28,0.32-0.34l0.39-0.18
c0.12-0.06,0.23-0.22,0.23-0.35l0.03-0.85c0-0.14-0.09-0.3-0.21-0.37l-0.37-0.2C9.67,4.71,9.54,4.55,9.49,4.42L9.33,3.98
C9.27,3.85,9.26,3.64,9.31,3.52l0.15-0.4C9.5,2.99,9.47,2.8,9.37,2.7L8.79,2.08c-0.09-0.1-0.28-0.15-0.41-0.11L7.97,2.09
C7.84,2.13,7.63,2.11,7.51,2.05l-0.43-0.2C6.94,1.8,6.79,1.66,6.73,1.53L6.56,1.15C6.5,1.02,6.34,0.92,6.2,0.91L5.35,0.89
c-0.14,0-0.3,0.09-0.37,0.21l-0.2,0.37C4.71,1.6,4.55,1.73,4.42,1.77L3.98,1.94C3.85,2,3.64,2,3.52,1.96l-0.4-0.15
C2.99,1.76,2.8,1.8,2.7,1.89L2.08,2.48c-0.1,0.09-0.15,0.28-0.11,0.41L2.09,3.3c0.04,0.13,0.02,0.34-0.04,0.46L1.85,4.19z
M6.75,3.15c1.37,0.62,1.98,2.23,1.36,3.6s-2.23,1.98-3.6,1.36C3.15,7.5,2.54,5.89,3.15,4.52S5.38,2.54,6.75,3.15z"/>
</g>
</g>
<g>
<g>
<path fill="#ED6B21" d="M11,15c-0.55,0-1-0.45-1-1V8c0-0.55,0.45-1,1-1s1,0.45,1,1v6C12,14.55,11.55,15,11,15z"/>
</g>
</g>
<g>
<g>
<path fill="#ED6B21" d="M14,12H8c-0.55,0-1-0.45-1-1s0.45-1,1-1h6c0.55,0,1,0.45,1,1S14.55,12,14,12z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="import_x5F_plater">
<g>
<path fill="#808080" d="M13,2c0.55,0,1,0.45,1,1V13c0,0.55-0.45,1-1,1H3c-0.55,0-1-0.45-1-1V3c0-0.55,0.45-1,1-1H13 M13,1H3
c-1.1,0-2,0.89-2,2V13c0,1.1,0.89,2,2,2H13c1.1,0,2-0.89,2-2V3C15,1.89,14.11,1,13,1L13,1z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,12c-0.55,0-1-0.45-1-1V5c0-0.55,0.45-1,1-1s1,0.45,1,1v6C9,11.55,8.55,12,8,12z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,9H5C4.45,9,4,8.55,4,8s0.45-1,1-1h6c0.55,0,1,0.45,1,1S11.55,9,11,9z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 836 B

View file

@ -5,13 +5,13 @@
<g id="layers"> <g id="layers">
<g> <g>
<g> <g>
<rect x="1" y="13" fill="#FFFFFF" width="14" height="2"/> <rect x="1" y="13" fill="#808080" width="14" height="2"/>
</g> </g>
<g> <g>
<rect x="1" y="10.6" fill="#FFFFFF" width="14" height="1.74"/> <rect x="1" y="10.6" fill="#808080" width="14" height="1.74"/>
</g> </g>
<g> <g>
<rect x="1" y="8.19" fill="#FFFFFF" width="14" height="1.47"/> <rect x="1" y="8.19" fill="#808080" width="14" height="1.47"/>
</g> </g>
<g> <g>
<rect x="1" y="5.79" fill="#ED6B21" width="14" height="1.2"/> <rect x="1" y="5.79" fill="#ED6B21" width="14" height="1.2"/>
@ -20,7 +20,7 @@
<rect x="1" y="3.39" fill="#ED6B21" width="14" height="0.93"/> <rect x="1" y="3.39" fill="#ED6B21" width="14" height="0.93"/>
</g> </g>
<g> <g>
<rect x="1" y="0.99" fill="#FFFFFF" width="14" height="0.67"/> <rect x="1" y="0.99" fill="#808080" width="14" height="0.67"/>
</g> </g>
</g> </g>
</g> </g>

Before

Width:  |  Height:  |  Size: 845 B

After

Width:  |  Height:  |  Size: 845 B

Before After
Before After

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="X">
<path fill="#FF0000" d="M8,1C4.13,1,1,4.13,1,8c0,3.87,3.13,7,7,7s7-3.13,7-7C15,4.13,11.87,1,8,1z M9.26,12l-0.62-1.33L8,8.93
l-0.68,1.83L6.74,12H5.19l1.85-4.04L5.34,4H6.9l0.53,1.3L8,7l0.56-1.67L9.1,4h1.56l-1.7,3.96L10.81,12H9.26z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 596 B

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="Y">
<path fill="#00FF00" d="M8,1C4.13,1,1,4.13,1,8c0,3.87,3.13,7,7,7s7-3.13,7-7C15,4.13,11.87,1,8,1z M8.72,8.65V12H7.3V8.65L5.27,4
h1.55l0.62,1.47l0.58,1.71L8.6,5.43L9.19,4h1.55L8.72,8.65z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="Y_1_">
<path fill="#0000FF" d="M8,1C4.13,1,1,4.13,1,8c0,3.87,3.13,7,7,7s7-3.13,7-7C15,4.13,11.87,1,8,1z M10.42,10.73v1.27H5.41
l3.12-6.71H5.84V4.01h4.75l-3.07,6.72H10.42z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 534 B

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="number_x5F_of_x5F_copies">
<g>
<path fill="#808080" d="M13,2c0.55,0,1,0.45,1,1V13c0,0.55-0.45,1-1,1H3c-0.55,0-1-0.45-1-1V3c0-0.55,0.45-1,1-1H13 M13,1H3
c-1.1,0-2,0.89-2,2V13c0,1.1,0.89,2,2,2H13c1.1,0,2-0.89,2-2V3C15,1.89,14.11,1,13,1L13,1z"/>
</g>
<g>
<path fill="#ED6B21" d="M6,4.5H4C3.72,4.5,3.5,4.28,3.5,4S3.72,3.5,4,3.5h2c0.28,0,0.5,0.22,0.5,0.5S6.28,4.5,6,4.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M12,8.5H8C7.72,8.5,7.5,8.28,7.5,8S7.72,7.5,8,7.5h4c0.28,0,0.5,0.22,0.5,0.5S12.28,8.5,12,8.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M6,12.5H4c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h2c0.28,0,0.5,0.22,0.5,0.5S6.28,12.5,6,12.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M5,12.5c-0.28,0-0.5-0.22-0.5-0.5V4c0-0.28,0.22-0.5,0.5-0.5S5.5,3.72,5.5,4v8C5.5,12.28,5.28,12.5,5,12.5
z"/>
</g>
<g>
<path fill="#ED6B21" d="M10,10.5c-0.28,0-0.5-0.22-0.5-0.5V6c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v4
C10.5,10.28,10.28,10.5,10,10.5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

11
resources/icons/open.svg Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="open">
<path fill="#808080" d="M1.22,14V3c0,0,0-1,1-1s4,0,5,0s1,2,2,2s4,0,4,0s1,0,1,1v2h-1c0,0,0,0,0-1s-1-1-1-1h-3.5c-1,0-1-2-2-2
s-3.5,0-3.5,0c-1,0-1,1-1,1v9v1h1v1c0,0,0,0-1,0S1.22,14,1.22,14z"/>
<path fill="#ED6B21" d="M5,6C4.45,6,3.86,6.43,3.68,6.95l-2.37,7.1C1.14,14.57,1.45,15,2,15h10c0.55,0,1.14-0.43,1.32-0.95
l2.37-7.1C15.86,6.43,15.55,6,15,6L5,6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

83
resources/icons/pad.svg Normal file
View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="pad">
<g>
<path fill="#ED6B21" d="M14,14H2c-0.55,0-1-0.45-1-1s0.45-1,1-1h12c0.55,0,1,0.45,1,1S14.55,14,14,14z"/>
</g>
<g>
<path fill="#808080" d="M8,8.17c-0.4,0-0.8-0.1-1.11-0.31L2.55,4.97C1.95,4.57,1.5,3.72,1.5,3V2c0-0.28,0.22-0.5,0.5-0.5
S2.5,1.72,2.5,2v1c0,0.38,0.29,0.93,0.61,1.14l4.34,2.89c0.29,0.19,0.82,0.19,1.11,0l4.34-2.89C13.21,3.93,13.5,3.38,13.5,3V2
c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1c0,0.72-0.45,1.57-1.05,1.97L9.11,7.86C8.8,8.07,8.4,8.17,8,8.17z"/>
</g>
<g>
<g>
<path fill="#808080" d="M13,11.38c-0.21,0-0.38-0.17-0.38-0.38V7c0-0.21,0.17-0.38,0.38-0.38S13.38,6.79,13.38,7v4
C13.38,11.21,13.21,11.38,13,11.38z"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M12,7.49"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M12,11"/>
</g>
<g>
<path fill="#808080" d="M11,11.38c-0.21,0-0.38-0.17-0.38-0.38V8.12c0-0.21,0.17-0.38,0.38-0.38s0.38,0.17,0.38,0.38V11
C11.38,11.21,11.21,11.38,11,11.38z"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M10,8.79"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M10,11"/>
</g>
<g>
<path fill="#808080" d="M9,11.38c-0.21,0-0.38-0.17-0.38-0.38V9.5c0-0.21,0.17-0.38,0.38-0.38S9.38,9.29,9.38,9.5V11
C9.38,11.21,9.21,11.38,9,11.38z"/>
</g>
</g>
<g>
<g>
<path fill="#808080" d="M3,11.38c-0.21,0-0.38-0.17-0.38-0.38V7c0-0.21,0.17-0.38,0.38-0.38S3.37,6.79,3.37,7v4
C3.37,11.21,3.2,11.38,3,11.38z"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M4,7.49"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M4,11"/>
</g>
<g>
<path fill="#808080" d="M5,11.38c-0.21,0-0.38-0.17-0.38-0.38V8.12c0-0.21,0.17-0.38,0.38-0.38s0.38,0.17,0.38,0.38V11
C5.37,11.21,5.2,11.38,5,11.38z"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M6,8.79"/>
</g>
<g>
<path fill="none" stroke="#808080" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M6,11"/>
</g>
<g>
<path fill="#808080" d="M7,11.38c-0.21,0-0.38-0.17-0.38-0.38V9.5c0-0.21,0.17-0.38,0.38-0.38S7.37,9.29,7.37,9.5V11
C7.37,11.21,7.2,11.38,7,11.38z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

27
resources/icons/paste.svg Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="paste">
<path fill="#FFFFFF" d="M33.73,107.03H15.94c-1.4,0-2.54-1.14-2.54-2.54V23.52c0-1.4,1.14-2.54,2.54-2.54h7.62v5.08
c0,1.4,1.14,2.54,2.54,2.54h45.72c1.4,0,2.54-1.14,2.54-2.54v-5.08h7.62c1.4,0,2.54,1.14,2.54,2.54v10.16
c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54V23.52c0-4.2-3.42-7.62-7.62-7.62h-7.62v-5.08c0-1.4-1.14-2.54-2.54-2.54
H26.11c-1.4,0-2.54,1.14-2.54,2.54v5.08h-7.62c-4.2,0-7.62,3.42-7.62,7.62v80.97c0,4.2,3.42,7.62,7.62,7.62h17.78
c1.4,0,2.54-1.14,2.54-2.54C36.27,108.16,35.13,107.03,33.73,107.03z M28.65,13.36h40.64v10.16H28.65V13.36z"/>
<g>
<path fill="#ED6B21" d="M53.97,59.08h35.72c1.4,0,2.54-1.14,2.54-2.54c0-1.4-1.14-2.54-2.54-2.54H53.97
c-1.4,0-2.54,1.14-2.54,2.54C51.43,57.94,52.56,59.08,53.97,59.08z"/>
<path fill="#ED6B21" d="M104.93,69.24H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96
c1.4,0,2.54-1.14,2.54-2.54C107.47,70.38,106.33,69.24,104.93,69.24z"/>
<path fill="#ED6B21" d="M104.93,99.72H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,99.72,104.93,99.72z"/>
<path fill="#ED6B21" d="M115.75,51.15l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.12,118.23,53.62,115.75,51.15z M104.85,47.43
l6.57,6.57h-6.57V47.43z M115.01,112.42c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.38
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54
V112.42z"/>
<path fill="#ED6B21" d="M104.93,84.48H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96
c1.4,0,2.54-1.14,2.54-2.54C107.47,85.62,106.33,84.48,104.93,84.48z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="paste">
<path fill="#808080" d="M33.73,107.03H15.94c-1.4,0-2.54-1.14-2.54-2.54V23.52c0-1.4,1.14-2.54,2.54-2.54h7.62v5.08
c0,1.4,1.14,2.54,2.54,2.54h45.72c1.4,0,2.54-1.14,2.54-2.54v-5.08h7.62c1.4,0,2.54,1.14,2.54,2.54v10.16
c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54V23.52c0-4.2-3.42-7.62-7.62-7.62h-7.62v-5.08c0-1.4-1.14-2.54-2.54-2.54
H26.11c-1.4,0-2.54,1.14-2.54,2.54v5.08h-7.62c-4.2,0-7.62,3.42-7.62,7.62v80.97c0,4.2,3.42,7.62,7.62,7.62h17.78
c1.4,0,2.54-1.14,2.54-2.54C36.27,108.16,35.13,107.03,33.73,107.03z M28.65,13.36h40.64v10.16H28.65V13.36z"/>
<g>
<path fill="#ED6B21" d="M53.97,59.08h35.72c1.4,0,2.54-1.14,2.54-2.54c0-1.4-1.14-2.54-2.54-2.54H53.97
c-1.4,0-2.54,1.14-2.54,2.54C51.43,57.94,52.56,59.08,53.97,59.08z"/>
<path fill="#ED6B21" d="M104.93,69.24H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96
c1.4,0,2.54-1.14,2.54-2.54C107.47,70.38,106.33,69.24,104.93,69.24z"/>
<path fill="#ED6B21" d="M104.93,99.72H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54
S106.33,99.72,104.93,99.72z"/>
<path fill="#ED6B21" d="M115.75,51.15l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04
c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.12,118.23,53.62,115.75,51.15z M104.85,47.43
l6.57,6.57h-6.57V47.43z M115.01,112.42c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.38
c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54
V112.42z"/>
<path fill="#ED6B21" d="M104.93,84.48H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96
c1.4,0,2.54-1.14,2.54-2.54C107.47,85.62,106.33,84.48,104.93,84.48z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="plater">
<path fill="#808080" d="M13,2c0.55,0,1,0.45,1,1V13c0,0.55-0.45,1-1,1H3c-0.55,0-1-0.45-1-1V3c0-0.55,0.45-1,1-1H13 M13,1H3
c-1.1,0-2,0.89-2,2V13c0,1.1,0.89,2,2,2H13c1.1,0,2-0.89,2-2V3C15,1.89,14.11,1,13,1L13,1z"/>
<path fill="#ED6B21" d="M8.42,3.28c-0.23-0.15-0.6-0.15-0.83,0l-3.46,2.3C3.9,5.73,3.71,6.08,3.71,6.36v1.85c0,0.28,0,0.54,0,0.58
s0,0.31,0,0.58v0.27c0,0.27,0.19,0.62,0.42,0.78l3.46,2.3c0.23,0.15,0.6,0.15,0.83,0l3.46-2.3c0.23-0.15,0.42-0.5,0.42-0.78V9.38
c0-0.28,0-0.54,0-0.58s0-0.31,0-0.58V6.36c0-0.28-0.19-0.62-0.42-0.78L8.42,3.28z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 920 B

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="preview">
<g>
<path fill="#101010" d="M90.72,121.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,121.23,91.11,121.38,90.72,121.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,111.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,111.23,91.11,111.38,90.72,111.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,101.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12l-29.16,28.57C91.49,101.23,91.11,101.38,90.72,101.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,91.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,90.95C91.49,91.23,91.11,91.38,90.72,91.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,81.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,80.95C91.49,81.23,91.11,81.38,90.72,81.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,71.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,70.95C91.49,71.23,91.11,71.38,90.72,71.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M90.72,61.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,60.95C91.49,61.23,91.11,61.38,90.72,61.38z"/>
</g>
<g>
<path fill="#101010" d="M90.72,51.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,50.95C91.49,51.23,91.11,51.38,90.72,51.38z"/>
</g>
<g>
<g>
<path fill="#101010" d="M88.72,41.38H9.18c-1.68,0-2.22-0.95-2.37-1.36s-0.37-1.48,0.89-2.59L38.43,10.5
c1.1-0.96,3.03-1.69,4.49-1.69h75.85c1.65,0,2.22,0.94,2.38,1.34s0.42,1.47-0.75,2.63c0,0,0,0,0,0L93.2,39.55
C92.14,40.59,90.21,41.38,88.72,41.38z M11.17,38.38h77.55c0.71,0,1.87-0.47,2.37-0.97l26.01-25.6H42.92
c-0.74,0-1.96,0.46-2.51,0.95L11.17,38.38z M118.89,11.82C118.89,11.82,118.89,11.82,118.89,11.82
C118.89,11.82,118.89,11.82,118.89,11.82z M119.34,11.71L119.34,11.71L119.34,11.71z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="printer">
<rect x="1" y="1" fill="#FFFFFF" width="1" height="14"/>
<rect x="14" y="1" fill="#FFFFFF" width="1" height="14"/>
<rect x="1" y="5" fill="#FFFFFF" width="14" height="1"/>
<rect x="1" y="1" fill="#FFFFFF" width="14" height="1"/>
<rect x="1" y="13" fill="#FFFFFF" width="14" height="2"/>
<rect x="3" y="4" fill="#ED6B21" width="4" height="4"/>
<polygon fill="#ED6B21" points="5,9 4,8 6,8 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before After
Before After

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="slice">
<path fill="#808080" d="M14.22,6.61c-0.25-0.12-0.52-0.43-0.6-0.68s-0.32-1.09-0.23-1.35l0.12-0.35c0.09-0.26,0-0.63-0.2-0.83
L12.6,2.7c-0.19-0.19-0.57-0.28-0.83-0.2l-0.35,0.12c-0.26,0.09-0.67,0.06-0.91-0.05s-1-0.54-1.12-0.79L9.22,1.45
C9.1,1.2,8.77,1,8.5,1h-1C7.22,1,6.9,1.2,6.78,1.45L6.61,1.78C6.49,2.02,6.18,2.3,5.93,2.38S4.84,2.7,4.58,2.62L4.23,2.5
C3.97,2.41,3.6,2.5,3.4,2.7L2.7,3.4C2.5,3.6,2.41,3.97,2.5,4.23l0.12,0.35C2.7,4.84,2.68,5.25,2.57,5.49s-0.54,1-0.79,1.12
L1.45,6.78C1.2,6.9,1,7.22,1,7.5v1c0,0.27,0.2,0.6,0.45,0.72l0.33,0.17c0.25,0.12,0.52,0.43,0.6,0.68s0.32,1.09,0.23,1.35
L2.5,11.77c-0.09,0.26,0,0.63,0.2,0.83l0.7,0.7c0.19,0.19,0.57,0.28,0.83,0.2l0.35-0.12c0.26-0.09,0.67-0.06,0.91,0.05
s1,0.54,1.12,0.79l0.17,0.33C6.9,14.8,7.22,15,7.5,15h1c0.27,0,0.6-0.2,0.72-0.45l0.17-0.33c0.12-0.25,0.43-0.52,0.68-0.6
s1.09-0.32,1.35-0.23l0.35,0.12c0.26,0.09,0.63,0,0.83-0.2l0.71-0.71c0.19-0.19,0.28-0.57,0.2-0.83l-0.12-0.35
c-0.09-0.26-0.06-0.67,0.05-0.91s0.54-1,0.79-1.12l0.33-0.17C14.8,9.1,15,8.77,15,8.5v-1c0-0.28-0.2-0.6-0.45-0.72L14.22,6.61z
M8,13c-2.76,0-5-2.24-5-5s2.24-5,5-5s5,2.24,5,5S10.76,13,8,13z"/>
<path fill="#ED6B21" d="M6.86,5.51C6.39,5.23,6,5.45,6,6v4c0,0.55,0.39,0.77,0.86,0.49l3.29-1.97c0.47-0.28,0.47-0.75,0-1.03
L6.86,5.51z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="remove_x5F_copies">
<g>
<path fill="#808080" d="M8,2c3.31,0,6,2.69,6,6s-2.69,6-6,6s-6-2.69-6-6S4.69,2,8,2 M8,1C4.13,1,1,4.13,1,8s3.13,7,7,7s7-3.13,7-7
S11.87,1,8,1L8,1z"/>
</g>
<g>
<path fill="#ED6B21" d="M12,8.75H4C3.59,8.75,3.25,8.41,3.25,8S3.59,7.25,4,7.25h8c0.41,0,0.75,0.34,0.75,0.75S12.41,8.75,12,8.75
z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 689 B

View 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="#808080" 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

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="set_x5F_separate_x5F_obj">
<g>
<path fill="#808080" d="M6,15.49H2.04c-0.83,0-1.5-0.67-1.51-1.5l-0.02-3.96c0-0.4,0.15-0.78,0.44-1.06C1.22,8.69,1.6,8.53,2,8.53
l4,0c0.83,0,1.5,0.67,1.5,1.5v3.96C7.5,14.82,6.83,15.49,6,15.49z M6,9.53l-4,0c-0.13,0-0.26,0.05-0.35,0.15
C1.56,9.77,1.51,9.9,1.51,10.03l0.02,3.96c0,0.28,0.23,0.5,0.51,0.5H6c0.28,0,0.5-0.22,0.5-0.5v-3.96C6.5,9.75,6.28,9.53,6,9.53z"
/>
</g>
<g>
<path fill="#808080" d="M6,7.5H2.04c-0.83,0-1.5-0.67-1.51-1.5L0.51,2.04c0-0.4,0.15-0.78,0.44-1.06C1.22,0.7,1.6,0.54,2,0.54l4,0
c0.83,0,1.5,0.67,1.5,1.5V6C7.5,6.83,6.83,7.5,6,7.5z M6,1.54l-4,0c-0.13,0-0.26,0.05-0.35,0.15C1.56,1.78,1.51,1.9,1.51,2.04
L1.53,6c0,0.28,0.23,0.5,0.51,0.5H6c0.28,0,0.5-0.22,0.5-0.5V2.04C6.5,1.76,6.28,1.54,6,1.54z"/>
</g>
<g>
<path fill="#ED6B21" d="M14,7.5h-3.96c-0.83,0-1.5-0.67-1.51-1.5L8.51,2.04c0-0.4,0.15-0.78,0.44-1.06C9.22,0.7,9.6,0.54,10,0.54
l4,0c0.83,0,1.5,0.67,1.5,1.5V6C15.5,6.83,14.83,7.5,14,7.5z M14,1.54l-4,0c-0.13,0-0.26,0.05-0.35,0.15
C9.56,1.78,9.5,1.9,9.51,2.04L9.53,6c0,0.27,0.23,0.5,0.51,0.5H14c0.28,0,0.5-0.22,0.5-0.5V2.04C14.5,1.76,14.28,1.54,14,1.54z"/>
</g>
<g>
<path fill="#808080" d="M14,15.5h-3.96c-0.83,0-1.5-0.67-1.51-1.5l-0.02-3.96c0-0.4,0.15-0.78,0.44-1.06
C9.22,8.7,9.6,8.54,10,8.54l4,0c0.83,0,1.5,0.67,1.5,1.5V14C15.5,14.83,14.83,15.5,14,15.5z M14,9.54l-4,0
c-0.13,0-0.26,0.05-0.35,0.15C9.56,9.78,9.5,9.9,9.51,10.04L9.53,14c0,0.27,0.23,0.5,0.51,0.5H14c0.28,0,0.5-0.22,0.5-0.5v-3.96
C14.5,9.76,14.28,9.54,14,9.54z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="split_x5F_object_x5F_small">
<path fill="#808080" d="M10.98,7.22c-0.29,0-0.52-0.23-0.52-0.52V4.61V3.57c0-0.29-0.23-0.52-0.52-0.52H2.62
c-0.29,0-0.53,0.24-0.53,0.53l-0.04,7.31c0,0.14,0.05,0.27,0.15,0.37c0.1,0.1,0.23,0.15,0.37,0.15l3.19,0v0
c0.29,0,0.52,0.23,0.52,0.52s-0.23,0.52-0.52,0.52H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81-0.16-1.11-0.46
C1.16,11.69,1,11.29,1,10.87l0.04-7.31C1.05,2.7,1.75,2,2.62,2h7.31c0.86,0,1.57,0.7,1.57,1.57v1.04V6.7
C11.5,6.99,11.27,7.22,10.98,7.22z"/>
<g>
<path fill="#ED6B21" d="M13.53,8H7.47C7.21,8,7,8.21,7,8.47v6.07C7,14.79,7.21,15,7.47,15h6.07c0.26,0,0.47-0.21,0.47-0.47V8.47
C14,8.21,13.79,8,13.53,8z M12.36,12.68c0,1.14-0.57,1.65-1.88,1.65s-1.84-0.51-1.84-1.65v-2.33c0-1.17,0.51-1.65,1.84-1.65
c1.33,0,1.88,0.48,1.88,1.65V12.68z"/>
<path fill="#ED6B21" d="M10.47,9.57c-0.72,0-0.85,0.32-0.85,0.82v2.23c0,0.52,0.14,0.82,0.85,0.82c0.72,0,0.89-0.3,0.89-0.82V10.4
C11.37,9.9,11.24,9.57,10.47,9.57z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="split_x5F_parts_x5F_small">
<path fill="#808080" d="M10.98,7.22c-0.29,0-0.52-0.23-0.52-0.52V4.61V3.57c0-0.29-0.23-0.52-0.52-0.52H2.62
c-0.29,0-0.53,0.24-0.53,0.53l-0.04,7.31c0,0.14,0.05,0.27,0.15,0.37c0.1,0.1,0.23,0.15,0.37,0.15l3.19,0v0
c0.29,0,0.52,0.23,0.52,0.52s-0.23,0.52-0.52,0.52H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81-0.16-1.11-0.46
C1.16,11.69,1,11.29,1,10.87l0.04-7.31C1.05,2.7,1.75,2,2.62,2h7.31c0.86,0,1.57,0.7,1.57,1.57v1.04V6.7
C11.5,6.99,11.27,7.22,10.98,7.22z"/>
<g>
<path fill="#ED6B21" d="M13.53,8H7.47C7.21,8,7,8.21,7,8.47v6.07C7,14.79,7.21,15,7.47,15h6.07c0.26,0,0.47-0.21,0.47-0.47V8.47
C14,8.21,13.79,8,13.53,8z M12.19,10.89c0,1.16-0.65,1.69-1.99,1.69H9.81v1.72H8.79V8.7h1.41c1.35,0,1.99,0.49,1.99,1.67V10.89z"
/>
<path fill="#ED6B21" d="M10.21,9.62H9.81v2h0.39c0.73,0,0.97-0.25,0.97-0.78v-0.41C11.17,9.89,10.99,9.62,10.21,9.62z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="support_x5F_blocker">
<g>
<path fill="#808080" d="M8,8.17c-0.4,0-0.8-0.1-1.11-0.31L2.55,4.97C1.95,4.57,1.5,3.72,1.5,3V2c0-0.28,0.22-0.5,0.5-0.5
S2.5,1.72,2.5,2v1c0,0.38,0.29,0.93,0.61,1.14l4.34,2.89c0.29,0.19,0.82,0.19,1.11,0l4.34-2.89C13.21,3.93,13.5,3.38,13.5,3V2
c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1c0,0.72-0.45,1.57-1.05,1.97L9.11,7.86C8.8,8.07,8.4,8.17,8,8.17z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,8.38c-0.12,0-0.24-0.06-0.31-0.17c-0.11-0.17-0.07-0.41,0.1-0.52l3-2c0.12-0.08,0.26-0.08,0.38-0.02
s0.2,0.19,0.2,0.33v2c0,0.21-0.17,0.38-0.38,0.38S13.62,8.21,13.62,8V6.7l-2.42,1.61C11.14,8.35,11.07,8.38,11,8.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M14,14.38h-3c-0.21,0-0.38-0.17-0.38-0.38s0.17-0.38,0.38-0.38h2.62V13c0-0.21,0.17-0.38,0.38-0.38
s0.38,0.17,0.38,0.38v1C14.38,14.21,14.21,14.38,14,14.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M9,14.38H7c-0.21,0-0.38-0.17-0.38-0.38S6.79,13.62,7,13.62h2c0.21,0,0.38,0.17,0.38,0.38
S9.21,14.38,9,14.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M14,11.38c-0.21,0-0.38-0.17-0.38-0.38v-1c0-0.21,0.17-0.38,0.38-0.38s0.38,0.17,0.38,0.38v1
C14.38,11.21,14.21,11.38,14,11.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,10.38c-0.13,0-0.25-0.06-0.32-0.18C7.57,10.02,7.63,9.79,7.8,9.68l1.62-1C9.6,8.57,9.83,8.63,9.94,8.8
c0.11,0.18,0.05,0.41-0.12,0.52l-1.62,1C8.14,10.36,8.07,10.38,8,10.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M5,8.38c-0.07,0-0.14-0.02-0.21-0.06L2.38,6.7V8c0,0.21-0.17,0.38-0.38,0.38S1.62,8.21,1.62,8V6
c0-0.14,0.08-0.27,0.2-0.33C1.95,5.6,2.09,5.61,2.21,5.69l3,2c0.17,0.11,0.22,0.35,0.1,0.52C5.24,8.32,5.12,8.38,5,8.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M5,14.38H2c-0.21,0-0.38-0.17-0.38-0.38v-1c0-0.21,0.17-0.38,0.38-0.38S2.38,12.79,2.38,13v0.62H5
c0.21,0,0.38,0.17,0.38,0.38S5.21,14.38,5,14.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M2,11.38c-0.21,0-0.38-0.17-0.38-0.38v-1c0-0.21,0.17-0.38,0.38-0.38S2.38,9.79,2.38,10v1
C2.38,11.21,2.21,11.38,2,11.38z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,10.38c-0.07,0-0.14-0.02-0.2-0.06l-1.62-1C6.01,9.21,5.96,8.98,6.06,8.8C6.17,8.63,6.4,8.57,6.58,8.68
l1.62,1c0.18,0.11,0.23,0.34,0.12,0.52C8.25,10.31,8.13,10.38,8,10.38z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="support_x5F_enfocer">
<g>
<path fill="#808080" d="M8,8.17c-0.4,0-0.8-0.1-1.11-0.31L2.55,4.97C1.95,4.57,1.5,3.72,1.5,3V2c0-0.28,0.22-0.5,0.5-0.5
S2.5,1.72,2.5,2v1c0,0.38,0.29,0.93,0.61,1.14l4.34,2.89c0.29,0.19,0.82,0.19,1.11,0l4.34-2.89C13.21,3.93,13.5,3.38,13.5,3V2
c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1c0,0.72-0.45,1.57-1.05,1.97L9.11,7.86C8.8,8.07,8.4,8.17,8,8.17z"/>
</g>
<g>
<path fill="#ED6B21" d="M13,14.5H3c-0.83,0-1.5-0.67-1.5-1.5V7c0-0.45,0.19-0.81,0.51-0.98c0.32-0.17,0.72-0.13,1.1,0.12
l4.34,2.89c0.29,0.19,0.82,0.19,1.11,0l4.34-2.89c0.38-0.25,0.78-0.3,1.1-0.12C14.31,6.19,14.5,6.55,14.5,7v6
C14.5,13.83,13.83,14.5,13,14.5z M2.5,6.94c0,0.02,0,0.04,0,0.06v6c0,0.28,0.22,0.5,0.5,0.5h10c0.28,0,0.5-0.22,0.5-0.5V7
c0-0.02,0-0.04,0-0.06c-0.02,0.01-0.03,0.02-0.05,0.03L9.11,9.86c-0.62,0.41-1.6,0.41-2.22,0L2.55,6.97
C2.54,6.96,2.52,6.95,2.5,6.94z M8.83,9.45L8.83,9.45L8.83,9.45z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

37
resources/icons/test.svg Normal file
View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="test">
<g>
<path fill="#808080" d="M13,1.5h-1.5v1h1v12h-9v-12h1v-1H3C2.72,1.5,2.5,1.72,2.5,2v13c0,0.28,0.22,0.5,0.5,0.5h10
c0.28,0,0.5-0.22,0.5-0.5V2C13.5,1.72,13.28,1.5,13,1.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,8.5H5C4.72,8.5,4.5,8.28,4.5,8V5c0-0.28,0.22-0.5,0.5-0.5h3c0.28,0,0.5,0.22,0.5,0.5v3
C8.5,8.28,8.28,8.5,8,8.5z M5.5,7.5h2v-2h-2V7.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M8,13.5H5c-0.28,0-0.5-0.22-0.5-0.5v-3c0-0.28,0.22-0.5,0.5-0.5h3c0.28,0,0.5,0.22,0.5,0.5v3
C8.5,13.28,8.28,13.5,8,13.5z M5.5,12.5h2v-2h-2V12.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,5.5h-1C9.72,5.5,9.5,5.28,9.5,5S9.72,4.5,10,4.5h1c0.28,0,0.5,0.22,0.5,0.5S11.28,5.5,11,5.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,7.5h-1C9.72,7.5,9.5,7.28,9.5,7S9.72,6.5,10,6.5h1c0.28,0,0.5,0.22,0.5,0.5S11.28,7.5,11,7.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,10.5h-1c-0.28,0-0.5-0.22-0.5-0.5S9.72,9.5,10,9.5h1c0.28,0,0.5,0.22,0.5,0.5S11.28,10.5,11,10.5z"/>
</g>
<g>
<path fill="#ED6B21" d="M11,12.5h-1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h1c0.28,0,0.5,0.22,0.5,0.5S11.28,12.5,11,12.5z"/>
</g>
<g>
<g>
<path fill="#808080" d="M11,3.5H5C4.72,3.5,4.5,3.28,4.5,3V1c0-0.28,0.22-0.5,0.5-0.5h6c0.28,0,0.5,0.22,0.5,0.5v2
C11.5,3.28,11.28,3.5,11,3.5z M5.5,2.5h5v-1h-5V2.5z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="gueue">
<g>
<path fill="#808080" d="M6,15.49H2.04c-0.83,0-1.5-0.67-1.51-1.5l-0.02-3.96c0-0.4,0.15-0.78,0.44-1.06C1.22,8.69,1.6,8.53,2,8.53
l4,0c0.83,0,1.5,0.67,1.5,1.5v3.96C7.5,14.82,6.83,15.49,6,15.49z M6,9.53l-4,0c-0.13,0-0.26,0.05-0.35,0.15
C1.56,9.77,1.51,9.9,1.51,10.03l0.02,3.96c0,0.28,0.23,0.5,0.51,0.5H6c0.28,0,0.5-0.22,0.5-0.5v-3.96C6.5,9.75,6.28,9.53,6,9.53z"
/>
</g>
<g>
<path fill="#808080" d="M6,7.5H2.04c-0.83,0-1.5-0.67-1.51-1.5L0.51,2.04c0-0.4,0.15-0.78,0.44-1.06C1.22,0.7,1.6,0.54,2,0.54l4,0
c0,0,0,0,0,0c0.4,0,0.77,0.16,1.06,0.44C7.34,1.26,7.5,1.64,7.5,2.04V6C7.5,6.83,6.83,7.5,6,7.5z M6,1.54C6,1.54,6,1.54,6,1.54
l-4,0c-0.13,0-0.26,0.05-0.35,0.15C1.56,1.78,1.51,1.9,1.51,2.04L1.53,6c0,0.28,0.23,0.5,0.51,0.5H6c0.28,0,0.5-0.22,0.5-0.5V2.04
c0-0.13-0.05-0.26-0.15-0.35C6.26,1.59,6.13,1.54,6,1.54z"/>
</g>
<g>
<path fill="#808080" d="M14,7.5h-3.96c-0.83,0-1.5-0.67-1.51-1.5L8.51,2.04c0-0.4,0.15-0.78,0.44-1.06C9.22,0.7,9.6,0.54,10,0.54
l4,0h0c0.4,0,0.78,0.16,1.06,0.44c0.28,0.28,0.44,0.66,0.44,1.06V6C15.5,6.83,14.83,7.5,14,7.5z M14,1.54C14,1.54,14,1.54,14,1.54
l-4,0c-0.13,0-0.26,0.05-0.35,0.15C9.56,1.78,9.5,1.9,9.51,2.04L9.53,6c0,0.27,0.23,0.5,0.51,0.5H14c0.28,0,0.5-0.22,0.5-0.5V2.04
c0-0.13-0.05-0.26-0.15-0.35S14.13,1.54,14,1.54z"/>
</g>
<path fill="#ED6B21" d="M12,8.5c-1.93,0-3.5,1.57-3.5,3.5s1.57,3.5,3.5,3.5s3.5-1.57,3.5-3.5S13.93,8.5,12,8.5z M13.45,12.58H12
c-0.09,0-0.17-0.02-0.24-0.06c-0.02-0.01-0.04-0.02-0.05-0.04c-0.05-0.03-0.1-0.07-0.14-0.12c-0.01-0.01-0.02-0.01-0.03-0.02
l-1.25-1.67c-0.19-0.26-0.14-0.62,0.12-0.82c0.26-0.19,0.62-0.14,0.82,0.12l1.07,1.43h1.17c0.32,0,0.58,0.26,0.58,0.58
C14.04,12.32,13.78,12.58,13.45,12.58z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -3,22 +3,41 @@
<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" <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="advanced_x2B_wrench"> <g id="advanced_x2B_wrench">
<path fill="#808080" d="M7.39,3.69C7.32,3.46,7.23,3.24,7.11,3.03l0.22-0.65L6.62,1.67L5.97,1.89C5.76,1.77,5.54,1.68,5.31,1.61 <g>
L5,1H4L3.69,1.61C3.46,1.68,3.24,1.77,3.03,1.89L2.38,1.67L1.67,2.38l0.22,0.65C1.77,3.24,1.68,3.46,1.61,3.69L1,4v1l0.61,0.31 <path fill="#808080" d="M7.61,3.81c-0.12-0.06-0.26-0.21-0.3-0.34S7.15,2.92,7.19,2.79l0.06-0.17c0.04-0.13,0-0.32-0.1-0.41
c0.07,0.23,0.16,0.46,0.27,0.67L1.67,6.62l0.71,0.71l0.65-0.22c0.21,0.12,0.43,0.21,0.67,0.28L4,8h1l0.31-0.61 L6.8,1.85c-0.1-0.1-0.28-0.14-0.41-0.1L6.21,1.81C6.08,1.85,5.88,1.84,5.76,1.78s-0.5-0.27-0.56-0.39L5.11,1.22
c0.23-0.07,0.46-0.16,0.67-0.28l0.65,0.22l0.71-0.71L7.11,5.97c0.12-0.21,0.21-0.43,0.27-0.67L8,5V4L7.39,3.69z"/> C5.05,1.1,4.89,1,4.75,1h-0.5c-0.14,0-0.3,0.1-0.36,0.22L3.81,1.39c-0.06,0.12-0.21,0.26-0.34,0.3S2.92,1.85,2.79,1.81L2.62,1.75
<path fill="#808080" d="M12.4,2.49c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51L11.39,1.2c-0.15-0.08-0.31-0.15-0.48-0.2 c-0.13-0.04-0.32,0-0.41,0.1L1.85,2.2c-0.1,0.1-0.14,0.28-0.1,0.41l0.06,0.17c0.04,0.13,0.03,0.33-0.03,0.45s-0.27,0.5-0.39,0.56
l-0.22-0.44H9.98L9.76,1C9.59,1.05,9.43,1.11,9.28,1.2L8.82,1.04L8.31,1.55l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48L7.83,2.71 L1.22,3.89C1.1,3.95,1,4.11,1,4.25v0.5c0,0.14,0.1,0.3,0.22,0.36l0.17,0.08c0.12,0.06,0.26,0.21,0.3,0.34s0.16,0.54,0.12,0.67
v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48L8.31,4.58l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44h0.71 L1.75,6.38c-0.04,0.13,0,0.32,0.1,0.41L2.2,7.15c0.1,0.1,0.28,0.14,0.41,0.1l0.17-0.06c0.13-0.04,0.33-0.03,0.45,0.03
l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15l0.51-0.51L12.2,4.12c0.08-0.15,0.15-0.31,0.2-0.48l0.44-0.22V2.71L12.4,2.49z" s0.5,0.27,0.56,0.39l0.08,0.17C3.95,7.9,4.11,8,4.25,8h0.5c0.14,0,0.3-0.1,0.36-0.22l0.08-0.17c0.06-0.12,0.21-0.26,0.34-0.3
/> s0.54-0.16,0.67-0.12l0.17,0.06c0.13,0.04,0.32,0,0.41-0.1L7.15,6.8c0.1-0.1,0.14-0.28,0.1-0.41L7.19,6.21
<path fill="#ED6B21" d="M14.36,10.66c0.04-0.34,0.04-0.68,0-1.02L15,8.91L14.46,7.6l-0.97-0.07c-0.21-0.27-0.45-0.51-0.72-0.72 C7.15,6.08,7.16,5.88,7.22,5.76s0.27-0.5,0.39-0.56l0.17-0.08C7.9,5.05,8,4.89,8,4.75v-0.5c0-0.14-0.1-0.3-0.22-0.36L7.61,3.81z
L12.7,5.84L11.39,5.3l-0.73,0.64c-0.34-0.04-0.68-0.04-1.02,0L8.91,5.3L7.6,5.84L7.53,6.81C7.26,7.02,7.02,7.26,6.81,7.53L5.84,7.6 M4.5,6.42c-1.06,0-1.92-0.86-1.92-1.92c0-1.06,0.86-1.92,1.92-1.92S6.42,3.44,6.42,4.5C6.42,5.56,5.56,6.42,4.5,6.42z"/>
L5.3,8.91l0.64,0.73c-0.04,0.34-0.04,0.68,0,1.02L5.3,11.39l0.54,1.31l0.97,0.07c0.21,0.27,0.45,0.51,0.72,0.72l0.07,0.97L8.91,15 </g>
l0.73-0.64c0.34,0.04,0.68,0.04,1.02,0L11.39,15l1.31-0.54l0.07-0.97c0.27-0.21,0.51-0.45,0.72-0.72l0.97-0.07L15,11.39 <g>
L14.36,10.66z"/> <path fill="#808080" d="M12.61,2.6c-0.12-0.06-0.24-0.18-0.28-0.27s-0.11-0.42-0.06-0.54s0-0.31-0.1-0.41l-0.15-0.15
<circle fill="#FFFFFF" cx="4.5" cy="4.5" r="1.92"/> c-0.1-0.1-0.28-0.14-0.41-0.1s-0.3,0.04-0.39,0S10.86,0.9,10.8,0.78s-0.22-0.22-0.36-0.22h-0.21c-0.14,0-0.3,0.1-0.36,0.22
<circle fill="#FFFFFF" cx="10.33" cy="3.06" r="1.11"/> S9.68,1.03,9.59,1.06S9.18,1.16,9.05,1.12s-0.31,0-0.41,0.1L8.49,1.37c-0.1,0.1-0.14,0.28-0.1,0.41s0.04,0.3,0,0.39
<circle fill="#FFFFFF" cx="10.15" cy="10.15" r="2.85"/> S8.17,2.54,8.05,2.6S7.83,2.82,7.83,2.96v0.21c0,0.14,0.1,0.3,0.22,0.36S8.3,3.71,8.33,3.8s0.11,0.42,0.06,0.54s0,0.31,0.1,0.41
l0.15,0.15c0.1,0.1,0.28,0.14,0.41,0.1s0.3-0.04,0.39,0s0.37,0.22,0.43,0.34s0.22,0.22,0.36,0.22h0.21c0.14,0,0.3-0.1,0.36-0.22
s0.18-0.24,0.27-0.28s0.42-0.11,0.54-0.06s0.31,0,0.41-0.1l0.15-0.15c0.1-0.1,0.14-0.28,0.1-0.41s-0.04-0.3,0-0.39
s0.22-0.37,0.34-0.43s0.22-0.22,0.22-0.36V2.96C12.83,2.82,12.74,2.66,12.61,2.6z M10.33,4.18c-0.62,0-1.11-0.5-1.11-1.11
c0-0.62,0.5-1.11,1.11-1.11s1.11,0.5,1.11,1.11C11.45,3.68,10.95,4.18,10.33,4.18z"/>
</g>
<g>
<path fill="#ED6B21" d="M14.38,9.89c-0.01-0.14,0.06-0.33,0.15-0.44l0.31-0.35c0.09-0.1,0.12-0.29,0.07-0.42l-0.35-0.85
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.47-0.03c-0.14-0.01-0.32-0.1-0.42-0.2l-0.37-0.37c-0.1-0.09-0.2-0.28-0.2-0.41l-0.03-0.47
c-0.01-0.14-0.12-0.29-0.25-0.35L11.62,5.4c-0.13-0.05-0.32-0.02-0.42,0.07l-0.36,0.31c-0.1,0.09-0.3,0.16-0.44,0.15l-0.52,0
C9.75,5.93,9.55,5.86,9.45,5.77L9.1,5.46C8.99,5.37,8.8,5.34,8.68,5.4L7.83,5.75C7.7,5.8,7.59,5.95,7.58,6.09L7.55,6.56
c-0.01,0.14-0.1,0.32-0.2,0.42L6.98,7.34c-0.09,0.1-0.28,0.2-0.41,0.2L6.09,7.58C5.95,7.59,5.8,7.7,5.75,7.83L5.4,8.68
C5.34,8.8,5.37,8.99,5.46,9.1l0.31,0.36c0.09,0.1,0.16,0.3,0.15,0.44l0,0.52c0.01,0.14-0.06,0.33-0.15,0.44L5.46,11.2
c-0.09,0.1-0.12,0.29-0.07,0.42l0.35,0.85c0.05,0.13,0.21,0.24,0.35,0.25l0.47,0.03c0.14,0.01,0.32,0.1,0.42,0.2l0.37,0.37
c0.1,0.09,0.2,0.28,0.2,0.41l0.03,0.47c0.01,0.14,0.12,0.29,0.25,0.35l0.85,0.35c0.13,0.05,0.32,0.02,0.42-0.07l0.36-0.31
c0.1-0.09,0.3-0.16,0.44-0.15l0.52,0c0.14-0.01,0.33,0.06,0.44,0.15l0.35,0.31c0.1,0.09,0.29,0.12,0.42,0.07l0.85-0.35
c0.13-0.05,0.24-0.21,0.25-0.35l0.03-0.47c0.01-0.14,0.1-0.32,0.2-0.42l0.37-0.37c0.09-0.1,0.28-0.2,0.41-0.21l0.47-0.03
c0.14-0.01,0.29-0.12,0.35-0.25l0.35-0.85c0.05-0.13,0.02-0.32-0.07-0.42l-0.31-0.36c-0.09-0.1-0.16-0.3-0.15-0.44L14.38,9.89z
M10.15,13c-1.57,0-2.85-1.27-2.85-2.85S8.58,7.3,10.15,7.3S13,8.58,13,10.15S11.72,13,10.15,13z"/>
</g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before After
Before After

View file

@ -2,24 +2,21 @@
const vec3 ZERO = vec3(0.0, 0.0, 0.0); const vec3 ZERO = vec3(0.0, 0.0, 0.0);
varying vec3 clipping_planes_dots;
// x = tainted, y = specular; // x = tainted, y = specular;
varying vec2 intensity; varying vec2 intensity;
varying vec3 delta_box_min; varying vec3 delta_box_min;
varying vec3 delta_box_max; varying vec3 delta_box_max;
varying float world_z;
uniform vec4 uniform_color; uniform vec4 uniform_color;
// x = min z, y = max z;
uniform vec2 z_range;
void main() void main()
{ {
if ((world_z < z_range.x) || (z_range.y < world_z)) if (any(lessThan(clipping_planes_dots, ZERO)))
discard; discard;
// if the fragment is outside the print volume -> use darker color // if the fragment is outside the print volume -> use darker color
vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb; vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb;
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a); gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a);

View file

@ -28,13 +28,18 @@ struct PrintBoxDetection
uniform PrintBoxDetection print_box; uniform PrintBoxDetection print_box;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
// Clipping plane - general orientation. Used by the SLA gizmo.
uniform vec4 clipping_plane;
// x = tainted, y = specular; // x = tainted, y = specular;
varying vec2 intensity; varying vec2 intensity;
varying vec3 delta_box_min; varying vec3 delta_box_min;
varying vec3 delta_box_max; varying vec3 delta_box_max;
varying float world_z; varying vec3 clipping_planes_dots;
void main() void main()
{ {
@ -69,5 +74,8 @@ void main()
} }
gl_Position = ftransform(); gl_Position = ftransform();
world_z = vec3(print_box.volume_world_matrix * gl_Vertex).z; // Point in homogenous coordinates.
vec4 world_pos = print_box.volume_world_matrix * gl_Vertex;
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
} }

View file

@ -43,11 +43,21 @@ typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal;
static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
typedef struct { struct stl_facet {
stl_normal normal; stl_normal normal;
stl_vertex vertex[3]; stl_vertex vertex[3];
char extra[2]; char extra[2];
} stl_facet;
stl_facet rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) {
stl_facet out;
out.normal = rot * this->normal;
out.vertex[0] = rot * this->vertex[0];
out.vertex[1] = rot * this->vertex[1];
out.vertex[2] = rot * this->vertex[2];
return out;
}
};
#define SIZEOF_STL_FACET 50 #define SIZEOF_STL_FACET 50
static_assert(offsetof(stl_facet, normal) == 0, "stl_facet.normal has correct offset"); static_assert(offsetof(stl_facet, normal) == 0, "stl_facet.normal has correct offset");

View file

@ -41,10 +41,12 @@ stl_open(stl_file *stl, const char *file) {
stl_count_facets(stl, file); stl_count_facets(stl, file);
stl_allocate(stl); stl_allocate(stl);
stl_read(stl, 0, true); stl_read(stl, 0, true);
if (!stl->error) fclose(stl->fp); if (stl->fp != nullptr) {
fclose(stl->fp);
stl->fp = nullptr;
}
} }
void void
stl_initialize(stl_file *stl) { stl_initialize(stl_file *stl) {
memset(stl, 0, sizeof(stl_file)); memset(stl, 0, sizeof(stl_file));
@ -118,7 +120,7 @@ stl_count_facets(stl_file *stl, const char *file) {
} }
/* Read the int following the header. This should contain # of facets */ /* Read the int following the header. This should contain # of facets */
bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, stl->fp); bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, stl->fp) != 0;
#ifndef BOOST_LITTLE_ENDIAN #ifndef BOOST_LITTLE_ENDIAN
// Convert from little endian to big endian. // Convert from little endian to big endian.
stl_internal_reverse_quads((char*)&header_num_facets, 4); stl_internal_reverse_quads((char*)&header_num_facets, 4);
@ -257,7 +259,6 @@ stl_reallocate(stl_file *stl) {
time running this for the stl and therefore we should reset our max and min stats. */ time running this for the stl and therefore we should reset our max and min stats. */
void stl_read(stl_file *stl, int first_facet, bool first) { void stl_read(stl_file *stl, int first_facet, bool first) {
stl_facet facet; stl_facet facet;
int i;
if (stl->error) return; if (stl->error) return;
@ -268,7 +269,7 @@ void stl_read(stl_file *stl, int first_facet, bool first) {
} }
char normal_buf[3][32]; char normal_buf[3][32];
for(i = first_facet; i < stl->stats.number_of_facets; i++) { for(uint32_t i = first_facet; i < stl->stats.number_of_facets; i++) {
if(stl->stats.type == binary) if(stl->stats.type == binary)
/* Read a single facet from a binary .STL file */ /* Read a single facet from a binary .STL file */
{ {
@ -366,17 +367,19 @@ void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first)
} }
} }
void void stl_close(stl_file *stl)
stl_close(stl_file *stl) { {
if (stl->error) return; assert(stl->fp == nullptr);
assert(stl->heads == nullptr);
assert(stl->tail == nullptr);
if(stl->neighbors_start != NULL) if (stl->facet_start != NULL)
free(stl->neighbors_start);
if(stl->facet_start != NULL)
free(stl->facet_start); free(stl->facet_start);
if(stl->v_indices != NULL) if (stl->neighbors_start != NULL)
free(stl->neighbors_start);
if (stl->v_indices != NULL)
free(stl->v_indices); free(stl->v_indices);
if(stl->v_shared != NULL) if (stl->v_shared != NULL)
free(stl->v_shared); free(stl->v_shared);
memset(stl, 0, sizeof(stl_file));
} }

View file

@ -189,7 +189,6 @@ target_link_libraries(libslic3r
clipper clipper
nowide nowide
${EXPAT_LIBRARIES} ${EXPAT_LIBRARIES}
${GLEW_LIBRARIES}
glu-libtess glu-libtess
polypartition polypartition
poly2tri poly2tri

View file

@ -593,6 +593,8 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
this->origin_translation = rhs.origin_translation; this->origin_translation = rhs.origin_translation;
m_bounding_box = rhs.m_bounding_box; m_bounding_box = rhs.m_bounding_box;
m_bounding_box_valid = rhs.m_bounding_box_valid; m_bounding_box_valid = rhs.m_bounding_box_valid;
m_raw_bounding_box = rhs.m_raw_bounding_box;
m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid;
m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box;
m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid;
@ -627,6 +629,8 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
this->origin_translation = std::move(rhs.origin_translation); this->origin_translation = std::move(rhs.origin_translation);
m_bounding_box = std::move(rhs.m_bounding_box); m_bounding_box = std::move(rhs.m_bounding_box);
m_bounding_box_valid = std::move(rhs.m_bounding_box_valid); m_bounding_box_valid = std::move(rhs.m_bounding_box_valid);
m_raw_bounding_box = rhs.m_raw_bounding_box;
m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid;
m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box;
m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid;
@ -859,7 +863,7 @@ TriangleMesh ModelObject::full_raw_mesh() const
return mesh; return mesh;
} }
BoundingBoxf3 ModelObject::raw_mesh_bounding_box() const const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const
{ {
if (! m_raw_mesh_bounding_box_valid) { if (! m_raw_mesh_bounding_box_valid) {
m_raw_mesh_bounding_box_valid = true; m_raw_mesh_bounding_box_valid = true;
@ -880,33 +884,36 @@ BoundingBoxf3 ModelObject::full_raw_mesh_bounding_box() const
} }
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied. // A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
// This bounding box is only used for the actual slicing. // This bounding box is only used for the actual slicing and for layer editing UI to calculate the layers.
BoundingBoxf3 ModelObject::raw_bounding_box() const const BoundingBoxf3& ModelObject::raw_bounding_box() const
{ {
BoundingBoxf3 bb; if (! m_raw_bounding_box_valid) {
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT m_raw_bounding_box_valid = true;
m_raw_bounding_box.reset();
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
if (this->instances.empty()) if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
for (const ModelVolume *v : this->volumes) for (const ModelVolume *v : this->volumes)
if (v->is_model_part()) { if (v->is_model_part()) {
#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT #if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
if (this->instances.empty()) if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT #endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
TriangleMesh vol_mesh(v->mesh); #if ENABLE_GENERIC_SUBPARTS_PLACEMENT
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT m_raw_bounding_box.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix()));
vol_mesh.transform(inst_matrix * v->get_matrix()); #else
bb.merge(vol_mesh.bounding_box()); // unmaintaned
#else assert(false);
vol_mesh.transform(v->get_matrix()); // vol_mesh.transform(v->get_matrix());
bb.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true)); // m_raw_bounding_box_valid.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true));
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
} }
return bb; }
return m_raw_bounding_box;
} }
// This returns an accurate snug bounding box of the transformed object instance, without the translation applied. // This returns an accurate snug bounding box of the transformed object instance, without the translation applied.
@ -920,13 +927,13 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_
{ {
if (v->is_model_part()) if (v->is_model_part())
{ {
TriangleMesh mesh(v->mesh);
#if ENABLE_GENERIC_SUBPARTS_PLACEMENT #if ENABLE_GENERIC_SUBPARTS_PLACEMENT
mesh.transform(inst_matrix * v->get_matrix()); bb.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix()));
bb.merge(mesh.bounding_box());
#else #else
mesh.transform(v->get_matrix()); // not maintained
bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(mesh, dont_translate)); assert(false);
//mesh.transform(v->get_matrix());
//bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(mesh, dont_translate));
#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
} }
} }

View file

@ -212,7 +212,7 @@ public:
// This bounding box is approximate and not snug. // This bounding box is approximate and not snug.
// This bounding box is being cached. // This bounding box is being cached.
const BoundingBoxf3& bounding_box() const; const BoundingBoxf3& bounding_box() const;
void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; }
// A mesh containing all transformed instances of this object. // A mesh containing all transformed instances of this object.
TriangleMesh mesh() const; TriangleMesh mesh() const;
@ -223,11 +223,11 @@ public:
TriangleMesh full_raw_mesh() const; TriangleMesh full_raw_mesh() const;
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied. // A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
// This bounding box is only used for the actual slicing. // This bounding box is only used for the actual slicing.
BoundingBoxf3 raw_bounding_box() const; const BoundingBoxf3& raw_bounding_box() const;
// A snug bounding box around the transformed non-modifier object volumes. // A snug bounding box around the transformed non-modifier object volumes.
BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const;
// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes. // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
BoundingBoxf3 raw_mesh_bounding_box() const; const BoundingBoxf3& raw_mesh_bounding_box() const;
// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes. // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
BoundingBoxf3 full_raw_mesh_bounding_box() const; BoundingBoxf3 full_raw_mesh_bounding_box() const;
@ -285,7 +285,7 @@ protected:
private: private:
ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()), ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()),
m_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {}
~ModelObject(); ~ModelObject();
/* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */
@ -304,6 +304,8 @@ private:
// Bounding box, cached. // Bounding box, cached.
mutable BoundingBoxf3 m_bounding_box; mutable BoundingBoxf3 m_bounding_box;
mutable bool m_bounding_box_valid; mutable bool m_bounding_box_valid;
mutable BoundingBoxf3 m_raw_bounding_box;
mutable bool m_raw_bounding_box_valid;
mutable BoundingBoxf3 m_raw_mesh_bounding_box; mutable BoundingBoxf3 m_raw_mesh_bounding_box;
mutable bool m_raw_mesh_bounding_box_valid; mutable bool m_raw_mesh_bounding_box_valid;
}; };

View file

@ -132,7 +132,7 @@ public:
// The slicing parameters are dependent on various configuration values // The slicing parameters are dependent on various configuration values
// (layer height, first layer height, raft settings, print nozzle diameter etc). // (layer height, first layer height, raft settings, print nozzle diameter etc).
const SlicingParameters& slicing_parameters() const { return m_slicing_params; } const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object); static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z);
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions) // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
std::vector<unsigned int> object_extruders() const; std::vector<unsigned int> object_extruders() const;

View file

@ -2528,14 +2528,17 @@ void PrintConfigDef::init_sla_params()
def = this->add("pad_wall_height", coFloat); def = this->add("pad_wall_height", coFloat);
def->label = L("Pad wall height"); def->label = L("Pad wall height");
def->tooltip = L("Defines the cavity depth. Set to zero to disable the cavity."); def->tooltip = L("Defines the pad cavity depth. Set to zero to disable the cavity. "
"Be careful when enabling this feature, as some resins may "
"produce an extreme suction effect inside the cavity, "
"which makes pealing the print off the vat foil difficult.");
def->category = L("Pad"); def->category = L("Pad");
// def->tooltip = L(""); // def->tooltip = L("");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->min = 0; def->min = 0;
def->max = 30; def->max = 30;
def->mode = comSimple; def->mode = comExpert;
def->default_value = new ConfigOptionFloat(5.0); def->default_value = new ConfigOptionFloat(0.);
def = this->add("pad_max_merge_distance", coFloat); def = this->add("pad_max_merge_distance", coFloat);
def->label = L("Max merge distance"); def->label = L("Max merge distance");
@ -3114,6 +3117,13 @@ CLIMiscConfigDef::CLIMiscConfigDef()
def->label = L("Logging level"); def->label = L("Logging level");
def->tooltip = L("Messages with severity lower or eqal to the loglevel will be printed out. 0:trace, 1:debug, 2:info, 3:warning, 4:error, 5:fatal"); def->tooltip = L("Messages with severity lower or eqal to the loglevel will be printed out. 0:trace, 1:debug, 2:info, 3:warning, 4:error, 5:fatal");
def->min = 0; def->min = 0;
#if defined(_MSC_VER) && defined(SLIC3R_GUI)
def = this->add("sw_renderer", coBool);
def->label = L("Render with a software renderer");
def->tooltip = L("Render with a software renderer. The bundled MESA software renderer is loaded instead of the default OpenGL driver.");
def->min = 0;
#endif /* _MSC_VER */
} }
const CLIActionsConfigDef cli_actions_config_def; const CLIActionsConfigDef cli_actions_config_def;

View file

@ -1370,7 +1370,7 @@ void PrintObject::update_slicing_parameters()
this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders()); this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders());
} }
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object) SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z)
{ {
PrintConfig print_config; PrintConfig print_config;
PrintObjectConfig object_config; PrintObjectConfig object_config;
@ -1390,7 +1390,9 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full
object_extruders); object_extruders);
sort_remove_duplicates(object_extruders); sort_remove_duplicates(object_extruders);
return SlicingParameters::create_from_config(print_config, object_config, model_object.bounding_box().max.z(), object_extruders); if (object_max_z <= 0.f)
object_max_z = model_object.raw_bounding_box().size().z();
return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders);
} }
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions) // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)

View file

@ -1572,10 +1572,8 @@ public:
auto hit = bridge_mesh_intersect(headjp, n, r); auto hit = bridge_mesh_intersect(headjp, n, r);
if(std::isinf(hit.distance())) ground_head_indices.emplace_back(i); if(std::isinf(hit.distance())) ground_head_indices.emplace_back(i);
else { else if(m_cfg.ground_facing_only) head.invalidate();
if(m_cfg.ground_facing_only) head.invalidate(); else m_iheads_onmodel.emplace_back(std::make_pair(i, hit));
m_iheads_onmodel.emplace_back(std::make_pair(i, hit));
}
} }
// We want to search for clusters of points that are far enough // We want to search for clusters of points that are far enough
@ -1872,7 +1870,7 @@ public:
} }
} }
void cascade_pillars() { void interconnect_pillars() {
// Now comes the algorithm that connects pillars with each other. // Now comes the algorithm that connects pillars with each other.
// Ideally every pillar should be connected with at least one of its // Ideally every pillar should be connected with at least one of its
// neighbors if that neighbor is within max_pillar_link_distance // neighbors if that neighbor is within max_pillar_link_distance
@ -2121,7 +2119,7 @@ bool SLASupportTree::generate(const std::vector<SupportPoint> &support_points,
std::bind(&Algorithm::routing_to_model, &alg), std::bind(&Algorithm::routing_to_model, &alg),
std::bind(&Algorithm::cascade_pillars, &alg), std::bind(&Algorithm::interconnect_pillars, &alg),
std::bind(&Algorithm::routing_headless, &alg), std::bind(&Algorithm::routing_headless, &alg),
@ -2150,16 +2148,16 @@ bool SLASupportTree::generate(const std::vector<SupportPoint> &support_points,
// Let's define a simple automaton that will run our program. // Let's define a simple automaton that will run our program.
auto progress = [&ctl, &pc] () { auto progress = [&ctl, &pc] () {
static const std::array<std::string, NUM_STEPS> stepstr { static const std::array<std::string, NUM_STEPS> stepstr {
L("Starting"), "Starting",
L("Filtering"), "Filtering",
L("Generate pinheads"), "Generate pinheads",
L("Classification"), "Classification",
L("Routing to ground"), "Routing to ground",
L("Routing supports to model surface"), "Routing supports to model surface",
L("Cascading pillars"), "Interconnecting pillars",
L("Processing small holes"), "Processing small holes",
L("Done"), "Done",
L("Abort") "Abort"
}; };
static const std::array<unsigned, NUM_STEPS> stepstate { static const std::array<unsigned, NUM_STEPS> stepstate {

View file

@ -693,6 +693,16 @@ void TriangleMeshSlicer::init(TriangleMesh *_mesh, throw_on_cancel_callback_type
} }
} }
void TriangleMeshSlicer::set_up_direction(const Vec3f& up)
{
m_quaternion.setFromTwoVectors(up, Vec3f::UnitZ());
m_use_quaternion = true;
}
void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* layers, throw_on_cancel_callback_type throw_on_cancel) const
{ {
BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::slice"; BOOST_LOG_TRIVIAL(debug) << "TriangleMeshSlicer::slice";
@ -795,7 +805,7 @@ void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons
void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex,
const std::vector<float> &z) const const std::vector<float> &z) const
{ {
const stl_facet &facet = this->mesh->stl.facet_start[facet_idx]; const stl_facet &facet = m_use_quaternion ? this->mesh->stl.facet_start[facet_idx].rotated(m_quaternion) : this->mesh->stl.facet_start[facet_idx];
// find facet extents // find facet extents
const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2))); const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2)));
@ -866,20 +876,37 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
// (external on the right of the line) // (external on the right of the line)
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0); int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0);
// These are used only if the cut plane is tilted:
stl_vertex rotated_a;
stl_vertex rotated_b;
for (int j = i; j - i < 3; ++j) { // loop through facet edges for (int j = i; j - i < 3; ++j) { // loop through facet edges
int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)]; int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)];
int a_id = vertices[j % 3]; int a_id = vertices[j % 3];
int b_id = vertices[(j+1) % 3]; int b_id = vertices[(j+1) % 3];
const stl_vertex *a = &this->v_scaled_shared[a_id];
const stl_vertex *b = &this->v_scaled_shared[b_id]; const stl_vertex *a;
const stl_vertex *b;
if (m_use_quaternion) {
rotated_a = m_quaternion * this->v_scaled_shared[a_id];
rotated_b = m_quaternion * this->v_scaled_shared[b_id];
a = &rotated_a;
b = &rotated_b;
}
else {
a = &this->v_scaled_shared[a_id];
b = &this->v_scaled_shared[b_id];
}
// Is edge or face aligned with the cutting plane? // Is edge or face aligned with the cutting plane?
if (a->z() == slice_z && b->z() == slice_z) { if (a->z() == slice_z && b->z() == slice_z) {
// Edge is horizontal and belongs to the current layer. // Edge is horizontal and belongs to the current layer.
const stl_vertex &v0 = this->v_scaled_shared[vertices[0]]; // The following rotation of the three vertices may not be efficient, but this branch happens rarely.
const stl_vertex &v1 = this->v_scaled_shared[vertices[1]]; const stl_vertex &v0 = m_use_quaternion ? stl_vertex(m_quaternion * this->v_scaled_shared[vertices[0]]) : this->v_scaled_shared[vertices[0]];
const stl_vertex &v2 = this->v_scaled_shared[vertices[2]]; const stl_vertex &v1 = m_use_quaternion ? stl_vertex(m_quaternion * this->v_scaled_shared[vertices[1]]) : this->v_scaled_shared[vertices[1]];
const stl_normal &normal = this->mesh->stl.facet_start[facet_idx].normal; const stl_vertex &v2 = m_use_quaternion ? stl_vertex(m_quaternion * this->v_scaled_shared[vertices[2]]) : this->v_scaled_shared[vertices[2]];
const stl_normal &normal = facet.normal;
// We may ignore this edge for slicing purposes, but we may still use it for object cutting. // We may ignore this edge for slicing purposes, but we may still use it for object cutting.
FacetSliceType result = Slicing; FacetSliceType result = Slicing;
if (min_z == max_z) { if (min_z == max_z) {
@ -995,7 +1022,9 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
if (i == line_out->a_id || i == line_out->b_id) if (i == line_out->a_id || i == line_out->b_id)
i = vertices[2]; i = vertices[2];
assert(i != line_out->a_id && i != line_out->b_id); assert(i != line_out->a_id && i != line_out->b_id);
line_out->edge_type = (this->v_scaled_shared[i].z() < slice_z) ? feTop : feBottom; line_out->edge_type = ((m_use_quaternion ?
(m_quaternion * this->v_scaled_shared[i]).z()
: this->v_scaled_shared[i].z()) < slice_z) ? feTop : feBottom;
} }
#endif #endif
return Slicing; return Slicing;

View file

@ -25,9 +25,10 @@ public:
TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd> &facets); TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd> &facets);
TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_initialize(&this->stl); *this = other; } TriangleMesh(const TriangleMesh &other) : repaired(false) { stl_initialize(&this->stl); *this = other; }
TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_initialize(&this->stl); this->swap(other); } TriangleMesh(TriangleMesh &&other) : repaired(false) { stl_initialize(&this->stl); this->swap(other); }
~TriangleMesh() { stl_close(&this->stl); } ~TriangleMesh() { clear(); }
TriangleMesh& operator=(const TriangleMesh &other); TriangleMesh& operator=(const TriangleMesh &other);
TriangleMesh& operator=(TriangleMesh &&other) { this->swap(other); return *this; } TriangleMesh& operator=(TriangleMesh &&other) { this->swap(other); return *this; }
void clear() { stl_close(&this->stl); this->repaired = false; }
void swap(TriangleMesh &other) { std::swap(this->stl, other.stl); std::swap(this->repaired, other.repaired); } void swap(TriangleMesh &other) { std::swap(this->stl, other.stl); std::swap(this->repaired, other.repaired); }
void ReadSTLFile(const char* input_file) { stl_open(&stl, input_file); } void ReadSTLFile(const char* input_file) { stl_open(&stl, input_file); }
void write_ascii(const char* output_file) { stl_write_ascii(&this->stl, output_file, ""); } void write_ascii(const char* output_file) { stl_write_ascii(&this->stl, output_file, ""); }
@ -171,6 +172,7 @@ public:
FacetSliceType slice_facet(float slice_z, const stl_facet &facet, const int facet_idx, FacetSliceType slice_facet(float slice_z, const stl_facet &facet, const int facet_idx,
const float min_z, const float max_z, IntersectionLine *line_out) const; const float min_z, const float max_z, IntersectionLine *line_out) const;
void cut(float z, TriangleMesh* upper, TriangleMesh* lower) const; void cut(float z, TriangleMesh* upper, TriangleMesh* lower) const;
void set_up_direction(const Vec3f& up);
private: private:
const TriangleMesh *mesh; const TriangleMesh *mesh;
@ -178,6 +180,10 @@ private:
std::vector<int> facets_edges; std::vector<int> facets_edges;
// Scaled copy of this->mesh->stl.v_shared // Scaled copy of this->mesh->stl.v_shared
std::vector<stl_vertex> v_scaled_shared; std::vector<stl_vertex> v_scaled_shared;
// Quaternion that will be used to rotate every facet before the slicing
Eigen::Quaternion<float, Eigen::DontAlign> m_quaternion;
// Whether or not the above quaterion should be used
bool m_use_quaternion = false;
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const; void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const; void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;

View file

@ -6,10 +6,12 @@
#define NOMINMAX #define NOMINMAX
#include <Windows.h> #include <Windows.h>
#include <wchar.h> #include <wchar.h>
#ifdef SLIC3R_GUI
// Let the NVIDIA and AMD know we want to use their graphics card // Let the NVIDIA and AMD know we want to use their graphics card
// on a dual graphics card system. // on a dual graphics card system.
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#endif /* SLIC3R_GUI */
#endif /* WIN32 */ #endif /* WIN32 */
#include <cstdio> #include <cstdio>
@ -38,8 +40,11 @@
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "slic3r.hpp" #include "slic3r.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp" #ifdef SLIC3R_GUI
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#endif /* SLIC3R_GUI */
using namespace Slic3r; using namespace Slic3r;
@ -448,7 +453,7 @@ int CLI::run(int argc, char **argv)
} }
if (start_gui) { if (start_gui) {
#if 1 #ifdef SLIC3R_GUI
// #ifdef USE_WX // #ifdef USE_WX
GUI::GUI_App *gui = new GUI::GUI_App(); GUI::GUI_App *gui = new GUI::GUI_App();
// gui->autosave = m_config.opt_string("autosave"); // gui->autosave = m_config.opt_string("autosave");
@ -477,12 +482,12 @@ int CLI::run(int argc, char **argv)
gui->mainframe->load_config(m_extra_config); gui->mainframe->load_config(m_extra_config);
}); });
return wxEntry(argc, argv); return wxEntry(argc, argv);
#else #else /* SLIC3R_GUI */
// No GUI support. Just print out a help. // No GUI support. Just print out a help.
this->print_help(false); this->print_help(false);
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc). // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
return (argc == 0) ? 0 : 1; return (argc == 0) ? 0 : 1;
#endif #endif /* SLIC3R_GUI */
} }
return 0; return 0;
@ -563,7 +568,13 @@ bool CLI::setup(int argc, char **argv)
void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const
{ {
boost::nowide::cout boost::nowide::cout
<< "Slic3r Prusa Edition " << SLIC3R_BUILD << std::endl << "Slic3r Prusa Edition " << SLIC3R_BUILD
#ifdef SLIC3R_GUI
<< " (with GUI support)"
#else /* SLIC3R_GUI */
<< " (without GUI support)"
#endif /* SLIC3R_GUI */
<< std::endl
<< "https://github.com/prusa3d/Slic3r" << std::endl << std::endl << "https://github.com/prusa3d/Slic3r" << std::endl << std::endl
<< "Usage: slic3r [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl << "Usage: slic3r [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl
<< std::endl << std::endl

View file

@ -154,7 +154,7 @@ endif ()
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES}) add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
target_link_libraries(libslic3r_gui libslic3r avrdude imgui) target_link_libraries(libslic3r_gui libslic3r avrdude imgui ${GLEW_LIBRARIES})
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY) if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE) add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
endif () endif ()

View file

@ -721,32 +721,37 @@ int GLVolumeCollection::load_wipe_tower_preview(
return int(this->volumes.size() - 1); return int(this->volumes.size() - 1);
} }
typedef std::pair<GLVolume*, double> GLVolumeWithZ; GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func)
typedef std::vector<GLVolumeWithZ> GLVolumesWithZList;
static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func)
{ {
GLVolumesWithZList list; GLVolumeWithIdAndZList list;
list.reserve(volumes.size()); list.reserve(volumes.size());
for (GLVolume* volume : volumes) for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i)
{ {
GLVolume* volume = volumes[i];
bool is_transparent = (volume->render_color[3] < 1.0f); bool is_transparent = (volume->render_color[3] < 1.0f);
if ((((type == GLVolumeCollection::Opaque) && !is_transparent) || if ((((type == GLVolumeCollection::Opaque) && !is_transparent) ||
((type == GLVolumeCollection::Transparent) && is_transparent) || ((type == GLVolumeCollection::Transparent) && is_transparent) ||
(type == GLVolumeCollection::All)) && (type == GLVolumeCollection::All)) &&
(! filter_func || filter_func(*volume))) (! filter_func || filter_func(*volume)))
list.emplace_back(std::make_pair(volume, 0.0)); list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0)));
} }
if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) if ((type == GLVolumeCollection::Transparent) && (list.size() > 1))
{ {
for (GLVolumeWithZ& volume : list) for (GLVolumeWithIdAndZ& volume : list)
{ {
volume.second = volume.first->bounding_box.transformed(view_matrix * volume.first->world_matrix()).max(2); volume.second.second = volume.first->bounding_box.transformed(view_matrix * volume.first->world_matrix()).max(2);
} }
std::sort(list.begin(), list.end(), std::sort(list.begin(), list.end(),
[](const GLVolumeWithZ& v1, const GLVolumeWithZ& v2) -> bool { return v1.second < v2.second; } [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.second.second < v2.second.second; }
);
}
else if ((type == GLVolumeCollection::Opaque) && (list.size() > 1))
{
std::sort(list.begin(), list.end(),
[](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.first->selected && !v2.first->selected; }
); );
} }
@ -769,6 +774,7 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id)); glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id));
GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
GLint z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "z_range") : -1; GLint z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "z_range") : -1;
GLint clipping_plane_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "clipping_plane") : -1;
GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1; GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1;
GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1; GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1;
GLint print_box_detection_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1; GLint print_box_detection_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1;
@ -784,8 +790,11 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
if (z_range_id != -1) if (z_range_id != -1)
glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range)); glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); if (clipping_plane_id != -1)
for (GLVolumeWithZ& volume : to_render) { glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)clipping_plane));
GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func);
for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->set_render_color(); volume.first->set_render_color();
volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
} }
@ -814,8 +823,8 @@ void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface,
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func);
for (GLVolumeWithZ& volume : to_render) for (GLVolumeWithIdAndZ& volume : to_render)
{ {
volume.first->set_render_color(); volume.first->set_render_color();
volume.first->render_legacy(); volume.first->render_legacy();

View file

@ -412,6 +412,8 @@ public:
}; };
typedef std::vector<GLVolume*> GLVolumePtrs; typedef std::vector<GLVolume*> GLVolumePtrs;
typedef std::pair<GLVolume*, std::pair<unsigned int, double>> GLVolumeWithIdAndZ;
typedef std::vector<GLVolumeWithIdAndZ> GLVolumeWithIdAndZList;
class GLVolumeCollection class GLVolumeCollection
{ {
@ -431,6 +433,9 @@ private:
// z range for clipping in shaders // z range for clipping in shaders
float z_range[2]; float z_range[2];
// plane coeffs for clipping in shaders
float clipping_plane[4];
public: public:
GLVolumePtrs volumes; GLVolumePtrs volumes;
@ -489,6 +494,7 @@ public:
} }
void set_z_range(float min_z, float max_z) { z_range[0] = min_z; z_range[1] = max_z; } void set_z_range(float min_z, float max_z) { z_range[0] = min_z; z_range[1] = max_z; }
void set_clipping_plane(const double* coeffs) { clipping_plane[0] = coeffs[0]; clipping_plane[1] = coeffs[1]; clipping_plane[2] = coeffs[2]; clipping_plane[3] = coeffs[3]; }
// returns true if all the volumes are completely contained in the print volume // returns true if all the volumes are completely contained in the print volume
// returns the containment state in the given out_state, if non-null // returns the containment state in the given out_state, if non-null
@ -505,6 +511,8 @@ private:
GLVolumeCollection& operator=(const GLVolumeCollection &); GLVolumeCollection& operator=(const GLVolumeCollection &);
}; };
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = nullptr);
class GLModel class GLModel
{ {
protected: protected:

View file

@ -255,16 +255,21 @@ void GLCanvas3D::LayersEditing::set_config(const DynamicPrintConfig* config)
void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id) void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
{ {
const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr; const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr;
if (model_object_new == nullptr || this->last_object_id != object_id || m_model_object != model_object_new || m_model_object->id() != model_object_new->id()) { // Maximum height of an object changes when the object gets rotated or scaled.
// Changing maximum height of an object will invalidate the layer heigth editing profile.
// m_model_object->raw_bounding_box() is cached, therefore it is cheap even if this method is called frequently.
float new_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->raw_bounding_box().size().z();
if (m_model_object != model_object_new || this->last_object_id != object_id || m_object_max_z != new_max_z ||
(model_object_new != nullptr && m_model_object->id() != model_object_new->id())) {
m_layer_height_profile.clear(); m_layer_height_profile.clear();
m_layer_height_profile_modified = false; m_layer_height_profile_modified = false;
delete m_slicing_parameters; delete m_slicing_parameters;
m_slicing_parameters = nullptr; m_slicing_parameters = nullptr;
m_layers_texture.valid = false; m_layers_texture.valid = false;
}
this->last_object_id = object_id; this->last_object_id = object_id;
m_model_object = model_object_new; m_model_object = model_object_new;
m_object_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->bounding_box().max.z(); m_object_max_z = new_max_z;
}
} }
bool GLCanvas3D::LayersEditing::is_allowed() const bool GLCanvas3D::LayersEditing::is_allowed() const
@ -623,7 +628,7 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters()
{ {
if (m_slicing_parameters == nullptr) { if (m_slicing_parameters == nullptr) {
m_slicing_parameters = new SlicingParameters(); m_slicing_parameters = new SlicingParameters();
*m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object); *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z);
} }
} }
@ -2204,6 +2209,9 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
void GLCanvas3D::on_char(wxKeyEvent& evt) void GLCanvas3D::on_char(wxKeyEvent& evt)
{ {
if (!m_initialized)
return;
// see include/wx/defs.h enum wxKeyCode // see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode(); int keyCode = evt.GetKeyCode();
int ctrlMask = wxMOD_CONTROL; int ctrlMask = wxMOD_CONTROL;
@ -2222,9 +2230,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
//#endif /* __APPLE__ */ //#endif /* __APPLE__ */
if ((evt.GetModifiers() & ctrlMask) != 0) { if ((evt.GetModifiers() & ctrlMask) != 0) {
switch (keyCode) { switch (keyCode) {
#ifdef __APPLE__
case 'a': case 'a':
case 'A': case 'A':
#else /* __APPLE__ */
case WXK_CONTROL_A: case WXK_CONTROL_A:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL)); post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
break; break;
#ifdef __APPLE__ #ifdef __APPLE__
@ -3134,6 +3145,11 @@ Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos)
return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1)); return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1));
} }
double GLCanvas3D::get_size_proportional_to_max_bed_size(double factor) const
{
return factor * m_bed.get_bounding_box().max_size();
}
bool GLCanvas3D::_is_shown_on_screen() const bool GLCanvas3D::_is_shown_on_screen() const
{ {
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
@ -3226,12 +3242,37 @@ bool GLCanvas3D::_init_toolbar()
if (!m_toolbar.add_separator()) if (!m_toolbar.add_separator())
return false; return false;
item.name = "copy";
#if ENABLE_SVG_ICONS
item.icon_filename = "copy.svg";
#endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Copy") + " [" + GUI::shortkey_ctrl_prefix() + "C]";
item.sprite_id = 4;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_copy(); };
if (!m_toolbar.add_item(item))
return false;
item.name = "paste";
#if ENABLE_SVG_ICONS
item.icon_filename = "paste.svg";
#endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Paste") + " [" + GUI::shortkey_ctrl_prefix() + "V]";
item.sprite_id = 5;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_paste(); };
if (!m_toolbar.add_item(item))
return false;
if (!m_toolbar.add_separator())
return false;
item.name = "more"; item.name = "more";
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
item.icon_filename = "instance_add.svg"; item.icon_filename = "instance_add.svg";
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Add instance [+]"); item.tooltip = GUI::L_str("Add instance [+]");
item.sprite_id = 4; item.sprite_id = 6;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); }; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); }; item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
@ -3243,7 +3284,7 @@ bool GLCanvas3D::_init_toolbar()
item.icon_filename = "instance_remove.svg"; item.icon_filename = "instance_remove.svg";
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Remove instance [-]"); item.tooltip = GUI::L_str("Remove instance [-]");
item.sprite_id = 5; item.sprite_id = 7;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); }; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); }; item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
@ -3258,7 +3299,7 @@ bool GLCanvas3D::_init_toolbar()
item.icon_filename = "split_objects.svg"; item.icon_filename = "split_objects.svg";
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Split to objects"); item.tooltip = GUI::L_str("Split to objects");
item.sprite_id = 6; item.sprite_id = 8;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); }; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback; item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); }; item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
@ -3270,7 +3311,7 @@ bool GLCanvas3D::_init_toolbar()
item.icon_filename = "split_parts.svg"; item.icon_filename = "split_parts.svg";
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Split to parts"); item.tooltip = GUI::L_str("Split to parts");
item.sprite_id = 7; item.sprite_id = 9;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); }; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); }; item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
@ -3285,7 +3326,7 @@ bool GLCanvas3D::_init_toolbar()
item.icon_filename = "layers.svg"; item.icon_filename = "layers.svg";
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = GUI::L_str("Layers editing"); item.tooltip = GUI::L_str("Layers editing");
item.sprite_id = 8; item.sprite_id = 10;
item.is_toggable = true; item.is_toggable = true;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); }; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; }; item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; };
@ -3490,7 +3531,15 @@ void GLCanvas3D::_picking_pass() const
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
_render_volumes(true); m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane();
if (m_camera_clipping_plane.is_active()) {
::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data());
::glEnable(GL_CLIP_PLANE0);
}
_render_volumes_for_picking();
if (m_camera_clipping_plane.is_active())
::glDisable(GL_CLIP_PLANE0);
m_gizmos.render_current_gizmo_for_picking_pass(m_selection); m_gizmos.render_current_gizmo_for_picking_pass(m_selection);
if (m_multisample_allowed) if (m_multisample_allowed)
@ -3571,6 +3620,8 @@ void GLCanvas3D::_render_axes() const
m_bed.render_axes(); m_bed.render_axes();
} }
void GLCanvas3D::_render_objects() const void GLCanvas3D::_render_objects() const
{ {
if (m_volumes.empty()) if (m_volumes.empty())
@ -3579,6 +3630,8 @@ void GLCanvas3D::_render_objects() const
glsafe(::glEnable(GL_LIGHTING)); glsafe(::glEnable(GL_LIGHTING));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane();
if (m_use_VBOs) if (m_use_VBOs)
{ {
if (m_picking_enabled) if (m_picking_enabled)
@ -3599,6 +3652,8 @@ void GLCanvas3D::_render_objects() const
else else
m_volumes.set_z_range(-FLT_MAX, FLT_MAX); m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
m_shader.start_using(); m_shader.start_using();
if (m_picking_enabled && m_layers_editing.is_enabled() && m_layers_editing.last_object_id != -1) { if (m_picking_enabled && m_layers_editing.is_enabled() && m_layers_editing.last_object_id != -1) {
int object_id = m_layers_editing.last_object_id; int object_id = m_layers_editing.last_object_id;
@ -3619,27 +3674,34 @@ void GLCanvas3D::_render_objects() const
} }
else else
{ {
::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data());
::glEnable(GL_CLIP_PLANE0);
if (m_use_clipping_planes) if (m_use_clipping_planes)
{ {
glsafe(::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_clipping_planes[0].get_data())); glsafe(::glClipPlane(GL_CLIP_PLANE1, (GLdouble*)m_clipping_planes[0].get_data()));
glsafe(::glEnable(GL_CLIP_PLANE0));
glsafe(::glClipPlane(GL_CLIP_PLANE1, (GLdouble*)m_clipping_planes[1].get_data()));
glsafe(::glEnable(GL_CLIP_PLANE1)); glsafe(::glEnable(GL_CLIP_PLANE1));
glsafe(::glClipPlane(GL_CLIP_PLANE2, (GLdouble*)m_clipping_planes[1].get_data()));
glsafe(::glEnable(GL_CLIP_PLANE2));
} }
// do not cull backfaces to show broken geometry, if any // do not cull backfaces to show broken geometry, if any
m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled, m_camera.get_view_matrix(), [this](const GLVolume& volume) { m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled, m_camera.get_view_matrix(), [this](const GLVolume& volume) {
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0); return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
}); });
m_volumes.render_legacy(GLVolumeCollection::Transparent, false, m_camera.get_view_matrix()); m_volumes.render_legacy(GLVolumeCollection::Transparent, false, m_camera.get_view_matrix());
::glDisable(GL_CLIP_PLANE0);
if (m_use_clipping_planes) if (m_use_clipping_planes)
{ {
glsafe(::glDisable(GL_CLIP_PLANE0));
glsafe(::glDisable(GL_CLIP_PLANE1)); glsafe(::glDisable(GL_CLIP_PLANE1));
glsafe(::glDisable(GL_CLIP_PLANE2));
} }
} }
m_camera_clipping_plane = ClippingPlane::ClipsNothing();
glsafe(::glDisable(GL_LIGHTING)); glsafe(::glDisable(GL_LIGHTING));
} }
@ -3675,13 +3737,10 @@ void GLCanvas3D::_render_legend_texture() const
m_legend_texture.render(*this); m_legend_texture.render(*this);
} }
void GLCanvas3D::_render_volumes(bool fake_colors) const void GLCanvas3D::_render_volumes_for_picking() const
{ {
static const GLfloat INV_255 = 1.0f / 255.0f; static const GLfloat INV_255 = 1.0f / 255.0f;
if (!fake_colors)
glsafe(::glEnable(GL_LIGHTING));
// do not cull backfaces to show broken geometry, if any // do not cull backfaces to show broken geometry, if any
glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glDisable(GL_CULL_FACE));
@ -3691,27 +3750,31 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const
glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
unsigned int volume_id = 0; const Transform3d& view_matrix = m_camera.get_view_matrix();
for (GLVolume* vol : m_volumes.volumes) GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Opaque, view_matrix);
{ for (const GLVolumeWithIdAndZ& volume : to_render)
if (fake_colors)
{ {
// Object picking mode. Render the object with a color encoding the object index. // Object picking mode. Render the object with a color encoding the object index.
unsigned int r = (volume_id & 0x000000FF) >> 0; unsigned int r = (volume.second.first & 0x000000FF) >> 0;
unsigned int g = (volume_id & 0x0000FF00) >> 8; unsigned int g = (volume.second.first & 0x0000FF00) >> 8;
unsigned int b = (volume_id & 0x00FF0000) >> 16; unsigned int b = (volume.second.first & 0x00FF0000) >> 16;
glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255));
if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries))
volume.first->render();
} }
else
to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Transparent, view_matrix);
for (const GLVolumeWithIdAndZ& volume : to_render)
{ {
vol->set_render_color(); // Object picking mode. Render the object with a color encoding the object index.
glsafe(::glColor4fv(vol->render_color)); unsigned int r = (volume.second.first & 0x000000FF) >> 0;
} unsigned int g = (volume.second.first & 0x0000FF00) >> 8;
unsigned int b = (volume.second.first & 0x00FF0000) >> 16;
glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255));
if ((!fake_colors || !vol->disabled) && (vol->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries))
vol->render(); volume.first->render();
++volume_id;
} }
glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
@ -3719,9 +3782,6 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
if (!fake_colors)
glsafe(::glDisable(GL_LIGHTING));
} }
void GLCanvas3D::_render_current_gizmo() const void GLCanvas3D::_render_current_gizmo() const
@ -3999,15 +4059,9 @@ void GLCanvas3D::_update_volumes_hover_state() const
return; return;
GLVolume* volume = m_volumes.volumes[m_hover_volume_id]; GLVolume* volume = m_volumes.volumes[m_hover_volume_id];
if (volume->is_modifier)
switch (m_selection.get_mode())
{
case Selection::Volume:
{
volume->hover = true; volume->hover = true;
break; else
}
case Selection::Instance:
{ {
int object_idx = volume->object_idx(); int object_idx = volume->object_idx();
int instance_idx = volume->instance_idx(); int instance_idx = volume->instance_idx();
@ -4017,9 +4071,6 @@ void GLCanvas3D::_update_volumes_hover_state() const
if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
v->hover = true; v->hover = true;
} }
break;
}
} }
} }

View file

@ -65,6 +65,37 @@ public:
void set_scale_factor(int height); void set_scale_factor(int height);
}; };
class ClippingPlane
{
double m_data[4];
public:
ClippingPlane()
{
m_data[0] = 0.0;
m_data[1] = 0.0;
m_data[2] = 1.0;
m_data[3] = 0.0;
}
ClippingPlane(const Vec3d& direction, double offset)
{
Vec3d norm_dir = direction.normalized();
m_data[0] = norm_dir(0);
m_data[1] = norm_dir(1);
m_data[2] = norm_dir(2);
m_data[3] = offset;
}
bool is_active() const { return m_data[3] != DBL_MAX; }
static ClippingPlane ClipsNothing() { return ClippingPlane(Vec3d(0., 0., 1.), DBL_MAX); }
const double* get_data() const { return m_data; }
};
wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
using Vec2dEvent = Event<Vec2d>; using Vec2dEvent = Event<Vec2d>;
@ -288,32 +319,6 @@ class GLCanvas3D
} }
}; };
public:
class ClippingPlane
{
double m_data[4];
public:
ClippingPlane()
{
m_data[0] = 0.0;
m_data[1] = 0.0;
m_data[2] = 1.0;
m_data[3] = 0.0;
}
ClippingPlane(const Vec3d& direction, double offset)
{
Vec3d norm_dir = direction.normalized();
m_data[0] = norm_dir(0);
m_data[1] = norm_dir(1);
m_data[2] = norm_dir(2);
m_data[3] = offset;
}
const double* get_data() const { return m_data; }
};
private: private:
struct SlaCap struct SlaCap
{ {
@ -405,6 +410,7 @@ private:
mutable GLGizmosManager m_gizmos; mutable GLGizmosManager m_gizmos;
mutable GLToolbar m_toolbar; mutable GLToolbar m_toolbar;
ClippingPlane m_clipping_planes[2]; ClippingPlane m_clipping_planes[2];
mutable ClippingPlane m_camera_clipping_plane;
bool m_use_clipping_planes; bool m_use_clipping_planes;
mutable SlaCap m_sla_caps[2]; mutable SlaCap m_sla_caps[2];
std::string m_sidebar_field; std::string m_sidebar_field;
@ -579,6 +585,8 @@ public:
void refresh_camera_scene_box() { m_camera.set_scene_box(scene_bounding_box()); } void refresh_camera_scene_box() { m_camera.set_scene_box(scene_bounding_box()); }
bool is_mouse_dragging() const { return m_mouse.dragging; } bool is_mouse_dragging() const { return m_mouse.dragging; }
double get_size_proportional_to_max_bed_size(double factor) const;
private: private:
bool _is_shown_on_screen() const; bool _is_shown_on_screen() const;
@ -605,7 +613,7 @@ private:
#endif // ENABLE_RENDER_SELECTION_CENTER #endif // ENABLE_RENDER_SELECTION_CENTER
void _render_warning_texture() const; void _render_warning_texture() const;
void _render_legend_texture() const; void _render_legend_texture() const;
void _render_volumes(bool fake_colors) const; void _render_volumes_for_picking() const;
void _render_current_gizmo() const; void _render_current_gizmo() const;
void _render_gizmos_overlay() const; void _render_gizmos_overlay() const;
void _render_toolbar() const; void _render_toolbar() const;

View file

@ -21,6 +21,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_COPY, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_PASTE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);

View file

@ -20,6 +20,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_COPY, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_PASTE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);

View file

@ -61,19 +61,22 @@ ObjectList::ObjectList(wxWindow* parent) :
{ {
// Fill CATEGORY_ICON // Fill CATEGORY_ICON
{ {
// Note: `this` isn't passed to create_scaled_bitmap() here because of bugs in the widget,
// see note in PresetBundle::load_compatible_bitmaps()
// ptFFF // ptFFF
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(this, "layers"); CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(nullptr, "layers");
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(this, "infill"); CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(nullptr, "infill");
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(this, "support"); CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(nullptr, "support");
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(this, "time"); CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(nullptr, "time");
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(this, "funnel"); CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(nullptr, "funnel");
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(this, "funnel"); CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(nullptr, "funnel");
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(this, "skirt+brim"); // CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(nullptr, "skirt+brim");
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(this, "time"); // CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(nullptr, "time");
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(this, "wrench"); CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(nullptr, "wrench");
// ptSLA // ptSLA
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(this, "sla_supports"); CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(nullptr, "support"/*"sla_supports"*/);
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(this, "brick.png"); CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(nullptr, "pad");
} }
// create control // create control
@ -392,10 +395,10 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const
void ObjectList::init_icons() void ObjectList::init_icons()
{ {
m_bmp_modifiermesh = create_scaled_bitmap(this, "lambda.png"); m_bmp_modifiermesh = create_scaled_bitmap(nullptr, "add_modifier");
m_bmp_solidmesh = create_scaled_bitmap(this, "object.png"); m_bmp_solidmesh = create_scaled_bitmap(nullptr, "add_part");
m_bmp_support_enforcer = create_scaled_bitmap(this, "support_enforcer_.png"); m_bmp_support_enforcer = create_scaled_bitmap(nullptr, "support_enforcer");
m_bmp_support_blocker = create_scaled_bitmap(this, "support_blocker_.png"); m_bmp_support_blocker = create_scaled_bitmap(nullptr, "support_blocker");
m_bmp_vector.reserve(4); // bitmaps for different types of parts m_bmp_vector.reserve(4); // bitmaps for different types of parts
@ -406,13 +409,13 @@ void ObjectList::init_icons()
m_objects_model->SetVolumeBitmaps(m_bmp_vector); m_objects_model->SetVolumeBitmaps(m_bmp_vector);
// init icon for manifold warning // init icon for manifold warning
m_bmp_manifold_warning = create_scaled_bitmap(this, "exclamation_mark_.png"); m_bmp_manifold_warning = create_scaled_bitmap(nullptr, "exclamation");
// init bitmap for "Split to sub-objects" context menu // init bitmap for "Split to sub-objects" context menu
m_bmp_split = create_scaled_bitmap(this, "split_parts"); m_bmp_split = create_scaled_bitmap(nullptr, "split_parts_SMALL");
// init bitmap for "Add Settings" context menu // init bitmap for "Add Settings" context menu
m_bmp_cog = create_scaled_bitmap(this, "cog"); m_bmp_cog = create_scaled_bitmap(nullptr, "cog");
} }
@ -436,6 +439,66 @@ void ObjectList::selection_changed()
part_selection_changed(); part_selection_changed();
} }
void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes)
{
if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx))
return;
if (volumes.empty())
return;
ModelObject& model_object = *(*m_objects)[obj_idx];
const auto object_item = m_objects_model->GetItemById(obj_idx);
wxDataViewItemArray items;
for (const ModelVolume* volume : volumes)
{
auto vol_item = m_objects_model->AddVolumeChild(object_item, volume->name, volume->type(),
volume->config.has("extruder") ? volume->config.option<ConfigOptionInt>("extruder")->value : 0);
auto opt_keys = volume->config.keys();
if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder")))
select_item(m_objects_model->AddSettingsChild(vol_item));
items.Add(vol_item);
}
m_parts_changed = true;
parts_changed(obj_idx);
if (items.size() > 1)
{
m_selection_mode = smVolume;
m_last_selected_item = wxDataViewItem(0);
}
select_items(items);
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
selection_changed();
#endif //no __WXOSX__ //__WXMSW__
}
void ObjectList::paste_objects_into_list(const std::vector<size_t>& object_idxs)
{
if (object_idxs.empty())
return;
wxDataViewItemArray items;
for (const size_t object : object_idxs)
{
add_object_to_list(object);
m_parts_changed = true;
parts_changed(object);
items.Add(m_objects_model->GetItemById(object));
}
select_items(items);
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
selection_changed();
#endif //no __WXOSX__ //__WXMSW__
}
void ObjectList::OnChar(wxKeyEvent& event) void ObjectList::OnChar(wxKeyEvent& event)
{ {
if (event.GetKeyCode() == WXK_BACK){ if (event.GetKeyCode() == WXK_BACK){
@ -1374,9 +1437,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
const wxString name = _(L("Generic")) + "-" + _(type_name); const wxString name = _(L("Generic")) + "-" + _(type_name);
TriangleMesh mesh; TriangleMesh mesh;
auto& bed_shape = printer_config().option<ConfigOptionPoints>("bed_shape")->values; double side = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.1);
const auto& sz = BoundingBoxf(bed_shape).size();
const auto side = 0.1 * std::max(sz(0), sz(1));
if (type_name == "Box") if (type_name == "Box")
// Sitting on the print bed, left front front corner at (0, 0). // Sitting on the print bed, left front front corner at (0, 0).
@ -2132,6 +2193,7 @@ void ObjectList::update_selections_on_canvas()
add_to_selection(item, selection, instance_idx, false); add_to_selection(item, selection, instance_idx, false);
wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state(); wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->canvas3D()->render();
} }
void ObjectList::select_item(const wxDataViewItem& item) void ObjectList::select_item(const wxDataViewItem& item)

View file

@ -31,6 +31,8 @@ typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle;
// category -> vector ( option ; label ) // category -> vector ( option ; label )
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy; typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
typedef std::vector<ModelVolume*> ModelVolumePtrs;
namespace GUI { namespace GUI {
wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
@ -286,6 +288,9 @@ public:
void fix_through_netfabb() const; void fix_through_netfabb() const;
void update_item_error_icon(const int obj_idx, int vol_idx) const ; void update_item_error_icon(const int obj_idx, int vol_idx) const ;
void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes);
void paste_objects_into_list(const std::vector<size_t>& object_idxs);
void rescale(); void rescale();
private: private:

View file

@ -818,8 +818,8 @@ void Preview::on_sliders_scroll_changed(wxEvent& event)
} }
else if (tech == ptSLA) else if (tech == ptSLA)
{ {
m_canvas->set_clipping_plane(0, GLCanvas3D::ClippingPlane(Vec3d::UnitZ(), -m_slider->GetLowerValueD())); m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_slider->GetLowerValueD()));
m_canvas->set_clipping_plane(1, GLCanvas3D::ClippingPlane(-Vec3d::UnitZ(), m_slider->GetHigherValueD())); m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_slider->GetHigherValueD()));
m_canvas->set_use_clipping_planes(m_slider->GetHigherValue() != 0); m_canvas->set_use_clipping_planes(m_slider->GetHigherValue() != 0);
m_canvas_widget->Refresh(); m_canvas_widget->Refresh();
} }

View file

@ -10,6 +10,7 @@
#include "slic3r/GUI/GUI_ObjectSettings.hpp" #include "slic3r/GUI/GUI_ObjectSettings.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/PresetBundle.hpp" #include "slic3r/GUI/PresetBundle.hpp"
#include "libslic3r/Tesselate.hpp"
namespace Slic3r { namespace Slic3r {
@ -47,24 +48,24 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
{ {
if (selection.is_empty()) { if (selection.is_empty()) {
m_model_object = nullptr; m_model_object = nullptr;
m_old_model_object = nullptr;
return; return;
} }
m_old_model_object = m_model_object;
m_model_object = model_object; m_model_object = model_object;
m_active_instance = selection.get_instance_idx(); m_active_instance = selection.get_instance_idx();
if (model_object && selection.is_from_single_instance()) if (model_object && selection.is_from_single_instance())
{ {
// Cache the bb - it's needed for dealing with the clipping plane quite often
// It could be done inside update_mesh but one has to account for scaling of the instance.
//FIXME calling ModelObject::instance_bounding_box() is expensive!
m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius();
if (is_mesh_update_necessary()) { if (is_mesh_update_necessary()) {
update_mesh(); update_mesh();
editing_mode_reload_cache(); editing_mode_reload_cache();
} }
if (m_model_object != m_old_model_object)
m_editing_mode = false;
if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified) if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified)
get_data_from_backend(); get_data_from_backend();
@ -88,12 +89,75 @@ void GLGizmoSlaSupports::on_render(const Selection& selection) const
glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_BLEND));
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, false); // we'll recover current look direction from the modelview matrix (in world coords):
Eigen::Matrix<double, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z();
if (m_quadric != nullptr && selection.is_from_single_instance())
render_points(selection, direction_to_camera, false);
render_selection_rectangle(); render_selection_rectangle();
render_clipping_plane(selection, direction_to_camera);
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection, const Vec3d& direction_to_camera) const
{
if (m_clipping_plane_distance == 0.f)
return;
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
Transform3f instance_matrix = vol->get_instance_transformation().get_matrix().cast<float>();
Transform3f instance_matrix_no_translation_no_scaling = vol->get_instance_transformation().get_matrix(true,false,true).cast<float>();
Vec3f scaling = vol->get_instance_scaling_factor().cast<float>();
Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * direction_to_camera.cast<float>();
Vec3f up = Vec3f(up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
float height_mesh = (m_active_instance_bb_radius - m_clipping_plane_distance * 2*m_active_instance_bb_radius) * (up_noscale.norm()/up.norm());
if (m_clipping_plane_distance != m_old_clipping_plane_distance
|| m_old_direction_to_camera != direction_to_camera) {
std::vector<ExPolygons> list_of_expolys;
if (! m_tms) {
m_tms.reset(new TriangleMeshSlicer);
m_tms->init(const_cast<TriangleMesh*>(&m_mesh), [](){});
}
m_tms->set_up_direction(up);
m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){});
m_triangles = triangulate_expolygons_2f(list_of_expolys[0]);
m_old_direction_to_camera = direction_to_camera;
m_old_clipping_plane_distance = m_clipping_plane_distance;
}
if (! m_triangles.empty()) {
::glPushMatrix();
::glTranslated(0.0, 0.0, m_z_shift);
::glMultMatrixf(instance_matrix.data());
Eigen::Quaternionf q;
q.setFromTwoVectors(Vec3f::UnitZ(), up);
Eigen::AngleAxisf aa(q);
::glRotatef(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2));
::glTranslatef(0.f, 0.f, -0.001f); // to make sure the cut is safely beyond the near clipping plane
::glColor3f(1.0f, 0.37f, 0.0f);
::glBegin(GL_TRIANGLES);
::glColor3f(1.0f, 0.37f, 0.0f);
for (const Vec2f& point : m_triangles)
::glVertex3f(point(0), point(1), height_mesh);
::glEnd();
::glPopMatrix();
}
}
void GLGizmoSlaSupports::render_selection_rectangle() const void GLGizmoSlaSupports::render_selection_rectangle() const
{ {
if (m_selection_rectangle_status == srOff) if (m_selection_rectangle_status == srOff)
@ -143,24 +207,25 @@ void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const
{ {
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, true); // we'll recover current look direction from the modelview matrix (in world coords):
Eigen::Matrix<double, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
render_points(selection, direction_to_camera, true);
} }
void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const void GLGizmoSlaSupports::render_points(const Selection& selection, const Vec3d& direction_to_camera, bool picking) const
{ {
if (m_quadric == nullptr || !selection.is_from_single_instance())
return;
if (!picking) if (!picking)
glsafe(::glEnable(GL_LIGHTING)); glsafe(::glEnable(GL_LIGHTING));
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
double z_shift = vol->get_sla_shift_z();
const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix();
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(0.0, 0.0, z_shift)); glsafe(::glTranslated(0.0, 0.0, m_z_shift));
glsafe(::glMultMatrixd(instance_matrix.data())); glsafe(::glMultMatrixd(instance_matrix.data()));
float render_color[3]; float render_color[3];
@ -169,6 +234,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point; const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point;
const bool& point_selected = m_editing_mode_cache[i].selected; const bool& point_selected = m_editing_mode_cache[i].selected;
if (is_point_clipped(support_point.pos.cast<double>(), direction_to_camera))
continue;
// First decide about the color of the point. // First decide about the color of the point.
if (picking) { if (picking) {
std::array<float, 3> color = picking_color_component(i); std::array<float, 3> color = picking_color_component(i);
@ -238,13 +306,25 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
} }
bool GLGizmoSlaSupports::is_point_clipped(const Vec3d& point, const Vec3d& direction_to_camera) const
{
if (m_clipping_plane_distance == 0.f)
return false;
Vec3d transformed_point = m_model_object->instances.front()->get_transformation().get_matrix() * point;
transformed_point(2) += m_z_shift;
return direction_to_camera.dot(m_model_object->instances[m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift)) + m_active_instance_bb_radius
- m_clipping_plane_distance * 2*m_active_instance_bb_radius < direction_to_camera.dot(transformed_point);
}
bool GLGizmoSlaSupports::is_mesh_update_necessary() const bool GLGizmoSlaSupports::is_mesh_update_necessary() const
{ {
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty()) return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
&& ((m_model_object != m_old_model_object) || m_V.size()==0); && ((m_model_object->id() != m_current_mesh_model_id) || m_V.size()==0);
//if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix))
// return false;
} }
void GLGizmoSlaSupports::update_mesh() void GLGizmoSlaSupports::update_mesh()
@ -252,10 +332,9 @@ void GLGizmoSlaSupports::update_mesh()
wxBusyCursor wait; wxBusyCursor wait;
Eigen::MatrixXf& V = m_V; Eigen::MatrixXf& V = m_V;
Eigen::MatrixXi& F = m_F; Eigen::MatrixXi& F = m_F;
// Composite mesh of all instances in the world coordinate system.
// This mesh does not account for the possible Z up SLA offset. // This mesh does not account for the possible Z up SLA offset.
TriangleMesh mesh = m_model_object->raw_mesh(); m_mesh = m_model_object->raw_mesh();
const stl_file& stl = mesh.stl; const stl_file& stl = m_mesh.stl;
V.resize(3 * stl.stats.number_of_facets, 3); V.resize(3 * stl.stats.number_of_facets, 3);
F.resize(stl.stats.number_of_facets, 3); F.resize(stl.stats.number_of_facets, 3);
for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) { for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
@ -267,11 +346,15 @@ void GLGizmoSlaSupports::update_mesh()
F(i, 1) = 3*i+1; F(i, 1) = 3*i+1;
F(i, 2) = 3*i+2; F(i, 2) = 3*i+2;
} }
m_current_mesh_model_id = m_model_object->id();
m_editing_mode = false;
m_AABB = igl::AABB<Eigen::MatrixXf,3>(); m_AABB = igl::AABB<Eigen::MatrixXf,3>();
m_AABB.init(m_V, m_F); m_AABB.init(m_V, m_F);
} }
// Unprojects the mouse position on the mesh and return the hit point and normal of the facet.
// The function throws if no intersection if found.
std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
{ {
// if the gizmo doesn't have the V, F structures for igl, calculate them first: // if the gizmo doesn't have the V, F structures for igl, calculate them first:
@ -288,31 +371,53 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2)); ::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2)); ::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
igl::Hit hit; std::vector<igl::Hit> hits;
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
double z_offset = volume->get_sla_shift_z();
point1(2) -= z_offset; // we'll recover current look direction from the modelview matrix (in world coords):
point2(2) -= z_offset; Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
point1(2) -= m_z_shift;
point2(2) -= m_z_shift;
Transform3d inv = volume->get_instance_transformation().get_matrix().inverse(); Transform3d inv = volume->get_instance_transformation().get_matrix().inverse();
point1 = inv * point1; point1 = inv * point1;
point2 = inv * point2; point2 = inv * point2;
if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hit)) if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hits))
throw std::invalid_argument("unproject_on_mesh(): No intersection found."); throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
std::sort(hits.begin(), hits.end(), [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
// Now let's iterate through the points and find the first that is not clipped:
unsigned int i=0;
Vec3f bc;
Vec3f a;
Vec3f b;
Vec3f result;
for (i=0; i<hits.size(); ++i) {
igl::Hit& hit = hits[i];
int fid = hit.id; // facet id int fid = hit.id; // facet id
Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit bc = Vec3f(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit
Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0))); a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0)));
Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0))); b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0)));
result = bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2));
if (m_clipping_plane_distance == 0.f || !is_point_clipped(result.cast<double>(), direction_to_camera))
break;
}
if (i==hits.size() || (hits.size()-i) % 2 != 0) {
// All hits are either clipped, or there is an odd number of unclipped
// hits - meaning the nearest must be from inside the mesh.
throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
}
// Calculate and return both the point and the facet normal. // Calculate and return both the point and the facet normal.
return std::make_pair( return std::make_pair(
bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)), result,
a.cross(b) a.cross(b)
); );
} }
@ -383,36 +488,64 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); 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 // 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>())}); 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); const Transform3d& instance_matrix_no_translation_no_scaling = volume->get_instance_transformation().get_matrix(true,false,true);
// we'll recover current look direction from the modelview matrix (in world coords)... // we'll recover current look direction from the modelview matrix (in world coords)...
Vec3f direction_to_camera = camera.get_dir_forward().cast<float>(); Vec3f direction_to_camera = camera.get_dir_forward().cast<float>();
// ...and transform it to model coords. // ...and transform it to model coords.
direction_to_camera = (instance_matrix_no_translation.inverse().cast<float>() * direction_to_camera).normalized().eval(); Vec3f direction_to_camera_mesh = (instance_matrix_no_translation_no_scaling.inverse().cast<float>() * direction_to_camera).normalized().eval();
Vec3f scaling = volume->get_instance_scaling_factor().cast<float>();
direction_to_camera_mesh = Vec3f(direction_to_camera_mesh(0)*scaling(0), direction_to_camera_mesh(1)*scaling(1), direction_to_camera_mesh(2)*scaling(2));
// Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh: // 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) { for (unsigned int i=0; i<m_editing_mode_cache.size(); ++i) {
const sla::SupportPoint &support_point = m_editing_mode_cache[i].support_point; const sla::SupportPoint &support_point = m_editing_mode_cache[i].support_point;
Vec3f pos = instance_matrix.cast<float>() * support_point.pos; Vec3f pos = instance_matrix.cast<float>() * support_point.pos;
pos(2) += z_offset; pos(2) += m_z_shift;
GLdouble out_x, out_y, out_z; GLdouble out_x, out_y, out_z;
::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), (GLdouble*)modelview_matrix.data(), (GLdouble*)projection_matrix.data(), (GLint*)viewport.data(), &out_x, &out_y, &out_z); ::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), (GLdouble*)modelview_matrix.data(), (GLdouble*)projection_matrix.data(), (GLint*)viewport.data(), &out_x, &out_y, &out_z);
out_y = m_canvas_height - out_y; out_y = m_canvas_height - out_y;
if (rectangle.contains(Point(out_x, out_y))) { if (rectangle.contains(Point(out_x, out_y)) && !is_point_clipped(support_point.pos.cast<double>(), direction_to_camera.cast<double>())) {
bool is_obscured = false; bool is_obscured = false;
// Cast a ray in the direction of the camera and look for intersection with the mesh: // Cast a ray in the direction of the camera and look for intersection with the mesh:
std::vector<igl::Hit> hits; std::vector<igl::Hit> hits;
// Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies. // 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)) if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera_mesh * (support_point.head_front_radius + EPSILON), direction_to_camera_mesh, hits)) {
std::sort(hits.begin(), hits.end(), [](const igl::Hit& h1, const igl::Hit& h2) { return h1.t < h2.t; });
if (m_clipping_plane_distance != 0.f) {
// If the closest hit facet normal points in the same direction as the ray,
// we are looking through the mesh and should therefore discard the point:
int fid = hits.front().id; // facet id
Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0)));
Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0)));
if ((a.cross(b)).dot(direction_to_camera_mesh) > 0.f)
is_obscured = true;
// Eradicate all hits that are on clipped surfaces:
for (unsigned int j=0; j<hits.size(); ++j) {
const igl::Hit& hit = hits[j];
int fid = hit.id; // facet id
Vec3f bc = Vec3f(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit
Vec3f hit_pos = bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2));
if (is_point_clipped(hit_pos.cast<double>(), direction_to_camera.cast<double>())) {
hits.erase(hits.begin()+j);
--j;
}
}
}
// FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction. // 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. // Also, the threshold is in mesh coordinates, not in actual dimensions.
if (hits.size() > 1 || hits.front().t > 0.001f) if (!hits.empty())
is_obscured = true; is_obscured = true;
}
if (!is_obscured) { if (!is_obscured) {
if (m_selection_rectangle_status == srDeselect) if (m_selection_rectangle_status == srDeselect)
@ -570,6 +703,64 @@ void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const
ClippingPlane GLGizmoSlaSupports::get_sla_clipping_plane() const
{
if (!m_model_object || m_state == Off)
return ClippingPlane::ClipsNothing();
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
// we'll recover current look direction from the modelview matrix (in world coords):
Vec3d direction_to_camera(modelview_matrix.data()[2], modelview_matrix.data()[6], modelview_matrix.data()[10]);
float dist = direction_to_camera.dot(m_model_object->instances[m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift));
return ClippingPlane(-direction_to_camera.normalized(),(dist - (-m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_active_instance_bb_radius));
}
/*
void GLGizmoSlaSupports::find_intersecting_facets(const igl::AABB<Eigen::MatrixXf, 3>* aabb, const Vec3f& normal, double offset, std::vector<unsigned int>& idxs) const
{
if (aabb->is_leaf()) { // this is a facet
// corner.dot(normal) - offset
idxs.push_back(aabb->m_primitive);
}
else { // not a leaf
using CornerType = Eigen::AlignedBox<float, 3>::CornerType;
bool sign = std::signbit(offset - normal.dot(aabb->m_box.corner(CornerType(0))));
for (unsigned int i=1; i<8; ++i)
if (std::signbit(offset - normal.dot(aabb->m_box.corner(CornerType(i)))) != sign) {
find_intersecting_facets(aabb->m_left, normal, offset, idxs);
find_intersecting_facets(aabb->m_right, normal, offset, idxs);
}
}
}
void GLGizmoSlaSupports::make_line_segments() const
{
TriangleMeshSlicer tms(&m_model_object->volumes.front()->mesh);
Vec3f normal(0.f, 1.f, 1.f);
double d = 0.;
std::vector<IntersectionLine> lines;
find_intersections(&m_AABB, normal, d, lines);
ExPolygons expolys;
tms.make_expolygons_simple(lines, &expolys);
SVG svg("slice_loops.svg", get_extents(expolys));
svg.draw(expolys);
//for (const IntersectionLine &l : lines[i])
// svg.draw(l, "red", 0);
//svg.draw_outline(expolygons, "black", "blue", 0);
svg.Close();
}
*/
void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
{ {
if (!m_model_object) if (!m_model_object)
@ -580,7 +771,7 @@ void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_l
RENDER_AGAIN: RENDER_AGAIN:
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
const ImVec2 window_size(m_imgui->scaled(17.f, 18.f)); const ImVec2 window_size(m_imgui->scaled(17.f, 20.f));
ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) )); ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) ));
ImGui::SetNextWindowSize(ImVec2(window_size)); ImGui::SetNextWindowSize(ImVec2(window_size));
@ -687,6 +878,13 @@ RENDER_AGAIN:
(m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS")))); (m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS"))));
} }
// Following is rendered in both editing and non-editing mode:
m_imgui->text("Clipping of view: ");
ImGui::SameLine();
ImGui::PushItemWidth(150.0f);
bool value_changed = ImGui::SliderFloat(" ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f");
m_imgui->end(); m_imgui->end();
if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode
@ -740,12 +938,7 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state() void GLGizmoSlaSupports::on_set_state()
{ {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
wxGetApp().CallAfter([this]() {
if (m_state == On && m_old_state != On) { // the gizmo was just turned on if (m_state == On && m_old_state != On) { // the gizmo was just turned on
if (is_mesh_update_necessary()) if (is_mesh_update_necessary())
update_mesh(); update_mesh();
@ -762,6 +955,9 @@ void GLGizmoSlaSupports::on_set_state()
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value; m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
} }
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
if (m_model_object) { if (m_model_object) {
if (m_unsaved_changes) { if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points ?\n")), wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points ?\n")),
@ -772,13 +968,19 @@ void GLGizmoSlaSupports::on_set_state()
editing_mode_discard_changes(); editing_mode_discard_changes();
} }
} }
m_parent.toggle_model_objects_visibility(true); m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear(); m_editing_mode_cache.clear();
m_clipping_plane_distance = 0.f;
// Release copy of the mesh, triangle slicer and the AABB spatial search structure.
m_mesh.clear();
m_AABB.deinit();
m_V = Eigen::MatrixXf();
m_F = Eigen::MatrixXi();
m_tms.reset(nullptr);
});
} }
m_old_state = m_state; m_old_state = m_state;
});
} }
@ -827,9 +1029,17 @@ void GLGizmoSlaSupports::unselect_point(int i)
void GLGizmoSlaSupports::editing_mode_discard_changes() void GLGizmoSlaSupports::editing_mode_discard_changes()
{ {
// If the points were autogenerated, they may not be on the ModelObject yet.
// Because the user probably messed with the cache, we will get the data
// from the backend again.
if (m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated)
get_data_from_backend();
else {
m_editing_mode_cache.clear(); m_editing_mode_cache.clear();
for (const sla::SupportPoint& point : m_model_object->sla_support_points) for (const sla::SupportPoint& point : m_model_object->sla_support_points)
m_editing_mode_cache.emplace_back(point, false); m_editing_mode_cache.emplace_back(point, false);
}
m_editing_mode = false; m_editing_mode = false;
m_unsaved_changes = false; m_unsaved_changes = false;
} }

View file

@ -17,12 +17,17 @@ namespace Slic3r {
namespace GUI { namespace GUI {
class ClippingPlane;
class GLGizmoSlaSupports : public GLGizmoBase class GLGizmoSlaSupports : public GLGizmoBase
{ {
private: private:
ModelObject* m_model_object = nullptr; ModelObject* m_model_object = nullptr;
ModelObject* m_old_model_object = nullptr; ModelID m_current_mesh_model_id = 0;
int m_active_instance = -1; int m_active_instance = -1;
float m_active_instance_bb_radius; // to cache the bb
mutable float m_z_shift = 0.f;
std::pair<Vec3f, Vec3f> unproject_on_mesh(const Vec2d& mouse_pos); std::pair<Vec3f, Vec3f> unproject_on_mesh(const Vec2d& mouse_pos);
const float RenderPointScale = 1.f; const float RenderPointScale = 1.f;
@ -31,6 +36,8 @@ private:
Eigen::MatrixXf m_V; // vertices Eigen::MatrixXf m_V; // vertices
Eigen::MatrixXi m_F; // facets indices Eigen::MatrixXi m_F; // facets indices
igl::AABB<Eigen::MatrixXf,3> m_AABB; igl::AABB<Eigen::MatrixXf,3> m_AABB;
TriangleMesh m_mesh;
mutable std::vector<Vec2f> m_triangles;
class CacheEntry { class CacheEntry {
public: public:
@ -52,7 +59,7 @@ public:
void set_sla_support_data(ModelObject* model_object, const Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
void delete_selected_points(bool force = false); void delete_selected_points(bool force = false);
std::pair<float, float> get_sla_clipping_plane() const; ClippingPlane get_sla_clipping_plane() const;
private: private:
bool on_init(); bool on_init();
@ -61,7 +68,8 @@ private:
virtual void on_render_for_picking(const Selection& selection) const; virtual void on_render_for_picking(const Selection& selection) const;
void render_selection_rectangle() const; void render_selection_rectangle() const;
void render_points(const Selection& selection, bool picking = false) const; void render_points(const Selection& selection, const Vec3d& direction_to_camera, bool picking = false) const;
void render_clipping_plane(const Selection& selection, const Vec3d& direction_to_camera) const;
bool is_mesh_update_necessary() const; bool is_mesh_update_necessary() const;
void update_mesh(); void update_mesh();
void update_cache_entry_normal(unsigned int i) const; void update_cache_entry_normal(unsigned int i) const;
@ -74,6 +82,8 @@ private:
float m_density = 100.f; float m_density = 100.f;
mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
float m_clipping_plane_distance = 0.f; float m_clipping_plane_distance = 0.f;
mutable float m_old_clipping_plane_distance = 0.f;
mutable Vec3d m_old_direction_to_camera;
enum SelectionRectangleStatus { enum SelectionRectangleStatus {
srOff = 0, srOff = 0,
@ -90,7 +100,11 @@ private:
int m_canvas_width; int m_canvas_width;
int m_canvas_height; int m_canvas_height;
mutable std::unique_ptr<TriangleMeshSlicer> m_tms;
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const; std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
bool is_point_clipped(const Vec3d& point, const Vec3d& direction_to_camera) const;
void find_intersecting_facets(const igl::AABB<Eigen::MatrixXf, 3>* aabb, const Vec3f& normal, double offset, std::vector<unsigned int>& out) const;
// Methods that do the model_object and editing cache synchronization, // Methods that do the model_object and editing cache synchronization,
// editing mode selection, etc: // editing mode selection, etc:

View file

@ -467,6 +467,19 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
return false; return false;
} }
ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
{
if (!m_enabled || m_current != SlaSupports)
return ClippingPlane::ClipsNothing();
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end())
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->get_sla_clipping_plane();
return ClippingPlane::ClipsNothing();
}
void GLGizmosManager::render_current_gizmo(const Selection& selection) const void GLGizmosManager::render_current_gizmo(const Selection& selection) const
{ {
if (!m_enabled) if (!m_enabled)
@ -713,7 +726,12 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
{ {
switch (keyCode) switch (keyCode)
{ {
#ifdef __APPLE__
case 'a':
case 'A':
#else /* __APPLE__ */
case WXK_CONTROL_A: case WXK_CONTROL_A:
#endif /* __APPLE__ */
{ {
// Sla gizmo selects all support points // Sla gizmo selects all support points
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::SelectAll)) if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::SelectAll))

View file

@ -13,6 +13,7 @@ namespace GUI {
class Selection; class Selection;
class GLGizmoBase; class GLGizmoBase;
class GLCanvas3D; class GLCanvas3D;
class ClippingPlane;
class Rect class Rect
{ {
@ -146,7 +147,7 @@ public:
void set_sla_support_data(ModelObject* model_object, const Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_sla_clipping_plane() const;
void render_current_gizmo(const Selection& selection) const; void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const; void render_current_gizmo_for_picking_pass(const Selection& selection) const;

View file

@ -321,7 +321,7 @@ void MainFrame::init_menubar()
wxMenu* fileMenu = new wxMenu; wxMenu* fileMenu = new wxMenu;
{ {
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")), wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "open");
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")), wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "save"); [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "save");
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")), wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
@ -331,30 +331,30 @@ void MainFrame::init_menubar()
wxMenu* import_menu = new wxMenu(); wxMenu* import_menu = new wxMenu();
wxMenuItem* item_import_model = append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")), wxMenuItem* item_import_model = append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")),
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "brick_add.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater");
import_menu->AppendSeparator(); import_menu->AppendSeparator();
append_menu_item(import_menu, wxID_ANY, _(L("Import &Config")) + dots + "\tCtrl+L", _(L("Load exported configuration file")), append_menu_item(import_menu, wxID_ANY, _(L("Import &Config")) + dots + "\tCtrl+L", _(L("Load exported configuration file")),
[this](wxCommandEvent&) { load_config_file(); }, "plugin_add.png"); [this](wxCommandEvent&) { load_config_file(); }, "import_config");
append_menu_item(import_menu, wxID_ANY, _(L("Import Config from &project")) + dots +"\tCtrl+Alt+L", _(L("Load configuration from project file")), append_menu_item(import_menu, wxID_ANY, _(L("Import Config from &project")) + dots +"\tCtrl+Alt+L", _(L("Load configuration from project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "plugin_add.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "import_config");
import_menu->AppendSeparator(); import_menu->AppendSeparator();
append_menu_item(import_menu, wxID_ANY, _(L("Import Config &Bundle")) + dots, _(L("Load presets from a bundle")), append_menu_item(import_menu, wxID_ANY, _(L("Import Config &Bundle")) + dots, _(L("Load presets from a bundle")),
[this](wxCommandEvent&) { load_configbundle(); }, "lorry_add.png"); [this](wxCommandEvent&) { load_configbundle(); }, "import_config_bundle");
append_submenu(fileMenu, import_menu, wxID_ANY, _(L("&Import")), ""); append_submenu(fileMenu, import_menu, wxID_ANY, _(L("&Import")), "");
wxMenu* export_menu = new wxMenu(); wxMenu* export_menu = new wxMenu();
wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _(L("Export &G-code")) + dots +"\tCtrl+G", _(L("Export current plate as G-code")), wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _(L("Export &G-code")) + dots +"\tCtrl+G", _(L("Export current plate as G-code")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, "cog_go.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, "export_gcode");
export_menu->AppendSeparator(); export_menu->AppendSeparator();
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")), wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "brick_go.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "export_plater");
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")), wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "brick_go.png"); [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "export_plater");
export_menu->AppendSeparator(); export_menu->AppendSeparator();
append_menu_item(export_menu, wxID_ANY, _(L("Export &Config")) +dots +"\tCtrl+E", _(L("Export current configuration to file")), append_menu_item(export_menu, wxID_ANY, _(L("Export &Config")) +dots +"\tCtrl+E", _(L("Export current configuration to file")),
[this](wxCommandEvent&) { export_config(); }, "plugin_go.png"); [this](wxCommandEvent&) { export_config(); }, "export_config");
append_menu_item(export_menu, wxID_ANY, _(L("Export Config &Bundle")) + dots, _(L("Export all presets to file")), append_menu_item(export_menu, wxID_ANY, _(L("Export Config &Bundle")) + dots, _(L("Export all presets to file")),
[this](wxCommandEvent&) { export_configbundle(); }, "lorry_go.png"); [this](wxCommandEvent&) { export_configbundle(); }, "export_config_bundle");
append_submenu(fileMenu, export_menu, wxID_ANY, _(L("&Export")), ""); append_submenu(fileMenu, export_menu, wxID_ANY, _(L("&Export")), "");
fileMenu->AppendSeparator(); fileMenu->AppendSeparator();
@ -382,10 +382,10 @@ void MainFrame::init_menubar()
fileMenu->AppendSeparator(); fileMenu->AppendSeparator();
#endif #endif
m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(Re)Slice &Now")) + "\tCtrl+R", _(L("Start new slicing process")), m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(Re)Slice &Now")) + "\tCtrl+R", _(L("Start new slicing process")),
[this](wxCommandEvent&) { reslice_now(); }, "shape_handles.png"); [this](wxCommandEvent&) { reslice_now(); }, "re_slice");
fileMenu->AppendSeparator(); fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")), append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")),
[this](wxCommandEvent&) { repair_stl(); }, "wrench.png"); [this](wxCommandEvent&) { repair_stl(); }, "wrench");
fileMenu->AppendSeparator(); fileMenu->AppendSeparator();
append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")), append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")),
[this](wxCommandEvent&) { Close(false); }); [this](wxCommandEvent&) { Close(false); });
@ -425,13 +425,22 @@ void MainFrame::init_menubar()
[this](wxCommandEvent&) { m_plater->select_all(); }, ""); [this](wxCommandEvent&) { m_plater->select_all(); }, "");
editMenu->AppendSeparator(); editMenu->AppendSeparator();
wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, _(L("Deletes the current selection")), wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, _(L("Deletes the current selection")),
[this](wxCommandEvent&) { m_plater->remove_selected(); }, ""); [this](wxCommandEvent&) { m_plater->remove_selected(); }, "remove_menu");
wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")), wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")),
[this](wxCommandEvent&) { m_plater->reset(); }, ""); [this](wxCommandEvent&) { m_plater->reset(); }, "delete_all_menu");
editMenu->AppendSeparator();
wxMenuItem* item_copy = append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + "\tCtrl+C", _(L("Copy selection to clipboard")),
[this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, "copy_menu");
wxMenuItem* item_paste = append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + "\tCtrl+V", _(L("Paste clipboard")),
[this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, "paste_menu");
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_copy()); }, item_copy->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_paste()); }, item_paste->GetId());
} }
// Window menu // Window menu
@ -440,7 +449,7 @@ void MainFrame::init_menubar()
size_t tab_offset = 0; size_t tab_offset = 0;
if (m_plater) { if (m_plater) {
append_menu_item(windowMenu, wxID_HIGHEST + 1, _(L("&Plater Tab")) + "\tCtrl+1", _(L("Show the plater")), append_menu_item(windowMenu, wxID_HIGHEST + 1, _(L("&Plater Tab")) + "\tCtrl+1", _(L("Show the plater")),
[this](wxCommandEvent&) { select_tab(0); }, "application_view_tile.png"); [this](wxCommandEvent&) { select_tab(0); }, "plater");
tab_offset += 1; tab_offset += 1;
} }
if (tab_offset > 0) { if (tab_offset > 0) {
@ -455,9 +464,9 @@ void MainFrame::init_menubar()
if (m_plater) { if (m_plater) {
windowMenu->AppendSeparator(); windowMenu->AppendSeparator();
wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")), wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")),
[this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, ""); [this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, "editor_menu");
wxMenuItem* item_preview = append_menu_item(windowMenu, wxID_HIGHEST + 6, _(L("Pre&view")) + "\tCtrl+6", _(L("Show the 3D slices preview")), wxMenuItem* item_preview = append_menu_item(windowMenu, wxID_HIGHEST + 6, _(L("Pre&view")) + "\tCtrl+6", _(L("Show the 3D slices preview")),
[this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, ""); [this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, "preview_menu");
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_3d->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_3d->GetId());
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_preview->GetId()); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_preview->GetId());
@ -478,7 +487,7 @@ void MainFrame::init_menubar()
windowMenu->AppendSeparator(); windowMenu->AppendSeparator();
append_menu_item(windowMenu, wxID_ANY, _(L("Print &Host Upload Queue")) + "\tCtrl+J", _(L("Display the Print Host Upload Queue window")), append_menu_item(windowMenu, wxID_ANY, _(L("Print &Host Upload Queue")) + "\tCtrl+J", _(L("Display the Print Host Upload Queue window")),
[this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "arrow_up.png"); [this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue");
} }
// View menu // View menu
@ -590,7 +599,7 @@ void MainFrame::quick_slice(const int qs)
dlg->ShowModal(); dlg->ShowModal();
return; return;
} }
if (std::ifstream(m_qs_last_input_file.char_str())) { if (std::ifstream(m_qs_last_input_file.ToUTF8().data())) {
auto dlg = new wxMessageDialog(this, _(L("Previously sliced file ("))+m_qs_last_input_file+_(L(") not found.")), auto dlg = new wxMessageDialog(this, _(L("Previously sliced file ("))+m_qs_last_input_file+_(L(") not found.")),
_(L("File Not Found")), wxICON_ERROR | wxOK); _(L("File Not Found")), wxICON_ERROR | wxOK);
dlg->ShowModal(); dlg->ShowModal();
@ -705,24 +714,23 @@ void MainFrame::repair_stl()
dlg->Destroy(); dlg->Destroy();
} }
auto output_file = input_file; wxString output_file = input_file;
{ {
// output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ;
auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"), auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"),
get_dir_name(output_file), get_base_name(output_file), get_dir_name(output_file), get_base_name(output_file, ".obj"),
file_wildcards(FT_OBJ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); file_wildcards(FT_OBJ), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (dlg->ShowModal() != wxID_OK) { if (dlg->ShowModal() != wxID_OK) {
dlg->Destroy(); dlg->Destroy();
return /*undef*/; return;
} }
output_file = dlg->GetPath(); output_file = dlg->GetPath();
dlg->Destroy(); dlg->Destroy();
} }
auto tmesh = new Slic3r::TriangleMesh(); auto tmesh = new Slic3r::TriangleMesh();
tmesh->ReadSTLFile(input_file.char_str()); tmesh->ReadSTLFile(input_file.ToUTF8().data());
tmesh->repair(); tmesh->repair();
tmesh->WriteOBJFile(output_file.char_str()); tmesh->WriteOBJFile(output_file.ToUTF8().data());
Slic3r::GUI::show_info(this, L("Your file was repaired."), L("Repair")); Slic3r::GUI::show_info(this, L("Your file was repaired."), L("Repair"));
} }
@ -962,9 +970,12 @@ void MainFrame::update_ui_from_settings()
tab->update_ui_from_settings(); tab->update_ui_from_settings();
} }
std::string MainFrame::get_base_name(const wxString &full_name) const std::string MainFrame::get_base_name(const wxString &full_name, const char *extension) const
{ {
return boost::filesystem::path(full_name.wx_str()).filename().string(); boost::filesystem::path filename = boost::filesystem::path(full_name.wx_str()).filename();
if (extension != nullptr)
filename = filename.replace_extension(extension);
return filename.string();
} }
std::string MainFrame::get_dir_name(const wxString &full_name) const std::string MainFrame::get_dir_name(const wxString &full_name) const

View file

@ -54,7 +54,7 @@ class MainFrame : public DPIFrame
PrintHostQueueDialog *m_printhost_queue_dlg; PrintHostQueueDialog *m_printhost_queue_dlg;
std::string get_base_name(const wxString &full_name) const; std::string get_base_name(const wxString &full_name, const char *extension = nullptr) const;
std::string get_dir_name(const wxString &full_name) const; std::string get_dir_name(const wxString &full_name) const;
void on_presets_changed(SimpleEvent&); void on_presets_changed(SimpleEvent&);

View file

@ -144,8 +144,7 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
info_manifold_text->SetFont(wxGetApp().small_font()); info_manifold_text->SetFont(wxGetApp().small_font());
info_manifold = new wxStaticText(parent, wxID_ANY, ""); info_manifold = new wxStaticText(parent, wxID_ANY, "");
info_manifold->SetFont(wxGetApp().small_font()); info_manifold->SetFont(wxGetApp().small_font());
wxBitmap bitmap(GUI::from_u8(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, create_scaled_bitmap(parent, "exclamation"));
manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, bitmap);
auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL); auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL);
sizer_manifold->Add(info_manifold_text, 0); sizer_manifold->Add(info_manifold_text, 0);
sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2); sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2);
@ -1477,6 +1476,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_COPY, [q](SimpleEvent&) { q->copy_selection_to_clipboard(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_PASTE, [q](SimpleEvent&) { q->paste_from_clipboard(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); });
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this); view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
@ -1719,11 +1720,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (advanced) if (advanced)
{ {
wxMessageDialog dlg(q, _(L("This file cannot be loaded in simple mode. Do you want to switch to expert mode?\n")), wxMessageDialog dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?\n")),
_(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO); _(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) if (dlg.ShowModal() == wxID_YES)
{ {
Slic3r::GUI::wxGetApp().save_mode(comExpert); Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
view3D->set_as_dirty(); view3D->set_as_dirty();
} }
else else
@ -2669,25 +2670,21 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
this->statusbar()->set_progress(evt.status.percent); this->statusbar()->set_progress(evt.status.percent);
this->statusbar()->set_status_text(_(L(evt.status.text)) + wxString::FromUTF8("")); this->statusbar()->set_status_text(_(L(evt.status.text)) + wxString::FromUTF8(""));
} }
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SCENE) { if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE || PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) {
switch (this->printer_technology) { switch (this->printer_technology) {
case ptFFF: case ptFFF:
this->update_fff_scene(); this->update_fff_scene();
break; break;
case ptSLA: case ptSLA:
// If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
if (view3D->is_dragging()) if (view3D->is_dragging())
delayed_scene_refresh = true; delayed_scene_refresh = true;
else else
this->update_sla_scene(); this->update_sla_scene();
break; break;
} }
} } else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS) { // Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
// Update SLA gizmo (reload_scene calls update_gizmos_data)
q->canvas3D()->reload_scene(true);
}
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
// Update the SLA preview
this->preview->reload_print(); this->preview->reload_print();
} }
} }
@ -2895,17 +2892,17 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
wxMenuItem* item_delete = nullptr; wxMenuItem* item_delete = nullptr;
if (is_part) { if (is_part) {
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "remove"); [this](wxCommandEvent&) { q->remove_selected(); }, "delete");
sidebar->obj_list()->append_menu_item_export_stl(menu); sidebar->obj_list()->append_menu_item_export_stl(menu);
} }
else { else {
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")), wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")),
[this](wxCommandEvent&) { q->increase_instances(); }, "instance_add"); [this](wxCommandEvent&) { q->increase_instances(); }, "add_copies");
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")), wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")),
[this](wxCommandEvent&) { q->decrease_instances(); }, "instance_remove"); [this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies");
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")), wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png"); [this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies");
items_increase.push_back(item_increase); items_increase.push_back(item_increase);
items_decrease.push_back(item_decrease); items_decrease.push_back(item_decrease);
@ -2913,7 +2910,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake. // Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "remove"); [this](wxCommandEvent&) { q->remove_selected(); }, "delete");
menu->AppendSeparator(); menu->AppendSeparator();
wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu); wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu);
@ -2943,11 +2940,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
return false; return false;
append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")), append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")),
[this](wxCommandEvent&) { mirror(X); }, "bullet_red.png", menu); [this](wxCommandEvent&) { mirror(X); }, "mark_X", menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")), append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")),
[this](wxCommandEvent&) { mirror(Y); }, "bullet_green.png", menu); [this](wxCommandEvent&) { mirror(Y); }, "mark_Y", menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")), append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")),
[this](wxCommandEvent&) { mirror(Z); }, "bullet_blue.png", menu); [this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu);
wxMenuItem* item_mirror = append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); wxMenuItem* item_mirror = append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")));
@ -2968,9 +2965,9 @@ bool Plater::priv::complit_init_object_menu()
return false; return false;
wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")),
[this](wxCommandEvent&) { split_object(); }, "split_objects.png", &object_menu); [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu);
wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")),
[this](wxCommandEvent&) { split_volume(); }, "split_parts.png", &object_menu); [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu);
wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object"))/*, "shape_ungroup.png"*/); wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object"))/*, "shape_ungroup.png"*/);
object_menu.AppendSeparator(); object_menu.AppendSeparator();
@ -2990,7 +2987,7 @@ bool Plater::priv::complit_init_object_menu()
bool Plater::priv::complit_init_sla_object_menu() bool Plater::priv::complit_init_sla_object_menu()
{ {
wxMenuItem* item_split = append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")), wxMenuItem* item_split = append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")),
[this](wxCommandEvent&) { split_object(); }, "shape_ungroup_o.png"); [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL");
sla_object_menu.AppendSeparator(); sla_object_menu.AppendSeparator();
@ -3010,7 +3007,7 @@ bool Plater::priv::complit_init_sla_object_menu()
bool Plater::priv::complit_init_part_menu() bool Plater::priv::complit_init_part_menu()
{ {
wxMenuItem* item_split = append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")), wxMenuItem* item_split = append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")),
[this](wxCommandEvent&) { split_volume(); }, "shape_ungroup_p.png"); [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL");
part_menu.AppendSeparator(); part_menu.AppendSeparator();
@ -3117,7 +3114,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
bool Plater::priv::can_delete() const bool Plater::priv::can_delete() const
{ {
return !get_selection().is_empty(); return !get_selection().is_empty() && !get_selection().is_wipe_tower();
} }
bool Plater::priv::can_delete_all() const bool Plater::priv::can_delete_all() const
@ -3299,8 +3296,9 @@ void Plater::increase_instances(size_t num)
bool was_one_instance = model_object->instances.size()==1; bool was_one_instance = model_object->instances.size()==1;
float offset = 10.0; double offset_base = canvas3D()->get_size_proportional_to_max_bed_size(0.05);
for (size_t i = 0; i < num; i++, offset += 10.0) { double offset = offset_base;
for (size_t i = 0; i < num; i++, offset += offset_base) {
Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0);
model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation(), model_instance->get_mirror()); model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation(), model_instance->get_mirror());
// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); // p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec));
@ -3368,7 +3366,7 @@ void Plater::set_number_of_copies(/*size_t num*/)
bool Plater::is_selection_empty() const bool Plater::is_selection_empty() const
{ {
return p->get_selection().is_empty(); return p->get_selection().is_empty() || p->get_selection().is_wipe_tower();
} }
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower) void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
@ -3771,10 +3769,43 @@ void Plater::changed_object(int obj_idx)
this->p->schedule_background_process(); this->p->schedule_background_process();
} }
void Plater::schedule_background_process()
{
this->p->schedule_background_process();
}
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); } void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
void Plater::update_object_menu() { p->update_object_menu(); } void Plater::update_object_menu() { p->update_object_menu(); }
void Plater::copy_selection_to_clipboard()
{
p->view3D->get_canvas3d()->get_selection().copy_to_clipboard();
}
void Plater::paste_from_clipboard()
{
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
}
bool Plater::can_paste_from_clipboard() const
{
const Selection& selection = p->view3D->get_canvas3d()->get_selection();
const Selection::Clipboard& clipboard = selection.get_clipboard();
Selection::EMode mode = clipboard.get_mode();
if (clipboard.is_empty())
return false;
if ((mode == Selection::Volume) && !selection.is_from_single_instance())
return false;
if ((mode == Selection::Instance) && (selection.get_mode() != Selection::Instance))
return false;
return true;
}
bool Plater::can_delete() const { return p->can_delete(); } bool Plater::can_delete() const { return p->can_delete(); }
bool Plater::can_delete_all() const { return p->can_delete_all(); } bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_increase_instances() const { return p->can_increase_instances(); } bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
@ -3783,5 +3814,7 @@ bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); }
bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
bool Plater::can_arrange() const { return p->can_arrange(); } bool Plater::can_arrange() const { return p->can_arrange(); }
bool Plater::can_layers_editing() const { return p->can_layers_editing(); } bool Plater::can_layers_editing() const { return p->can_layers_editing(); }
bool Plater::can_copy() const { return !is_selection_empty(); }
bool Plater::can_paste() const { return can_paste_from_clipboard(); }
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI

View file

@ -167,6 +167,7 @@ public:
void reslice(); void reslice();
void reslice_SLA_supports(const ModelObject &object); void reslice_SLA_supports(const ModelObject &object);
void changed_object(int obj_idx); void changed_object(int obj_idx);
void schedule_background_process();
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
void send_gcode(); void send_gcode();
@ -187,6 +188,10 @@ public:
PrinterTechnology printer_technology() const; PrinterTechnology printer_technology() const;
void set_printer_technology(PrinterTechnology printer_technology); void set_printer_technology(PrinterTechnology printer_technology);
void copy_selection_to_clipboard();
void paste_from_clipboard();
bool can_paste_from_clipboard() const;
bool can_delete() const; bool can_delete() const;
bool can_delete_all() const; bool can_delete_all() const;
bool can_increase_instances() const; bool can_increase_instances() const;
@ -195,6 +200,8 @@ public:
bool can_split_to_volumes() const; bool can_split_to_volumes() const;
bool can_arrange() const; bool can_arrange() const;
bool can_layers_editing() const; bool can_layers_editing() const;
bool can_copy() const;
bool can_paste() const;
private: private:
struct priv; struct priv;

View file

@ -801,12 +801,16 @@ bool PresetCollection::delete_current_preset()
void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name) void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name)
{ {
*m_bitmap_main_frame = create_scaled_bitmap(window, file_name); // XXX: See note in PresetBundle::load_compatible_bitmaps()
(void)window;
*m_bitmap_main_frame = create_scaled_bitmap(nullptr, file_name);
} }
void PresetCollection::load_bitmap_add(wxWindow *window, const std::string &file_name) void PresetCollection::load_bitmap_add(wxWindow *window, const std::string &file_name)
{ {
*m_bitmap_add = create_scaled_bitmap(window, file_name); // XXX: See note in PresetBundle::load_compatible_bitmaps()
(void)window;
*m_bitmap_add = create_scaled_bitmap(nullptr, file_name);
} }
const Preset* PresetCollection::get_selected_preset_parent() const const Preset* PresetCollection::get_selected_preset_parent() const

View file

@ -398,22 +398,27 @@ void PresetBundle::export_selections(AppConfig &config)
void PresetBundle::load_compatible_bitmaps(wxWindow *window) void PresetBundle::load_compatible_bitmaps(wxWindow *window)
{ {
*m_bitmapCompatible = create_scaled_bitmap(window, "flag_green"); // We don't actually pass the window pointer here and instead generate
*m_bitmapIncompatible = create_scaled_bitmap(window, "flag_red"); // a low DPI bitmap, because the wxBitmapComboBox and wxDataViewCtrl don't support
*m_bitmapLock = create_scaled_bitmap(window, "lock_closed"); // high DPI bitmaps very well, they compute their dimensions wrong.
*m_bitmapLockOpen = create_scaled_bitmap(window, "sys_unlock.png"); // TODO: Update this when fixed in wxWidgets
// See also PresetCollection::load_bitmap_default() and PresetCollection::load_bitmap_add()
(void)window;
*m_bitmapCompatible = create_scaled_bitmap(nullptr, "flag_green");
*m_bitmapIncompatible = create_scaled_bitmap(nullptr, "flag_red");
*m_bitmapLock = create_scaled_bitmap(nullptr, "lock_closed");
*m_bitmapLockOpen = create_scaled_bitmap(nullptr, "sys_unlock.png");
prints .set_bitmap_compatible(m_bitmapCompatible); prints .set_bitmap_compatible(m_bitmapCompatible);
filaments .set_bitmap_compatible(m_bitmapCompatible); filaments .set_bitmap_compatible(m_bitmapCompatible);
sla_prints .set_bitmap_compatible(m_bitmapCompatible); sla_prints .set_bitmap_compatible(m_bitmapCompatible);
sla_materials.set_bitmap_compatible(m_bitmapCompatible); sla_materials.set_bitmap_compatible(m_bitmapCompatible);
printers .set_bitmap_compatible(m_bitmapCompatible);
prints .set_bitmap_incompatible(m_bitmapIncompatible); prints .set_bitmap_incompatible(m_bitmapIncompatible);
filaments .set_bitmap_incompatible(m_bitmapIncompatible); filaments .set_bitmap_incompatible(m_bitmapIncompatible);
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible); sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible); sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
printers .set_bitmap_incompatible(m_bitmapIncompatible);
prints .set_bitmap_lock(m_bitmapLock); prints .set_bitmap_lock(m_bitmapLock);
filaments .set_bitmap_lock(m_bitmapLock); filaments .set_bitmap_lock(m_bitmapLock);

View file

@ -1022,6 +1022,77 @@ bool Selection::requires_local_axes() const
return (m_mode == Volume) && is_from_single_instance(); return (m_mode == Volume) && is_from_single_instance();
} }
void Selection::copy_to_clipboard()
{
if (!m_valid)
return;
m_clipboard.reset();
for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content)
{
ModelObject* src_object = m_model->objects[object.first];
ModelObject* dst_object = m_clipboard.add_object();
dst_object->name = src_object->name;
dst_object->input_file = src_object->input_file;
dst_object->config = src_object->config;
dst_object->sla_support_points = src_object->sla_support_points;
dst_object->sla_points_status = src_object->sla_points_status;
dst_object->layer_height_ranges = src_object->layer_height_ranges;
dst_object->layer_height_profile = src_object->layer_height_profile;
dst_object->origin_translation = src_object->origin_translation;
for (int i : object.second)
{
dst_object->add_instance(*src_object->instances[i]);
}
for (unsigned int i : m_list)
{
// Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance.
const GLVolume* volume = (*m_volumes)[i];
if ((volume->object_idx() == object.first) && (volume->instance_idx() == *object.second.begin()))
{
int volume_idx = volume->volume_idx();
if ((0 <= volume_idx) && (volume_idx < (int)src_object->volumes.size()))
{
ModelVolume* src_volume = src_object->volumes[volume_idx];
ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
dst_volume->set_new_unique_id();
} else {
assert(false);
}
}
}
}
m_clipboard.set_mode(m_mode);
}
void Selection::paste_from_clipboard()
{
if (!m_valid || m_clipboard.is_empty())
return;
switch (m_clipboard.get_mode())
{
case Volume:
{
if (is_from_single_instance())
paste_volumes_from_clipboard();
break;
}
case Instance:
{
if (m_mode == Instance)
paste_objects_from_clipboard();
break;
}
}
}
void Selection::update_valid() void Selection::update_valid()
{ {
m_valid = (m_volumes != nullptr) && (m_model != nullptr); m_valid = (m_volumes != nullptr) && (m_model != nullptr);
@ -1697,5 +1768,44 @@ bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
return count == (unsigned int)m_model->objects[object_idx]->volumes.size(); return count == (unsigned int)m_model->objects[object_idx]->volumes.size();
} }
void Selection::paste_volumes_from_clipboard()
{
int obj_idx = get_object_idx();
if ((obj_idx < 0) || ((int)m_model->objects.size() <= obj_idx))
return;
ModelObject* src_object = m_clipboard.get_object(0);
if (src_object != nullptr)
{
ModelObject* dst_object = m_model->objects[obj_idx];
ModelVolumePtrs volumes;
for (ModelVolume* src_volume : src_object->volumes)
{
ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
dst_volume->set_new_unique_id();
double offset = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.05);
dst_volume->translate(offset, offset, 0.0);
volumes.push_back(dst_volume);
}
wxGetApp().obj_list()->paste_volumes_into_list(obj_idx, volumes);
}
}
void Selection::paste_objects_from_clipboard()
{
std::vector<size_t> object_idxs;
const ModelObjectPtrs& src_objects = m_clipboard.get_objects();
for (const ModelObject* src_object : src_objects)
{
ModelObject* dst_object = m_model->add_object(*src_object);
double offset = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.05);
dst_object->translate(offset, offset, 0.0);
object_idxs.push_back(m_model->objects.size() - 1);
}
wxGetApp().obj_list()->paste_objects_into_list(object_idxs);
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View file

@ -138,6 +138,23 @@ public:
typedef std::set<int> InstanceIdxsList; typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap; typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
class Clipboard
{
Model m_model;
Selection::EMode m_mode;
public:
void reset() { m_model.clear_objects(); }
bool is_empty() const { return m_model.objects.empty(); }
ModelObject* add_object() { return m_model.add_object(); }
ModelObject* get_object(unsigned int id) { return (id < (unsigned int)m_model.objects.size()) ? m_model.objects[id] : nullptr; }
const ModelObjectPtrs& get_objects() const { return m_model.objects; }
Selection::EMode get_mode() const { return m_mode; }
void set_mode(Selection::EMode mode) { m_mode = mode; }
};
private: private:
struct Cache struct Cache
{ {
@ -163,6 +180,7 @@ private:
// set of indices to m_volumes // set of indices to m_volumes
IndicesList m_list; IndicesList m_list;
Cache m_cache; Cache m_cache;
Clipboard m_clipboard;
mutable BoundingBoxf3 m_bounding_box; mutable BoundingBoxf3 m_bounding_box;
mutable bool m_bounding_box_dirty; mutable bool m_bounding_box_dirty;
@ -267,6 +285,11 @@ public:
bool requires_local_axes() const; bool requires_local_axes() const;
void copy_to_clipboard();
void paste_from_clipboard();
const Clipboard& get_clipboard() const { return m_clipboard; }
private: private:
void update_valid(); void update_valid();
void update_type(); void update_type();
@ -301,6 +324,9 @@ private:
void synchronize_unselected_volumes(); void synchronize_unselected_volumes();
void ensure_on_bed(); void ensure_on_bed();
bool is_from_fully_selected_instance(unsigned int volume_idx) const; bool is_from_fully_selected_instance(unsigned int volume_idx) const;
void paste_volumes_from_clipboard();
void paste_objects_from_clipboard();
}; };
} // namespace GUI } // namespace GUI

View file

@ -166,9 +166,12 @@ void Tab::create_preset_tab()
m_bmp_non_system = &m_bmp_white_bullet; m_bmp_non_system = &m_bmp_white_bullet;
// Bitmaps to be shown on the "Undo user changes" button next to each input field. // Bitmaps to be shown on the "Undo user changes" button next to each input field.
// m_bmp_value_revert = create_scaled_bitmap(this, "undo"); // m_bmp_value_revert = create_scaled_bitmap(this, "undo");
// m_bmp_white_bullet = create_scaled_bitmap(this, luma >= 128 ? "dot" : "dot_white"/*"bullet_white.png"*/);
// m_bmp_question = create_scaled_bitmap(this, "question");
// m_bmp_value_revert = create_scaled_bitmap(this, "undo");
// m_bmp_white_bullet = create_scaled_bitmap(this, "bullet_white.png"); // m_bmp_white_bullet = create_scaled_bitmap(this, "bullet_white.png");
add_scaled_bitmap(this, m_bmp_value_revert, "undo"); add_scaled_bitmap(this, m_bmp_value_revert, "undo");
add_scaled_bitmap(this, m_bmp_white_bullet, "bullet_white.png"); add_scaled_bitmap(this, m_bmp_white_bullet, luma >= 128 ? "dot" : "dot_white"/*"bullet_white.png"*/);
fill_icon_descriptions(); fill_icon_descriptions();
set_tooltips_text(); set_tooltips_text();
@ -1163,7 +1166,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Advanced"))); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("interface_shells"); optgroup->append_single_option_line("interface_shells");
page = add_options_page(_(L("Advanced")), "wrench.png"); page = add_options_page(_(L("Advanced")), "wrench");
optgroup = page->new_optgroup(_(L("Extrusion width"))); optgroup = page->new_optgroup(_(L("Extrusion width")));
optgroup->append_single_option_line("extrusion_width"); optgroup->append_single_option_line("extrusion_width");
optgroup->append_single_option_line("first_layer_extrusion_width"); optgroup->append_single_option_line("first_layer_extrusion_width");
@ -1536,7 +1539,7 @@ void TabFilament::build()
optgroup->append_single_option_line("slowdown_below_layer_time"); optgroup->append_single_option_line("slowdown_below_layer_time");
optgroup->append_single_option_line("min_print_speed"); optgroup->append_single_option_line("min_print_speed");
page = add_options_page(_(L("Advanced")), "wrench.png"); page = add_options_page(_(L("Advanced")), "wrench");
optgroup = page->new_optgroup(_(L("Filament properties"))); optgroup = page->new_optgroup(_(L("Filament properties")));
optgroup->append_single_option_line("filament_type"); optgroup->append_single_option_line("filament_type");
optgroup->append_single_option_line("filament_soluble"); optgroup->append_single_option_line("filament_soluble");
@ -1704,10 +1707,15 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto printhost_browse = [=](wxWindow* parent) { auto printhost_browse = [=](wxWindow* parent) {
// auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots, // auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots,
// wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); // wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
// btn->SetBitmap(create_scaled_bitmap(this, "browse"));
// auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots,
// wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetBitmap(create_scaled_bitmap(this, "zoom.png")); // btn->SetBitmap(create_scaled_bitmap(this, "zoom.png"));
add_scaled_button(parent, &m_printhost_browse_btn, "zoom.png", _(L(" Browse ")) + dots, wxBU_LEFT | wxBU_EXACTFIT); add_scaled_button(parent, &m_printhost_browse_btn, "browse", _(L(" Browse ")) + dots, wxBU_LEFT | wxBU_EXACTFIT);
PrusaButton* btn = m_printhost_browse_btn; PrusaButton* btn = m_printhost_browse_btn;
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -1722,6 +1730,11 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
return sizer; return sizer;
}; };
auto print_host_test = [this](wxWindow* parent) {
auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")),
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap(this, "test"));
auto print_host_test = [this](wxWindow* parent) { auto print_host_test = [this](wxWindow* parent) {
// auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")), // auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")),
// wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); // wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
@ -1765,7 +1778,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) { auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap(this, "zoom.png")); btn->SetBitmap(create_scaled_bitmap(this, "browse"));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -3330,7 +3343,8 @@ void TabSLAMaterial::build()
optgroup = page->new_optgroup(_(L("Corrections"))); optgroup = page->new_optgroup(_(L("Corrections")));
optgroup->label_width = 19;//190; optgroup->label_width = 19;//190;
std::vector<std::string> corrections = {"material_correction"}; std::vector<std::string> corrections = {"material_correction"};
std::vector<std::string> axes{ "X", "Y", "Z" }; // std::vector<std::string> axes{ "X", "Y", "Z" };
std::vector<std::string> axes{ "XY", "Z" };
for (auto& opt_key : corrections) { for (auto& opt_key : corrections) {
auto line = Line{ m_config->def()->get(opt_key)->full_label, "" }; auto line = Line{ m_config->def()->get(opt_key)->full_label, "" };
int id = 0; int id = 0;
@ -3413,7 +3427,7 @@ void TabSLAPrint::build()
optgroup->append_single_option_line("layer_height"); optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("faded_layers"); optgroup->append_single_option_line("faded_layers");
page = add_options_page(_(L("Supports")), "sla_supports"); page = add_options_page(_(L("Supports")), "support"/*"sla_supports"*/);
optgroup = page->new_optgroup(_(L("Supports"))); optgroup = page->new_optgroup(_(L("Supports")));
optgroup->append_single_option_line("supports_enable"); optgroup->append_single_option_line("supports_enable");
@ -3441,7 +3455,7 @@ void TabSLAPrint::build()
optgroup->append_single_option_line("support_points_density_relative"); optgroup->append_single_option_line("support_points_density_relative");
optgroup->append_single_option_line("support_points_minimal_distance"); optgroup->append_single_option_line("support_points_minimal_distance");
page = add_options_page(_(L("Pad")), "brick.png"); page = add_options_page(_(L("Pad")), "pad");
optgroup = page->new_optgroup(_(L("Pad"))); optgroup = page->new_optgroup(_(L("Pad")));
optgroup->append_single_option_line("pad_enable"); optgroup->append_single_option_line("pad_enable");
optgroup->append_single_option_line("pad_wall_thickness"); optgroup->append_single_option_line("pad_wall_thickness");

Some files were not shown because too many files have changed in this diff Show more