Merge branch 'dev' of https://github.com/prusa3d/PrusaSlicer into et_new_camera_movements
3
deps/Boost/Boost.cmake
vendored
@ -28,6 +28,9 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
|||||||
elseif (MSVC_VERSION LESS 1930)
|
elseif (MSVC_VERSION LESS 1930)
|
||||||
# 1920-1929 = VS 16.0 (v142 toolset)
|
# 1920-1929 = VS 16.0 (v142 toolset)
|
||||||
set(_boost_toolset "msvc-14.2")
|
set(_boost_toolset "msvc-14.2")
|
||||||
|
elseif (MSVC_VERSION LESS 1940)
|
||||||
|
# 1930-1939 = VS 17.0 (v143 toolset)
|
||||||
|
set(_boost_toolset "msvc-14.3")
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unsupported MSVC version")
|
message(FATAL_ERROR "Unsupported MSVC version")
|
||||||
endif ()
|
endif ()
|
||||||
|
4
deps/deps-windows.cmake
vendored
@ -15,6 +15,10 @@ elseif (MSVC_VERSION LESS 1930)
|
|||||||
# 1920-1929 = VS 16.0 (v142 toolset)
|
# 1920-1929 = VS 16.0 (v142 toolset)
|
||||||
set(DEP_VS_VER "16")
|
set(DEP_VS_VER "16")
|
||||||
set(DEP_BOOST_TOOLSET "msvc-14.2")
|
set(DEP_BOOST_TOOLSET "msvc-14.2")
|
||||||
|
elseif (MSVC_VERSION LESS 1940)
|
||||||
|
# 1930-1939 = VS 17.0 (v143 toolset)
|
||||||
|
set(DEP_VS_VER "17")
|
||||||
|
set(DEP_BOOST_TOOLSET "msvc-14.3")
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unsupported MSVC version")
|
message(FATAL_ERROR "Unsupported MSVC version")
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#
|
#
|
||||||
# Open preferences (might add item to highlight)
|
# Open preferences (might add item to highlight)
|
||||||
# hypertext_type = preferences
|
# hypertext_type = preferences
|
||||||
# hypertext_preferences_page = 2 (values 0-2 according to prefernces tab to be opened)
|
# hypertext_preferences_page = name of the prefernces tab
|
||||||
# hypertext_preferences_item = show_collapse_button (name of variable saved in prusaslicer.ini connected to the setting in preferences)
|
# hypertext_preferences_item = show_collapse_button (name of variable saved in prusaslicer.ini connected to the setting in preferences)
|
||||||
#
|
#
|
||||||
# Open gallery (no aditional var)
|
# Open gallery (no aditional var)
|
||||||
@ -97,7 +97,7 @@ documentation_link = https://help.prusa3d.com/en/article/reload-from-disk_120427
|
|||||||
[hint:Hiding sidebar]
|
[hint:Hiding sidebar]
|
||||||
text = Hiding sidebar\nDid you know that you can hide the right sidebar using the shortcut <b>Shift+Tab</b>? You can also enable the icon for this from the<a>Preferences</a>.
|
text = Hiding sidebar\nDid you know that you can hide the right sidebar using the shortcut <b>Shift+Tab</b>? You can also enable the icon for this from the<a>Preferences</a>.
|
||||||
hypertext_type = preferences
|
hypertext_type = preferences
|
||||||
hypertext_preferences_page = 2
|
hypertext_preferences_page = GUI
|
||||||
hypertext_preferences_item = show_collapse_button
|
hypertext_preferences_item = show_collapse_button
|
||||||
|
|
||||||
[hint:Perspective camera]
|
[hint:Perspective camera]
|
||||||
@ -214,7 +214,7 @@ disabled_tags = SLA
|
|||||||
[hint:Settings in non-modal window]
|
[hint:Settings in non-modal window]
|
||||||
text = Settings in non-modal window\nDid you know that you can open the Settings in a new non-modal window? This means you can have settings open on one screen and the G-code Preview on the other. Go to the<a>Preferences</a>and select Settings in non-modal window.
|
text = Settings in non-modal window\nDid you know that you can open the Settings in a new non-modal window? This means you can have settings open on one screen and the G-code Preview on the other. Go to the<a>Preferences</a>and select Settings in non-modal window.
|
||||||
hypertext_type = preferences
|
hypertext_type = preferences
|
||||||
hypertext_preferences_page = 2
|
hypertext_preferences_page = GUI
|
||||||
hypertext_preferences_item = dlg_settings_layout_mode
|
hypertext_preferences_item = dlg_settings_layout_mode
|
||||||
|
|
||||||
[hint:Adaptive infills]
|
[hint:Adaptive infills]
|
||||||
|
91
resources/icons/edit_button_pressed.svg
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 348.882 348.882"
|
||||||
|
style="enable-background:new 0 0 348.882 348.882;"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="edit_button - Copy.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs209">
|
||||||
|
|
||||||
|
|
||||||
|
</defs><sodipodi:namedview
|
||||||
|
id="namedview207"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="2.3274346"
|
||||||
|
inkscape:cx="89.583613"
|
||||||
|
inkscape:cy="139.85355"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="3191"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Capa_1" />
|
||||||
|
<path
|
||||||
|
d="m 333.988,11.758 -0.42,-0.383 C 325.538,4.04 315.129,0 304.258,0 292.071,0 280.37,5.159 272.154,14.153 L 116.803,184.231 c -1.416,1.55 -2.49,3.379 -3.154,5.37 l -18.267,54.762 c -2.112,6.331 -1.052,13.333 2.835,18.729 3.918,5.438 10.23,8.685 16.886,8.685 0,0 0.001,0 0.001,0 2.879,0 5.693,-0.592 8.362,-1.76 l 52.89,-23.138 c 1.923,-0.841 3.648,-2.076 5.063,-3.626 L 336.771,73.176 C 352.937,55.479 351.69,27.929 333.988,11.758 Z m -203.607,222.489 10.719,-32.134 0.904,-0.99 20.316,18.556 -0.904,0.99 z M 314.621,52.943 182.553,197.53 162.237,178.974 294.305,34.386 c 2.583,-2.828 6.118,-4.386 9.954,-4.386 3.365,0 6.588,1.252 9.082,3.53 l 0.419,0.383 c 5.484,5.009 5.87,13.546 0.861,19.03 z"
|
||||||
|
id="path170"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1" /><path
|
||||||
|
d="m 303.85,138.388 c -8.284,0 -15,6.716 -15,15 v 127.347 c 0,21.034 -17.113,38.147 -38.147,38.147 H 68.904 c -21.035,0 -38.147,-17.113 -38.147,-38.147 V 100.413 c 0,-21.034 17.113,-38.147 38.147,-38.147 h 131.587 c 8.284,0 15,-6.716 15,-15 0,-8.284 -6.716,-15 -15,-15 H 68.904 c -37.577,0 -68.147,30.571 -68.147,68.147 v 180.321 c 0,37.576 30.571,68.147 68.147,68.147 h 181.798 c 37.576,0 68.147,-30.571 68.147,-68.147 V 153.388 c 0.001,-8.284 -6.715,-15 -14.999,-15 z"
|
||||||
|
id="path172"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1" />
|
||||||
|
<g
|
||||||
|
id="g176">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g178">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g180">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g182">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g184">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g186">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g188">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g190">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g192">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g194">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g196">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g198">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g200">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g202">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g204">
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
157
resources/icons/legend_colorchanges.svg
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 348.882 348.882"
|
||||||
|
style="enable-background:new 0 0 348.882 348.882;"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="legend_colorchange.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs209">
|
||||||
|
|
||||||
|
|
||||||
|
</defs><sodipodi:namedview
|
||||||
|
id="namedview207"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.8228724"
|
||||||
|
inkscape:cx="159.80606"
|
||||||
|
inkscape:cy="209.63153"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Capa_1" />
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="g176">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g178">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g180">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g182">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g184">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g186">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g188">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g190">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g192">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g194">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g196">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g198">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g200">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g202">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g204">
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
style="fill:#da948b;fill-opacity:1"
|
||||||
|
id="rect4805"
|
||||||
|
width="280.72397"
|
||||||
|
height="36.457657"
|
||||||
|
x="34.634773"
|
||||||
|
y="295.91464" /><g
|
||||||
|
id="g5796"
|
||||||
|
transform="matrix(0.5,0,0,0.5,48.819638,25.122266)"><path
|
||||||
|
style="fill:#ffce47"
|
||||||
|
d="m 433.479,205.747 c 75.09,43.351 100.812,139.37 57.461,214.46 -43.351,75.09 -139.37,100.812 -214.46,57.461 -7.304,-4.21 -14.135,-8.93 -20.48,-14.074 l 31.824,-170.903 123.221,-97.645 c 7.632,2.924 15.13,6.491 22.434,10.701 z"
|
||||||
|
id="path4126" /><path
|
||||||
|
style="fill:#ff4181"
|
||||||
|
d="m 78.521,205.747 c -75.09,43.351 -100.812,139.37 -57.461,214.46 43.351,75.09 139.37,100.812 214.46,57.461 7.304,-4.21 14.135,-8.93 20.48,-14.074 L 224.176,292.691 100.955,195.046 c -7.632,2.924 -15.13,6.491 -22.434,10.701 z"
|
||||||
|
id="path4128" /><path
|
||||||
|
style="fill:#4eb9ff"
|
||||||
|
d="m 412.999,170.271 c 0,8.432 -0.667,16.707 -1.953,24.775 L 256,256.196 100.954,195.046 c -1.286,-8.068 -1.953,-16.343 -1.953,-24.775 0,-86.713 70.298,-156.999 156.999,-156.999 86.701,0 156.999,70.285 156.999,156.999 z"
|
||||||
|
id="path4130" /><path
|
||||||
|
style="fill:#ff755c"
|
||||||
|
d="M 312.09,316.957 H 199.91 c -8.7,54.525 12.023,110.943 56.09,146.637 44.066,-35.694 64.789,-92.112 56.09,-146.637 z"
|
||||||
|
id="path4132" /><path
|
||||||
|
style="fill:#85c250"
|
||||||
|
d="m 256,219.797 56.09,97.16 c 51.577,-19.74 90.086,-65.906 98.955,-121.911 C 358.098,174.724 298.865,185 256,219.797 Z"
|
||||||
|
id="path4134" /><path
|
||||||
|
style="fill:#3b8bc0"
|
||||||
|
d="m 100.954,195.046 c 8.869,56.005 47.379,102.171 98.955,121.911 l 56.09,-97.16 C 213.134,185 153.902,174.724 100.954,195.046 Z"
|
||||||
|
id="path4136" /><path
|
||||||
|
style="fill:#174461"
|
||||||
|
d="m 292.981,263.208 c 9.876,17.119 16.173,35.331 19.109,53.748 -17.423,6.661 -36.326,10.313 -56.09,10.313 -19.764,0 -38.667,-3.652 -56.09,-10.313 2.936,-18.418 9.233,-36.629 19.109,-53.749 9.876,-17.107 22.494,-31.667 36.981,-43.411 14.486,11.746 27.105,26.305 36.981,43.412 z"
|
||||||
|
id="path4138" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4126"
|
||||||
|
id="use4251"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4128"
|
||||||
|
id="use4253"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4130"
|
||||||
|
id="use4255"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4132"
|
||||||
|
id="use4257"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4134"
|
||||||
|
id="use4259"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4136"
|
||||||
|
id="use4261"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /><use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path4138"
|
||||||
|
id="use4263"
|
||||||
|
width="100%"
|
||||||
|
height="100%" /></g></svg>
|
After Width: | Height: | Size: 4.2 KiB |
9
resources/icons/legend_customgcodes.svg
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
|
||||||
|
<rect id="rect4805" x="11.7" y="81.8" width="73.6" height="9.56" style="fill: #e2d243"/>
|
||||||
|
<g>
|
||||||
|
<path d="M38.1,25c-5.6,5.6-3.5,15.9,3.9,18.7.8.3.9.5-.7,1.9C26.6,58.2,29.4,62,21.5,51.7c-2.5-3.3,4-4.8,3-7.1a17,17,0,0,1-1.8-4.4c-.1-.4-.2-.5-.7-.5-2.6-.1-6.5,1.1-6.6-2.9a45.7,45.7,0,0,0,0-7.4c-.1-1.8.8-3.5,2.8-3.3s4.3,1,4.8-1.2a14,14,0,0,1,1.6-3.8,1,1,0,0,0-.3-1.4c-1.4-1.6-4.9-3.6-2.5-5.9l6.1-6.1a2.1,2.1,0,0,1,3.3,0c4.8,5.1,2.6,2.3,8.1,1.1,1.4-.3,1.3-.9,1.2-1.9a18.6,18.6,0,0,1-.4-3.4c.6-2.8,3.8-1.9,5.9-2h5.3c1.7,0,2.4.7,2.5,2.5s-.8,3.7,1.8,5,3.5,2.6,4.9.8S63.9,5.5,66,7.6l6.3,6.3c.5.4.4.8-.1,1.2L59,28.3c-.7.7-.9.2-1.2-.3C55,20.8,44.2,18.6,39,24.1" style="fill: #ed6b21"/>
|
||||||
|
<path d="M78.9,18.8c1.7.1,8.5,7.4,10.1,9.2a1.7,1.7,0,0,1,0,2.4c-1.6,1.7-3.4,3.4-5.1,5.1a.7.7,0,0,1-1.1,0L72.5,25.2c-.4-.5-.3-.7.3-1.3s2.8-2.8,4.1-4.1A2.8,2.8,0,0,1,78.9,18.8Z" style="fill: #fff"/>
|
||||||
|
<path d="M45.7,73.7h0c-1.6,1.2-3.5,1.2-5.3,1.7l-5.6,1.3c-2.1.4-2.9.3-3.7-1.4a1.3,1.3,0,0,1-.1-.6c.8-3.6,1.5-7.2,2.4-10.8.5-1.8,2.2-2.7,3.4-4s.6,0,.9.2L47.8,70.3a.8.8,0,0,1,.4.9" style="fill: #fff"/>
|
||||||
|
<path d="M78.2,39.4a1.1,1.1,0,0,1,0,1.5c-7.9,8.5-16.6,16.5-24.7,24.9-.6.6-1,.7-1.6,0l-9.8-9.7a1.2,1.2,0,0,1,0-1.6c8.4-8.3,16.7-16.7,25-25,.4-.4.7-.5,1.2,0C71.5,32.8,74.9,36,78.2,39.4Z" style="fill: #fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
107
resources/icons/legend_deretract.svg
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 348.882 348.882"
|
||||||
|
style="enable-background:new 0 0 348.882 348.882;"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="legend_deretract.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs209">
|
||||||
|
|
||||||
|
|
||||||
|
</defs><sodipodi:namedview
|
||||||
|
id="namedview207"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.6457448"
|
||||||
|
inkscape:cx="174.08531"
|
||||||
|
inkscape:cy="175.30057"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Capa_1" />
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="g176">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g178">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g180">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g182">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g184">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g186">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g188">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g190">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g192">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g194">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g196">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g198">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g200">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g202">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g204">
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="m 168.35743,271.22732 a 7.3770678,7.3770678 0 0 0 2.35439,5.49356 7.5340268,7.5340268 0 0 0 10.98712,0 l 92.13487,-91.82095 a 7.5340268,7.5340268 0 0 0 0,-10.98712 7.5340268,7.5340268 0 0 0 -10.98712,0 l -92.13487,91.82095 a 7.3770678,7.3770678 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3790"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,179.09246 a 7.3770678,7.3770678 0 0 0 2.354394,5.80747 l 92.134868,91.82095 a 7.5340268,7.5340268 0 0 0 10.98712,0 7.5340268,7.5340268 0 0 0 0,-10.98712 L 89.564071,173.59889 a 7.5340268,7.5340268 0 0 0 -10.987119,0 7.3770678,7.3770678 0 0 0 -2.354394,5.49357 z m 92.134872,18.20723 a 8.0049033,8.0049033 0 0 0 2.35439,5.65052 7.8479445,7.8479445 0 0 0 10.98712,0 l 92.13487,-92.29183 a 7.5340268,7.5340268 0 0 0 0,-10.987123 7.5340268,7.5340268 0 0 0 -10.98712,0 l -92.13487,92.134873 a 7.6909855,7.6909855 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3792"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,105.16482 a 7.3770678,7.3770678 0 0 0 2.354394,5.49356 l 92.134868,92.29183 a 7.8479445,7.8479445 0 0 0 10.98712,0 7.8479445,7.8479445 0 0 0 0,-11.14408 L 89.564071,99.671257 a 7.8479445,7.8479445 0 0 0 -13.341513,5.493563 z m 92.134872,18.20723 a 8.0049033,8.0049033 0 0 0 2.35439,5.65052 7.8479445,7.8479445 0 0 0 10.98712,0 l 92.13487,-92.134866 a 7.8479445,7.8479445 0 0 0 0,-11.144082 7.8479445,7.8479445 0 0 0 -10.98712,0 l -92.13487,92.134868 a 7.8479445,7.8479445 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3794"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,31.237177 a 8.0049033,8.0049033 0 0 0 2.354394,5.650527 l 92.134868,92.134866 a 7.8479445,7.8479445 0 0 0 10.98712,0 7.8479445,7.8479445 0 0 0 0,-11.14408 L 89.564071,25.743622 a 7.8479445,7.8479445 0 0 0 -13.341513,5.493555 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3796"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><rect
|
||||||
|
style="fill:#49adcf;fill-opacity:1"
|
||||||
|
id="rect4805"
|
||||||
|
width="280.72397"
|
||||||
|
height="36.457657"
|
||||||
|
x="34.634773"
|
||||||
|
y="295.91464" /></svg>
|
After Width: | Height: | Size: 3.8 KiB |
76
resources/icons/legend_pauseprints.svg
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
id="Layer_1"
|
||||||
|
style="enable-background:new 0 0 96 96;"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 96 96"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="legend_pauseprints.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs7016"><linearGradient
|
||||||
|
id="linearGradient7403"
|
||||||
|
inkscape:swatch="solid"><stop
|
||||||
|
style="stop-color:#000000;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop7401" /></linearGradient></defs><sodipodi:namedview
|
||||||
|
id="namedview7014"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="4.2291667"
|
||||||
|
inkscape:cx="6.2660098"
|
||||||
|
inkscape:cy="41.73399"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Layer_1" /><style
|
||||||
|
type="text/css"
|
||||||
|
id="style6991">
|
||||||
|
.st0{fill:none;stroke:#010000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:10;}
|
||||||
|
.st1{fill:none;stroke:#010000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st2{fill:none;stroke:#010000;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st3{fill:none;stroke:#010000;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st4{fill:#010000;}
|
||||||
|
.st5{fill:none;stroke:#010000;stroke-width:3.8974;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st6{fill:none;stroke:#010000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st7{fill:#010000;stroke:#010000;stroke-width:2;stroke-miterlimit:10;}
|
||||||
|
.st8{opacity:0.75;}
|
||||||
|
.st9{fill:none;stroke:#010000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st10{fill:none;stroke:#010000;stroke-width:6;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st11{fill:none;stroke:#010000;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st12{fill:none;stroke:#010000;stroke-width:3.9497;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st13{fill:none;stroke:#010000;stroke-width:1.9008;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st14{fill:none;stroke:#010000;stroke-width:1.9935;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st15{fill:none;stroke:#010000;stroke-width:4;stroke-miterlimit:10;}
|
||||||
|
.st16{fill:none;stroke:#010000;stroke-width:1.9048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st17{fill:none;stroke:#010000;stroke-width:1.934;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st18{fill:none;stroke:#010000;stroke-width:1.9684;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
.st19{fill:none;stroke:#010000;stroke-width:1.9343;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
</style><rect
|
||||||
|
style="fill:#52f083;fill-opacity:1;stroke-width:0.262144"
|
||||||
|
id="rect4805"
|
||||||
|
width="73.590103"
|
||||||
|
height="9.5571566"
|
||||||
|
x="11.677858"
|
||||||
|
y="81.76329" /><g
|
||||||
|
id="g7865"
|
||||||
|
transform="matrix(0.13421773,0,0,0.13421773,16.48933,9.3957966)"><path
|
||||||
|
d="m 355.507,181.955 c 8.793,-6.139 29.39,-20.519 29.39,-55.351 v -71.77 h 9.814 c 4.49,0 8.17,-3.679 8.17,-8.169 V 8.165 C 402.881,3.675 399.2,0 394.711,0 H 78.351 c -4.495,0 -8.165,3.675 -8.165,8.165 v 38.5 c 0,4.491 3.67,8.169 8.165,8.169 h 9.82 v 73.071 c 0,34.499 10.502,42.576 29.074,53.89 l 80.745,49.203 v 20.984 c -20.346,12.23 -73.465,44.242 -80.434,49.107 -8.793,6.135 -29.384,20.51 -29.384,55.352 v 61.793 h -9.82 c -4.495,0 -8.165,3.676 -8.165,8.166 v 38.498 c 0,4.49 3.67,8.17 8.165,8.17 h 316.361 c 4.49,0 8.17,-3.68 8.17,-8.17 V 426.4 c 0,-4.49 -3.681,-8.166 -8.17,-8.166 h -9.814 V 355.13 c 0,-34.493 -10.508,-42.572 -29.069,-53.885 l -80.745,-49.202 v -20.987 c 20.332,-12.225 73.452,-44.234 80.422,-49.101 z m -102.781,90.904 87.802,53.5 c 6.734,4.109 10.333,6.373 12.001,9.002 1.991,3.164 2.963,9.627 2.963,19.768 v 63.104 H 117.574 V 356.44 c 0,-19.507 9.718,-26.289 16.81,-31.242 5.551,-3.865 54.402,-33.389 85.878,-52.289 4.428,-2.658 7.135,-7.441 7.135,-12.611 v -37.563 c 0,-5.123 -2.671,-9.883 -7.053,-12.55 l -87.54,-53.339 -0.265,-0.165 c -6.741,-4.105 -10.336,-6.369 -11.998,-9.009 -1.992,-3.156 -2.968,-9.626 -2.968,-19.767 v -73.07 h 237.918 v 71.77 c 0,19.5 -9.718,26.288 -16.814,31.235 -5.546,3.872 -54.391,33.395 -85.869,52.295 -4.427,2.658 -7.134,7.442 -7.134,12.601 v 37.563 c 0.001,5.132 2.672,9.889 7.052,12.56 z"
|
||||||
|
id="path7859"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" /><path
|
||||||
|
d="m 331.065,154.234 c 0,0 5.291,-4.619 -2.801,-3.299 -19.178,3.115 -53.079,15.133 -92.079,15.133 -39,0 -57,-11 -82.507,-11.303 -5.569,-0.066 -5.456,3.629 0.937,7.391 6.386,3.758 63.772,35.681 71.671,40.08 7.896,4.389 12.417,4.05 20.786,0 12.174,-5.902 83.993,-48.002 83.993,-48.002 z"
|
||||||
|
id="path7861"
|
||||||
|
style="stroke:#ed6b21;stroke-opacity:1;fill:#ed6b21;fill-opacity:1" /><path
|
||||||
|
d="m 154.311,397.564 c -6.748,6.209 -9.978,10.713 5.536,10.713 12.656,0 139.332,0 155.442,0 16.099,0 9.856,-5.453 2.311,-12.643 -14.576,-13.883 -45.416,-23.566 -82.414,-23.566 -38.754,0 -65.844,11.655 -80.875,25.496 z"
|
||||||
|
id="path7863"
|
||||||
|
style="stroke:#ed6b21;stroke-opacity:1;fill:#ed6b21;fill-opacity:1" /></g></svg>
|
After Width: | Height: | Size: 5.4 KiB |
110
resources/icons/legend_retract.svg
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 348.882 348.882"
|
||||||
|
style="enable-background:new 0 0 348.882 348.882;"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="legend_retract.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs209">
|
||||||
|
|
||||||
|
|
||||||
|
</defs><sodipodi:namedview
|
||||||
|
id="namedview207"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.6457448"
|
||||||
|
inkscape:cx="174.08531"
|
||||||
|
inkscape:cy="175.30057"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Capa_1" />
|
||||||
|
|
||||||
|
<g
|
||||||
|
id="g176">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g178">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g180">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g182">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g184">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g186">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g188">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g190">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g192">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g194">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g196">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g198">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g200">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g202">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g204">
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g5653"
|
||||||
|
transform="matrix(1,0,0,-1,0,302.59856)"
|
||||||
|
style="stroke:#ed6b21;stroke-opacity:1;fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none"><path
|
||||||
|
d="m 168.35743,271.22732 a 7.3770678,7.3770678 0 0 0 2.35439,5.49356 7.5340268,7.5340268 0 0 0 10.98712,0 l 92.13487,-91.82095 a 7.5340268,7.5340268 0 0 0 0,-10.98712 7.5340268,7.5340268 0 0 0 -10.98712,0 l -92.13487,91.82095 a 7.3770678,7.3770678 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3790"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,179.09246 a 7.3770678,7.3770678 0 0 0 2.354394,5.80747 l 92.134868,91.82095 a 7.5340268,7.5340268 0 0 0 10.98712,0 7.5340268,7.5340268 0 0 0 0,-10.98712 L 89.564071,173.59889 a 7.5340268,7.5340268 0 0 0 -10.987119,0 7.3770678,7.3770678 0 0 0 -2.354394,5.49357 z m 92.134872,18.20723 a 8.0049033,8.0049033 0 0 0 2.35439,5.65052 7.8479445,7.8479445 0 0 0 10.98712,0 l 92.13487,-92.29183 a 7.5340268,7.5340268 0 0 0 0,-10.987123 7.5340268,7.5340268 0 0 0 -10.98712,0 l -92.13487,92.134873 a 7.6909855,7.6909855 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3792"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,105.16482 a 7.3770678,7.3770678 0 0 0 2.354394,5.49356 l 92.134868,92.29183 a 7.8479445,7.8479445 0 0 0 10.98712,0 7.8479445,7.8479445 0 0 0 0,-11.14408 L 89.564071,99.671257 a 7.8479445,7.8479445 0 0 0 -13.341513,5.493563 z m 92.134872,18.20723 a 8.0049033,8.0049033 0 0 0 2.35439,5.65052 7.8479445,7.8479445 0 0 0 10.98712,0 l 92.13487,-92.134866 a 7.8479445,7.8479445 0 0 0 0,-11.144082 7.8479445,7.8479445 0 0 0 -10.98712,0 l -92.13487,92.134868 a 7.8479445,7.8479445 0 0 0 -2.35439,5.49356 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3794"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /><path
|
||||||
|
d="m 76.222558,31.237177 a 8.0049033,8.0049033 0 0 0 2.354394,5.650527 l 92.134868,92.134866 a 7.8479445,7.8479445 0 0 0 10.98712,0 7.8479445,7.8479445 0 0 0 0,-11.14408 L 89.564071,25.743622 a 7.8479445,7.8479445 0 0 0 -13.341513,5.493555 z"
|
||||||
|
fill="#333333"
|
||||||
|
id="path3796"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke-width:4;stroke:#ed6b21;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" /></g><rect
|
||||||
|
style="fill:#cd22d6;fill-opacity:1"
|
||||||
|
id="rect4805"
|
||||||
|
width="280.72397"
|
||||||
|
height="36.457657"
|
||||||
|
x="34.634773"
|
||||||
|
y="295.91464" /></svg>
|
After Width: | Height: | Size: 4.0 KiB |
45
resources/icons/legend_seams.svg
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
class="svg-icon"
|
||||||
|
style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;"
|
||||||
|
viewBox="0 0 1024 1024"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1878"
|
||||||
|
sodipodi:docname="legend_seams.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1882" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1880"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.39648438"
|
||||||
|
inkscape:cx="361.93103"
|
||||||
|
inkscape:cy="596.49261"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg1878" />
|
||||||
|
<path
|
||||||
|
d="m 257.84285,390.79005 a 34.420553,34.420553 0 0 0 8.87467,-68.26667 l -60.07467,-15.01866 a 34.133334,34.133334 0 1 0 -17.74933,65.87733 l 60.07466,16.04267 a 26.624,26.624 0 0 0 8.87467,1.36533 z M 389.59752,199.98472 a 34.133334,34.133334 0 0 0 34.13333,25.25866 27.989334,27.989334 0 0 0 8.87467,0 34.133334,34.133334 0 0 0 23.89333,-41.64266 l -16.04267,-60.07467 a 34.133334,34.133334 0 1 0 -65.87733,17.74933 z m 164.864,341.33333 a 34.133334,34.133334 0 0 0 -49.49334,0 L 385.50152,662.83272 a 75.434666,75.434666 0 0 1 -104.448,0 73.386666,73.386666 0 0 1 0,-104.448 L 402.56818,438.91805 a 34.133334,34.133334 0 1 0 -48.128,-48.128 L 231.90152,509.91538 A 142.8846,142.8846 0 1 0 433.97085,711.98472 L 554.46152,591.49405 a 34.133334,34.133334 0 0 0 0,-50.176 z M 272.17885,254.25672 a 34.133334,34.133334 0 0 0 23.89333,9.89866 34.133334,34.133334 0 0 0 24.23467,-9.89866 34.133334,34.133334 0 0 0 0,-48.128 l -44.032,-44.032 a 34.133334,34.133334 0 0 0 -48.128,48.128 z m 548.864,250.19733 -60.07467,-16.04267 a 34.133334,34.133334 0 1 0 -17.06666,65.87734 l 60.07466,16.04266 h 8.87467 a 34.420552,34.420552 0 0 0 8.87467,-68.26666 z m -200.704,173.39733 a 34.133334,34.133334 0 0 0 -41.984,-23.89333 34.133334,34.133334 0 0 0 -23.89333,41.64267 l 16.04266,60.07466 a 34.133334,34.133334 0 0 0 34.13334,25.25867 39.253334,39.253334 0 0 0 8.87466,0 34.133334,34.133334 0 0 0 24.23467,-41.984 z m 117.41867,-53.58933 a 34.133334,34.133334 0 0 0 -48.128,48.128 l 44.032,44.032 a 34.133334,34.133334 0 0 0 48.128,0 34.133334,34.133334 0 0 0 0,-48.128 z m 81.23733,-356.01067 a 141.99467,141.99467 0 0 0 -243.02933,-102.4 L 455.47485,287.36605 a 34.876601,34.876601 0 1 0 49.49333,49.152 L 624.43485,215.00338 a 75.434666,75.434666 0 0 1 104.448,0 73.386666,73.386666 0 0 1 0,104.448 L 607.36818,438.91805 a 34.133334,34.133334 0 0 0 0,48.128 34.133334,34.133334 0 0 0 48.128,0 L 778.03485,367.92072 a 143.01867,143.01867 0 0 0 40.96,-99.66934 z"
|
||||||
|
id="path1876"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:0.8" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e6e6e6;fill-opacity:1;stroke-width:2.86654"
|
||||||
|
id="rect4805"
|
||||||
|
width="804.70764"
|
||||||
|
height="104.50751"
|
||||||
|
x="104.60175"
|
||||||
|
y="855.72644" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
77
resources/icons/legend_shells.svg
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 457.478 457.478"
|
||||||
|
enable-background="new 0 0 457.478 457.478"
|
||||||
|
id="svg24"
|
||||||
|
sodipodi:docname="legend_shell.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs28" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview26"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.88747438"
|
||||||
|
inkscape:cx="-16.3385"
|
||||||
|
inkscape:cy="218.03446"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg24" />
|
||||||
|
<g
|
||||||
|
id="g22"
|
||||||
|
style="fill:#ffffff;fill-opacity:1">
|
||||||
|
<path
|
||||||
|
d="m423.173,110.709l-189.434-109.369c-3.094-1.786-6.906-1.786-10-3.33067e-15l-189.433,109.369c-3.094,1.786-5,5.087-5,8.66v218.739c0,3.573 1.906,6.874 5,8.66l189.434,109.37c1.547,0.893 3.273,1.34 5,1.34s3.453-0.447 5-1.34l189.434-109.37c3.094-1.786 5-5.087 5-8.66v-218.739c-0.001-3.572-1.908-6.874-5.001-8.66zm-15,206.884l-6.459-3.729c-4.781-2.762-10.898-1.123-13.66,3.66-2.762,4.783-1.123,10.899 3.66,13.661l9.226,5.327-162.201,93.647v-188.638c0.128,0.005 0.255,0.024 0.383,0.024 3.456,0 6.817-1.793 8.67-5.001 1.421-2.46 1.669-5.271 0.932-7.799l159.449-92.058v180.906zm-338.747-.069c-2.761-4.782-8.874-6.422-13.66-3.66l-6.46,3.729v-180.905l159.449,92.058c-0.737,2.527-0.488,5.338 0.932,7.798 1.853,3.208 5.213,5.001 8.67,5.001 0.127,0 0.255-0.02 0.383-0.024v188.637l-162.202-93.647 9.227-5.327c4.784-2.761 6.422-8.877 3.661-13.66zm159.314-275.941c5.522,2.84217e-14 10-4.477 10-10v-4.263l159.431,92.048-159.634,92.165c-0.931-4.559-4.964-7.989-9.797-7.989-4.834,0-8.867,3.43-9.798,7.99l-159.635-92.166 159.433-92.048v4.264c0,5.522 4.478,9.999 10,9.999z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m304.003,280.544l17.839,10.3c1.575,0.909 3.294,1.341 4.99,1.341 3.456,0 6.817-1.793 8.67-5.001 2.762-4.783 1.123-10.898-3.66-13.66l-17.839-10.3c-4.784-2.761-10.898-1.123-13.66,3.66s-1.123,10.898 3.66,13.66z"
|
||||||
|
id="path4"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m260.147,255.224l17.84,10.299c1.575,0.91 3.294,1.341 4.99,1.341 3.456,0 6.818-1.793 8.67-5.001 2.762-4.783 1.123-10.899-3.66-13.66l-17.84-10.299c-4.784-2.763-10.899-1.123-13.66,3.66-2.762,4.783-1.123,10.899 3.66,13.66z"
|
||||||
|
id="path6"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m347.857,305.864l17.84,10.3c1.575,0.909 3.294,1.341 4.99,1.341 3.456,0 6.818-1.793 8.67-5.001 2.762-4.783 1.123-10.899-3.66-13.66l-17.84-10.3c-4.784-2.762-10.9-1.123-13.66,3.66-2.762,4.783-1.123,10.899 3.66,13.66z"
|
||||||
|
id="path8"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m174.501,266.865c1.696,0 3.416-0.432 4.99-1.341l17.84-10.3c4.783-2.761 6.422-8.877 3.66-13.66-2.761-4.783-8.877-6.421-13.66-3.66l-17.84,10.3c-4.783,2.761-6.422,8.877-3.66,13.66 1.852,3.209 5.213,5.001 8.67,5.001z"
|
||||||
|
id="path10"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m86.791,317.505c1.696,0 3.415-0.432 4.99-1.341l17.84-10.299c4.783-2.761 6.422-8.877 3.66-13.66-2.76-4.782-8.874-6.421-13.66-3.66l-17.84,10.299c-4.783,2.761-6.422,8.877-3.66,13.66 1.852,3.208 5.213,5.001 8.67,5.001z"
|
||||||
|
id="path12"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m130.646,292.185c1.696,0 3.416-0.432 4.99-1.341l17.839-10.3c4.783-2.762 6.422-8.877 3.66-13.66-2.761-4.783-8.877-6.421-13.66-3.66l-17.839,10.3c-4.783,2.762-6.422,8.877-3.66,13.66 1.853,3.208 5.213,5.001 8.67,5.001z"
|
||||||
|
id="path14"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="M218.74,82.223c0,5.523,4.478,10,10,10s10-4.477,10-10V61.624c0-5.523-4.478-10-10-10s-10,4.477-10,10V82.223z"
|
||||||
|
id="path16"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m228.74,102.264c-5.522,0-10,4.477-10,10v20.599c0,5.523 4.478,10 10,10s10-4.477 10-10v-20.599c0-5.523-4.477-10-10-10z"
|
||||||
|
id="path18"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
d="m228.74,152.904c-5.522,0-10,4.477-10,10v20.599c0,5.523 4.478,10 10,10s10-4.477 10-10v-20.599c0-5.523-4.477-10-10-10z"
|
||||||
|
id="path20"
|
||||||
|
style="fill:#ffffff;fill-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
10
resources/icons/legend_toolchanges.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
|
||||||
|
<rect id="rect4805" x="11.7" y="81.8" width="73.6" height="9.6" style="fill: #c1be63"/>
|
||||||
|
<polyline points="29.9 53.6 34.5 44.8 43.9 44.7 43.9 33.1 38.9 33.1 38.9 6.2 17 6.2 17 33.2 11.6 33.2 11.6 44.7 21 44.7 25.6 53.6" style="fill: #fff"/>
|
||||||
|
<polyline points="68 73.2 73.3 63.3 84 63.2 84 50 78.3 50 78.3 19.7 53.3 19.7 53.3 50.2 47.1 50.2 47.1 63.2 57.9 63.2 63.1 73.2" style="fill: #ed6b21"/>
|
||||||
|
<g>
|
||||||
|
<path d="M32.3,62.6c4.5,5.9,10.4,7.8,18.5,8.4" style="fill: none;stroke: #fff;stroke-miterlimit: 10;stroke-width: 2.8346456692913384px"/>
|
||||||
|
<polygon points="28.9 66.3 28.8 56.4 37.4 61.2 28.9 66.3" style="fill: #fff"/>
|
||||||
|
<polygon points="49.2 75.8 57.9 71.2 49.6 65.9 49.2 75.8" style="fill: #fff"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 844 B |
3
resources/icons/legend_toolmarker.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
|
||||||
|
<polyline points="50.6 92.4 57.8 78.8 72.7 78.7 72.7 60.6 64.7 60.6 64.7 2.2 30.3 2.2 30.3 60.7 21.8 60.7 21.8 78.7 36.6 78.7 43.9 92.4" style="fill: #fff"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 251 B |
163
resources/icons/legend_travel.svg
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="Layer_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
style="enable-background:new 0 0 512 512;"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="legend_travel.svg"
|
||||||
|
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
|
id="defs960" /><sodipodi:namedview
|
||||||
|
id="namedview958"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.5292969"
|
||||||
|
inkscape:cx="256"
|
||||||
|
inkscape:cy="256"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g955" />
|
||||||
|
<g
|
||||||
|
id="g955">
|
||||||
|
<path
|
||||||
|
d="M113.5,451c2.3,0,4.4-1,5.8-2.8c3.2-3.9,76.7-96.1,76.7-139.7c0-45.6-36.9-82.5-82.5-82.5S31,262.9,31,308.5 c0,43.6,73.5,135.8,76.7,139.7C109.1,450,111.2,451,113.5,451z M113.5,241c37.3,0,67.5,30.2,67.5,67.5c0,29.1-44.3,92.7-67.5,122.8 C90.3,401.2,46,337.6,46,308.5C46,271.2,76.2,241,113.5,241z"
|
||||||
|
id="path893"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke:#ed6b21;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M143.5,301c0-16.6-13.4-30-30-30s-30,13.4-30,30s13.4,30,30,30S143.5,317.6,143.5,301z M98.5,301c0-8.3,6.7-15,15-15 s15,6.7,15,15s-6.7,15-15,15S98.5,309.3,98.5,301z"
|
||||||
|
id="path895"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke:#ed6b21;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M421,188.5c2.2,0,4.3-1,5.7-2.6c5.6-6.5,54.3-64,54.3-94.9c0-33.1-26.9-60-60-60s-60,26.9-60,60 c0,30.9,48.8,88.4,54.3,94.9C416.7,187.5,418.8,188.5,421,188.5z M421,46c24.8,0,45,20.2,45,45c0,19-28.6,58.2-45,78.3 c-16.4-20.1-45-59.2-45-78.3C376,66.2,396.2,46,421,46z"
|
||||||
|
id="path897"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke:#ed6b21;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M443.5,83.5c0-12.4-10.1-22.5-22.5-22.5s-22.5,10.1-22.5,22.5S408.6,106,421,106S443.5,95.9,443.5,83.5z M413.5,83.5 c0-4.1,3.4-7.5,7.5-7.5s7.5,3.4,7.5,7.5S425.1,91,421,91S413.5,87.6,413.5,83.5z"
|
||||||
|
id="path899"
|
||||||
|
style="fill:#ed6b21;fill-opacity:1;stroke:#ed6b21;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M413.5,218.5h7.5c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-7.5c-4.1,0-7.5,3.4-7.5,7.5S409.4,218.5,413.5,218.5z"
|
||||||
|
id="path901"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M316,263.5h15.2c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-2,0-3.9,0.8-5.3,2.2s-2.2,3.3-2.2,5.3 C308.5,260.2,311.8,263.5,316,263.5z"
|
||||||
|
id="path903"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M400.1,256c0,4.1,3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3C403.4,248.5,400.1,251.9,400.1,256z"
|
||||||
|
id="path905"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M367.7,218.5h15.3c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5S363.5,218.5,367.7,218.5z"
|
||||||
|
id="path907"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M167.6,466h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S171.8,466,167.6,466z"
|
||||||
|
id="path909"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M294,245.7c0.5,0,1-0.1,1.6-0.2c4.1-0.9,6.6-4.8,5.8-8.9c-0.2-1-0.3-2.1-0.3-3.1c0-2.4,0.6-4.7,1.6-6.8 c1.9-3.7,0.4-8.2-3.3-10.1c-3.7-1.9-8.2-0.4-10.1,3.3c-3.1,6.1-4,13.1-2.6,19.8C287.4,243.1,290.4,245.6,294,245.7z"
|
||||||
|
id="path911"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M361.8,263.5H377c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5S357.6,263.5,361.8,263.5z"
|
||||||
|
id="path913"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M321.8,218.5h15.3c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5S317.7,218.5,321.8,218.5z"
|
||||||
|
id="path915"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M247.7,348.8c0.6,0.2,1.2,0.2,1.8,0.2c3.4,0,6.4-2.4,7.3-5.7c1-3.9,2.8-7.4,5.3-10.5c1.8-2,2.4-4.9,1.4-7.5 c-0.9-2.6-3.1-4.4-5.8-4.9c-2.7-0.5-5.4,0.6-7.1,2.7c-4,4.8-6.9,10.4-8.4,16.5c-0.5,1.9-0.2,4,0.8,5.7 C244.1,347.1,245.8,348.3,247.7,348.8z"
|
||||||
|
id="path917"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M395.9,465.7c-1.6,0.2-3.2,0.3-4.9,0.3h-9.4c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h9.4c2.3,0,4.5-0.1,6.7-0.4 c4.1-0.5,7-4.3,6.5-8.4C403.7,468.1,399.9,465.2,395.9,465.7L395.9,465.7z"
|
||||||
|
id="path919"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M406.3,378.2c-5-1.5-10.1-2.3-15.3-2.2h-2c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h2c3.7,0,7.4,0.5,10.9,1.6 c0.7,0.2,1.4,0.3,2.2,0.3c3.7,0,6.9-2.7,7.4-6.4C412.1,382.9,409.9,379.4,406.3,378.2L406.3,378.2z"
|
||||||
|
id="path921"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M390.3,323.5c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5H375c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5H390.3z"
|
||||||
|
id="path923"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M435.1,440.1c-3.8-1.7-8.2,0-9.9,3.8c-1.7,3.9-4.1,7.4-7.1,10.5c-1.9,1.9-2.7,4.7-1.9,7.3c0.7,2.6,2.8,4.6,5.5,5.3 c2.6,0.6,5.4-0.2,7.3-2.2c4.1-4.3,7.5-9.3,9.9-14.7C440.6,446.3,438.9,441.8,435.1,440.1z"
|
||||||
|
id="path925"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M474.4,287.3c-1.9-0.6-4-0.3-5.7,0.6c-1.7,1-3,2.6-3.6,4.5c-1.1,3.7-3.1,7-5.9,9.7c-3,2.9-3,7.7-0.1,10.6s7.7,3,10.6,0.1 c4.6-4.5,7.9-10,9.7-16.2c0.6-1.9,0.3-4-0.6-5.7C477.9,289.2,476.3,287.9,474.4,287.3z"
|
||||||
|
id="path927"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M465.8,273.5c3,0,5.6-1.7,6.9-4.4c1.2-2.7,0.7-5.9-1.3-8.1c-4.3-4.8-9.7-8.4-15.8-10.4c-3.9-1.3-8.2,0.7-9.5,4.7 s0.7,8.2,4.7,9.5c3.6,1.2,6.9,3.4,9.4,6.3C461.7,272.6,463.7,273.5,465.8,273.5z"
|
||||||
|
id="path929"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M358.5,376h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S362.6,376,358.5,376z"
|
||||||
|
id="path931"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M436.2,308.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S440.3,308.5,436.2,308.5z"
|
||||||
|
id="path933"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M213.5,466h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S217.6,466,213.5,466z"
|
||||||
|
id="path935"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M434.4,399c-2.3-3.4-7-4.3-10.4-2c-3.4,2.3-4.3,7-2,10.4c2.4,3.5,4.2,7.4,5.2,11.5c0.6,2.7,2.6,4.8,5.2,5.6 c2.6,0.8,5.5,0,7.4-1.9c1.9-1.9,2.6-4.8,1.9-7.4C440.3,409.5,437.8,404,434.4,399z"
|
||||||
|
id="path937"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M270.6,373.3c-3.6-1.8-6.7-4.3-9.1-7.5c-2.5-3.3-7.3-3.9-10.5-1.3c-3.3,2.5-3.9,7.3-1.3,10.5c3.8,4.9,8.7,8.9,14.3,11.7 c3.7,1.7,8.1,0.2,9.9-3.5C275.7,379.6,274.3,375.2,270.6,373.3z"
|
||||||
|
id="path939"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M259.3,466H244c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S263.4,466,259.3,466z"
|
||||||
|
id="path941"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M351,466h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5H351c4.1,0,7.5-3.4,7.5-7.5S355.1,466,351,466z"
|
||||||
|
id="path943"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M298.6,323.5c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5H298.6z"
|
||||||
|
id="path945"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M344.5,323.5c4.1,0,7.5-3.4,7.5-7.5s-3.4-7.5-7.5-7.5h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5H344.5z"
|
||||||
|
id="path947"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M312.6,376h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S316.8,376,312.6,376z"
|
||||||
|
id="path949"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M305.2,466h-15.3c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h15.3c4.1,0,7.5-3.4,7.5-7.5S309.3,466,305.2,466z"
|
||||||
|
id="path951"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
d="M121,466h-7.5c-4.1,0-7.5,3.4-7.5,7.5s3.4,7.5,7.5,7.5h7.5c4.1,0,7.5-3.4,7.5-7.5S125.1,466,121,466z"
|
||||||
|
id="path953"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-opacity:1;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 10 KiB |
16
resources/icons/legend_wipe.svg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg enable-background="new 0 0 1000 1000" version="1.1" viewBox="0 0 1e3 1e3" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect id="path6995" width="1e3" height="1e3" style="display:none;stroke:#FFFFFF;stroke-miterlimit:10"/>
|
||||||
|
|
||||||
|
<g transform="translate(1.7416 41.799)">
|
||||||
|
<path id="path6997"
|
||||||
|
d="m969.8 495.7c-10.7 22.2-16.2 30.3-35.8 53-47.1 54.8-64.5 95.5-83.8 195.8-12.6 65.9-21.5 86.8-45.2 103.8-1.8 1.3-4 1.9-6.2 1.9l-172.4-3.4c-6.6-0.1-11.4-6.4-9.7-12.8 21.1-79.3 66.6-153.2 57.1-240.5 0-0.3-0.1-0.6-0.1-0.9l-0.7-66.3c0-0.7-0.1-1.3-0.2-2-16.4-78.2 46.5-267.9-73-265.6-4.2 0.1-8-2.3-9.6-6.1-16.3-37.2-32.6-71.2-82.7-62.5-3.4 0.6-6.8-0.5-9.2-3-34.4-36.2-88.1-55.1-121.6-1.8-1.5 2.5-7.1 4.6-9.9 3.8-121.5-16.5-81.4 135.5-86.4 221.7-0.5 8.5-10.5 12.7-16.9 7.1-51.8-45.3-132.7-6.5-100.3 71.4l0.5 1.3c0.1 0.3 0.3 0.9 0.2 0.9 42.3 94.2 69.4 198.2 143.9 274.4 0.3 0.3 0.7 0.7 1.1 0.9 6.5 5 11.8 10.6 16.1 16.5 17.3 24-0.4 57.4-29.9 56.9l-190.5-3.7c-20.4-0.4-40-8.7-54.3-23.2-9.6-9.7-18.1-20.1-22-27.5-13.5-25.5-18.6-58.7-14.4-92.5 3.2-27.3 9.9-53 26.7-104.2 18.2-55.6 21.2-69.8 21.4-98.9 0-30.2-4-49-20.6-100.3-30.8-93.9-37.9-147.9-25.8-195.6 6.3-24.7 14.4-39.3 31.4-56.3 25.1-24.9 56-37 107-41.5 28.5-2.6 55-1.4 99.9 4.3 36.6 4.7 63.5 4.2 89.2-2 22.2-5.5 27.5-7.5 77.9-32 45.3-22 61.5-27.7 90-31.2 63.7-7.9 129.5 6.3 163.8 35.6 5.1 4.3 17.8 20 28.1 34.4 43.7 61.5 80.7 86.4 149.5 100.7 36.2 7.5 52.8 16.2 76.9 40.5 25.9 26.1 42.1 55 52.4 93.2 14.4 53.8 10 110-11.9 155.7z"
|
||||||
|
style="fill:#FFFFFF" />
|
||||||
|
|
||||||
|
<path id="path6999"
|
||||||
|
d="m233.1 455.1c-87.3-66.3 66.2 239.8 88.3 256.3 31.3 39.1 55.6 123.7 81.2 151.8s123.2 38.4 158.4 6.5 76.5-180 66.4-269.3c-0.4-90.4-5-180.8-1.4-271.3 2.4-33.2-42.1-34-40.7-0.7-0.5 33.3-0.9 66.7-1.5 100-0.3 16.5-9.6 26.6-23.6 26.2-60.5-8.5 17.7-210.7-40-219.9-56.8 10 14.9 211.2-46 218.1-62.2-6.3 18.3-243.8-39.2-255.1-60.1 9.3 16 247.1-47.7 253.9-14-0.4-22.4-11.1-22.2-28.6-8.9-41.8 25.5-179.1-17.6-190.7-47.3 20-11.8 217.8-24.3 275.7-16.5 80.6-69.8-29.1-90.1-52.9z"
|
||||||
|
style="fill:#ED6B21" />
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
@ -155,6 +155,18 @@ namespace ImGui
|
|||||||
const wchar_t ClippyMarker = 0x2602;
|
const wchar_t ClippyMarker = 0x2602;
|
||||||
const wchar_t InfoMarker = 0x2603;
|
const wchar_t InfoMarker = 0x2603;
|
||||||
const wchar_t SliderFloatEditBtnIcon = 0x2604;
|
const wchar_t SliderFloatEditBtnIcon = 0x2604;
|
||||||
|
const wchar_t SliderFloatEditBtnPressedIcon = 0x2605;
|
||||||
|
const wchar_t LegendTravel = 0x2606;
|
||||||
|
const wchar_t LegendWipe = 0x2607;
|
||||||
|
const wchar_t LegendRetract = 0x2608;
|
||||||
|
const wchar_t LegendDeretract = 0x2609;
|
||||||
|
const wchar_t LegendSeams = 0x2610;
|
||||||
|
const wchar_t LegendToolChanges = 0x2611;
|
||||||
|
const wchar_t LegendColorChanges = 0x2612;
|
||||||
|
const wchar_t LegendPausePrints = 0x2613;
|
||||||
|
const wchar_t LegendCustomGCodes = 0x2614;
|
||||||
|
const wchar_t LegendShells = 0x2615;
|
||||||
|
const wchar_t LegendToolMarker = 0x2616;
|
||||||
|
|
||||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ if (TARGET OpenVDB::openvdb)
|
|||||||
set(OpenVDBUtils_SOURCES OpenVDBUtils.cpp OpenVDBUtils.hpp)
|
set(OpenVDBUtils_SOURCES OpenVDBUtils.cpp OpenVDBUtils.hpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(libslic3r STATIC
|
set(SLIC3R_SOURCES
|
||||||
pchheader.cpp
|
pchheader.cpp
|
||||||
pchheader.hpp
|
pchheader.hpp
|
||||||
BoundingBox.cpp
|
BoundingBox.cpp
|
||||||
@ -29,6 +29,8 @@ add_library(libslic3r STATIC
|
|||||||
clipper.hpp
|
clipper.hpp
|
||||||
ClipperUtils.cpp
|
ClipperUtils.cpp
|
||||||
ClipperUtils.hpp
|
ClipperUtils.hpp
|
||||||
|
Color.cpp
|
||||||
|
Color.hpp
|
||||||
Config.cpp
|
Config.cpp
|
||||||
Config.hpp
|
Config.hpp
|
||||||
EdgeGrid.cpp
|
EdgeGrid.cpp
|
||||||
@ -291,6 +293,14 @@ add_library(libslic3r STATIC
|
|||||||
SLA/ReprojectPointsOnMesh.hpp
|
SLA/ReprojectPointsOnMesh.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_library(libslic3r STATIC ${SLIC3R_SOURCES})
|
||||||
|
|
||||||
|
foreach(_source IN ITEMS ${SLIC3R_SOURCES})
|
||||||
|
get_filename_component(_source_path "${_source}" PATH)
|
||||||
|
string(REPLACE "/" "\\" _group_path "${_source_path}")
|
||||||
|
source_group("${_group_path}" FILES "${_source}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
if (SLIC3R_STATIC)
|
if (SLIC3R_STATIC)
|
||||||
set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
|
set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
|
||||||
endif ()
|
endif ()
|
||||||
|
400
src/libslic3r/Color.cpp
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
#include "libslic3r.h"
|
||||||
|
#include "Color.hpp"
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
static const float INV_255 = 1.0f / 255.0f;
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// Conversion from RGB to HSV color space
|
||||||
|
// The input RGB values are in the range [0, 1]
|
||||||
|
// The output HSV values are in the ranges h = [0, 360], and s, v = [0, 1]
|
||||||
|
static void RGBtoHSV(float r, float g, float b, float& h, float& s, float& v)
|
||||||
|
{
|
||||||
|
assert(0.0f <= r && r <= 1.0f);
|
||||||
|
assert(0.0f <= g && g <= 1.0f);
|
||||||
|
assert(0.0f <= b && b <= 1.0f);
|
||||||
|
|
||||||
|
const float max_comp = std::max(std::max(r, g), b);
|
||||||
|
const float min_comp = std::min(std::min(r, g), b);
|
||||||
|
const float delta = max_comp - min_comp;
|
||||||
|
|
||||||
|
if (delta > 0.0f) {
|
||||||
|
if (max_comp == r)
|
||||||
|
h = 60.0f * (std::fmod(((g - b) / delta), 6.0f));
|
||||||
|
else if (max_comp == g)
|
||||||
|
h = 60.0f * (((b - r) / delta) + 2.0f);
|
||||||
|
else if (max_comp == b)
|
||||||
|
h = 60.0f * (((r - g) / delta) + 4.0f);
|
||||||
|
|
||||||
|
s = (max_comp > 0.0f) ? delta / max_comp : 0.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
h = 0.0f;
|
||||||
|
s = 0.0f;
|
||||||
|
}
|
||||||
|
v = max_comp;
|
||||||
|
|
||||||
|
while (h < 0.0f) { h += 360.0f; }
|
||||||
|
while (h > 360.0f) { h -= 360.0f; }
|
||||||
|
|
||||||
|
assert(0.0f <= s && s <= 1.0f);
|
||||||
|
assert(0.0f <= v && v <= 1.0f);
|
||||||
|
assert(0.0f <= h && h <= 360.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversion from HSV to RGB color space
|
||||||
|
// The input HSV values are in the ranges h = [0, 360], and s, v = [0, 1]
|
||||||
|
// The output RGB values are in the range [0, 1]
|
||||||
|
static void HSVtoRGB(float h, float s, float v, float& r, float& g, float& b)
|
||||||
|
{
|
||||||
|
assert(0.0f <= s && s <= 1.0f);
|
||||||
|
assert(0.0f <= v && v <= 1.0f);
|
||||||
|
assert(0.0f <= h && h <= 360.0f);
|
||||||
|
|
||||||
|
const float chroma = v * s;
|
||||||
|
const float h_prime = std::fmod(h / 60.0f, 6.0f);
|
||||||
|
const float x = chroma * (1.0f - std::abs(std::fmod(h_prime, 2.0f) - 1.0f));
|
||||||
|
const float m = v - chroma;
|
||||||
|
|
||||||
|
if (0.0f <= h_prime && h_prime < 1.0f) {
|
||||||
|
r = chroma;
|
||||||
|
g = x;
|
||||||
|
b = 0.0f;
|
||||||
|
}
|
||||||
|
else if (1.0f <= h_prime && h_prime < 2.0f) {
|
||||||
|
r = x;
|
||||||
|
g = chroma;
|
||||||
|
b = 0.0f;
|
||||||
|
}
|
||||||
|
else if (2.0f <= h_prime && h_prime < 3.0f) {
|
||||||
|
r = 0.0f;
|
||||||
|
g = chroma;
|
||||||
|
b = x;
|
||||||
|
}
|
||||||
|
else if (3.0f <= h_prime && h_prime < 4.0f) {
|
||||||
|
r = 0.0f;
|
||||||
|
g = x;
|
||||||
|
b = chroma;
|
||||||
|
}
|
||||||
|
else if (4.0f <= h_prime && h_prime < 5.0f) {
|
||||||
|
r = x;
|
||||||
|
g = 0.0f;
|
||||||
|
b = chroma;
|
||||||
|
}
|
||||||
|
else if (5.0f <= h_prime && h_prime < 6.0f) {
|
||||||
|
r = chroma;
|
||||||
|
g = 0.0f;
|
||||||
|
b = x;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = 0.0f;
|
||||||
|
g = 0.0f;
|
||||||
|
b = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
r += m;
|
||||||
|
g += m;
|
||||||
|
b += m;
|
||||||
|
|
||||||
|
assert(0.0f <= r && r <= 1.0f);
|
||||||
|
assert(0.0f <= g && g <= 1.0f);
|
||||||
|
assert(0.0f <= b && b <= 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Randomizer
|
||||||
|
{
|
||||||
|
std::random_device m_rd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
float random_float(float min, float max) {
|
||||||
|
std::mt19937 rand_generator(m_rd());
|
||||||
|
std::uniform_real_distribution<float> distrib(min, max);
|
||||||
|
return distrib(rand_generator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorRGB::ColorRGB(float r, float g, float b)
|
||||||
|
: m_data({ std::clamp(r, 0.0f, 1.0f), std::clamp(g, 0.0f, 1.0f), std::clamp(b, 0.0f, 1.0f) })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB::ColorRGB(unsigned char r, unsigned char g, unsigned char b)
|
||||||
|
: m_data({ std::clamp(r * INV_255, 0.0f, 1.0f), std::clamp(g * INV_255, 0.0f, 1.0f), std::clamp(b * INV_255, 0.0f, 1.0f) })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorRGB::operator < (const ColorRGB& other) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
if (m_data[i] < other.m_data[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorRGB::operator > (const ColorRGB& other) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
if (m_data[i] > other.m_data[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB ColorRGB::operator + (const ColorRGB& other) const
|
||||||
|
{
|
||||||
|
ColorRGB ret;
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
ret.m_data[i] = std::clamp(m_data[i] + other.m_data[i], 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB ColorRGB::operator * (float value) const
|
||||||
|
{
|
||||||
|
assert(value >= 0.0f);
|
||||||
|
ColorRGB ret;
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
ret.m_data[i] = std::clamp(value * m_data[i], 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA::ColorRGBA(float r, float g, float b, float a)
|
||||||
|
: m_data({ std::clamp(r, 0.0f, 1.0f), std::clamp(g, 0.0f, 1.0f), std::clamp(b, 0.0f, 1.0f), std::clamp(a, 0.0f, 1.0f) })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA::ColorRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||||
|
: m_data({ std::clamp(r * INV_255, 0.0f, 1.0f), std::clamp(g * INV_255, 0.0f, 1.0f), std::clamp(b * INV_255, 0.0f, 1.0f), std::clamp(a * INV_255, 0.0f, 1.0f) })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorRGBA::operator < (const ColorRGBA& other) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
if (m_data[i] < other.m_data[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorRGBA::operator > (const ColorRGBA& other) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
if (m_data[i] > other.m_data[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA ColorRGBA::operator + (const ColorRGBA& other) const
|
||||||
|
{
|
||||||
|
ColorRGBA ret;
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
ret.m_data[i] = std::clamp(m_data[i] + other.m_data[i], 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA ColorRGBA::operator * (float value) const
|
||||||
|
{
|
||||||
|
assert(value >= 0.0f);
|
||||||
|
ColorRGBA ret;
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
ret.m_data[i] = std::clamp(value * m_data[i], 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
ret.m_data[3] = this->m_data[3];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB operator * (float value, const ColorRGB& other) { return other * value; }
|
||||||
|
ColorRGBA operator * (float value, const ColorRGBA& other) { return other * value; }
|
||||||
|
|
||||||
|
ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t)
|
||||||
|
{
|
||||||
|
assert(0.0f <= t && t <= 1.0f);
|
||||||
|
return (1.0f - t) * a + t * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t)
|
||||||
|
{
|
||||||
|
assert(0.0f <= t && t <= 1.0f);
|
||||||
|
return (1.0f - t) * a + t * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB complementary(const ColorRGB& color)
|
||||||
|
{
|
||||||
|
return { 1.0f - color.r(), 1.0f - color.g(), 1.0f - color.b() };
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA complementary(const ColorRGBA& color)
|
||||||
|
{
|
||||||
|
return { 1.0f - color.r(), 1.0f - color.g(), 1.0f - color.b(), color.a() };
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB saturate(const ColorRGB& color, float factor)
|
||||||
|
{
|
||||||
|
float h, s, v;
|
||||||
|
RGBtoHSV(color.r(), color.g(), color.b(), h, s, v);
|
||||||
|
s = std::clamp(s * factor, 0.0f, 1.0f);
|
||||||
|
float r, g, b;
|
||||||
|
HSVtoRGB(h, s, v, r, g, b);
|
||||||
|
return { r, g, b };
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA saturate(const ColorRGBA& color, float factor)
|
||||||
|
{
|
||||||
|
return to_rgba(saturate(to_rgb(color), factor), color.a());
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB opposite(const ColorRGB& color)
|
||||||
|
{
|
||||||
|
float h, s, v;
|
||||||
|
RGBtoHSV(color.r(), color.g(), color.b(), h, s, v);
|
||||||
|
|
||||||
|
h += 65.0f; // 65 instead 60 to avoid circle values
|
||||||
|
if (h > 360.0f)
|
||||||
|
h -= 360.0f;
|
||||||
|
|
||||||
|
Randomizer rnd;
|
||||||
|
s = rnd.random_float(0.65f, 1.0f);
|
||||||
|
v = rnd.random_float(0.65f, 1.0f);
|
||||||
|
|
||||||
|
float r, g, b;
|
||||||
|
HSVtoRGB(h, s, v, r, g, b);
|
||||||
|
return { r, g, b };
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGB opposite(const ColorRGB& a, const ColorRGB& b)
|
||||||
|
{
|
||||||
|
float ha, sa, va;
|
||||||
|
RGBtoHSV(a.r(), a.g(), a.b(), ha, sa, va);
|
||||||
|
float hb, sb, vb;
|
||||||
|
RGBtoHSV(b.r(), b.g(), b.b(), hb, sb, vb);
|
||||||
|
|
||||||
|
float delta_h = std::abs(ha - hb);
|
||||||
|
float start_h = (delta_h > 180.0f) ? std::min(ha, hb) : std::max(ha, hb);
|
||||||
|
|
||||||
|
start_h += 5.0f; // to avoid circle change of colors for 120 deg
|
||||||
|
if (delta_h < 180.0f)
|
||||||
|
delta_h = 360.0f - delta_h;
|
||||||
|
|
||||||
|
Randomizer rnd;
|
||||||
|
float out_h = start_h + 0.5f * delta_h;
|
||||||
|
if (out_h > 360.0f)
|
||||||
|
out_h -= 360.0f;
|
||||||
|
float out_s = rnd.random_float(0.65f, 1.0f);
|
||||||
|
float out_v = rnd.random_float(0.65f, 1.0f);
|
||||||
|
|
||||||
|
float out_r, out_g, out_b;
|
||||||
|
HSVtoRGB(out_h, out_s, out_v, out_r, out_g, out_b);
|
||||||
|
return { out_r, out_g, out_b };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool can_decode_color(const std::string& color) { return color.size() == 7 && color.front() == '#'; }
|
||||||
|
|
||||||
|
bool decode_color(const std::string& color_in, ColorRGB& color_out)
|
||||||
|
{
|
||||||
|
auto hex_digit_to_int = [](const char c) {
|
||||||
|
return
|
||||||
|
(c >= '0' && c <= '9') ? int(c - '0') :
|
||||||
|
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
|
||||||
|
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
color_out = ColorRGB::BLACK();
|
||||||
|
if (can_decode_color(color_in)) {
|
||||||
|
const char* c = color_in.data() + 1;
|
||||||
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
|
const int digit1 = hex_digit_to_int(*c++);
|
||||||
|
const int digit2 = hex_digit_to_int(*c++);
|
||||||
|
if (digit1 != -1 && digit2 != -1)
|
||||||
|
color_out.set(i, float(digit1 * 16 + digit2) * INV_255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert(0.0f <= color_out.r() && color_out.r() <= 1.0f);
|
||||||
|
assert(0.0f <= color_out.g() && color_out.g() <= 1.0f);
|
||||||
|
assert(0.0f <= color_out.b() && color_out.b() <= 1.0f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool decode_color(const std::string& color_in, ColorRGBA& color_out)
|
||||||
|
{
|
||||||
|
ColorRGB rgb;
|
||||||
|
if (!decode_color(color_in, rgb))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
color_out = to_rgba(rgb, color_out.a());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out)
|
||||||
|
{
|
||||||
|
colors_out = std::vector<ColorRGB>(colors_in.size(), ColorRGB::BLACK());
|
||||||
|
for (size_t i = 0; i < colors_in.size(); ++i) {
|
||||||
|
if (!decode_color(colors_in[i], colors_out[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out)
|
||||||
|
{
|
||||||
|
colors_out = std::vector<ColorRGBA>(colors_in.size(), ColorRGBA::BLACK());
|
||||||
|
for (size_t i = 0; i < colors_in.size(); ++i) {
|
||||||
|
if (!decode_color(colors_in[i], colors_out[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string encode_color(const ColorRGB& color)
|
||||||
|
{
|
||||||
|
char buffer[64];
|
||||||
|
::sprintf(buffer, "#%02X%02X%02X", color.r_uchar(), color.g_uchar(), color.b_uchar());
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string encode_color(const ColorRGBA& color) { return encode_color(to_rgb(color)); }
|
||||||
|
|
||||||
|
ColorRGB to_rgb(const ColorRGBA& other_rgba) { return { other_rgba.r(), other_rgba.g(), other_rgba.b() }; }
|
||||||
|
ColorRGBA to_rgba(const ColorRGB& other_rgb) { return { other_rgb.r(), other_rgb.g(), other_rgb.b(), 1.0f }; }
|
||||||
|
ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha) { return { other_rgb.r(), other_rgb.g(), other_rgb.b(), alpha }; }
|
||||||
|
|
||||||
|
ColorRGBA picking_decode(unsigned int id)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
float((id >> 0) & 0xff) * INV_255, // red
|
||||||
|
float((id >> 8) & 0xff) * INV_255, // green
|
||||||
|
float((id >> 16) & 0xff) * INV_255, // blue
|
||||||
|
float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff)) * INV_255 // checksum for validating against unwanted alpha blending and multi sampling
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b) { return r + (g << 8) + (b << 16); }
|
||||||
|
|
||||||
|
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue)
|
||||||
|
{
|
||||||
|
// 8 bit hash for the color
|
||||||
|
unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff;
|
||||||
|
// Increase enthropy by a bit reversal
|
||||||
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
|
// Flip every second bit to increase the enthropy even more.
|
||||||
|
b ^= 0x55;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
170
src/libslic3r/Color.hpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#ifndef slic3r_Color_hpp_
|
||||||
|
#define slic3r_Color_hpp_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class ColorRGB
|
||||||
|
{
|
||||||
|
std::array<float, 3> m_data{1.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ColorRGB() = default;
|
||||||
|
ColorRGB(float r, float g, float b);
|
||||||
|
ColorRGB(unsigned char r, unsigned char g, unsigned char b);
|
||||||
|
ColorRGB(const ColorRGB& other) = default;
|
||||||
|
|
||||||
|
ColorRGB& operator = (const ColorRGB& other) { m_data = other.m_data; return *this; }
|
||||||
|
|
||||||
|
bool operator == (const ColorRGB& other) const { return m_data == other.m_data; }
|
||||||
|
bool operator != (const ColorRGB& other) const { return !operator==(other); }
|
||||||
|
bool operator < (const ColorRGB& other) const;
|
||||||
|
bool operator > (const ColorRGB& other) const;
|
||||||
|
|
||||||
|
ColorRGB operator + (const ColorRGB& other) const;
|
||||||
|
ColorRGB operator * (float value) const;
|
||||||
|
|
||||||
|
const float* const data() const { return m_data.data(); }
|
||||||
|
|
||||||
|
float r() const { return m_data[0]; }
|
||||||
|
float g() const { return m_data[1]; }
|
||||||
|
float b() const { return m_data[2]; }
|
||||||
|
|
||||||
|
void r(float r) { m_data[0] = std::clamp(r, 0.0f, 1.0f); }
|
||||||
|
void g(float g) { m_data[1] = std::clamp(g, 0.0f, 1.0f); }
|
||||||
|
void b(float b) { m_data[2] = std::clamp(b, 0.0f, 1.0f); }
|
||||||
|
|
||||||
|
void set(unsigned int comp, float value) {
|
||||||
|
assert(0 <= comp && comp <= 2);
|
||||||
|
m_data[comp] = std::clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char r_uchar() const { return static_cast<unsigned char>(m_data[0] * 255.0f); }
|
||||||
|
unsigned char g_uchar() const { return static_cast<unsigned char>(m_data[1] * 255.0f); }
|
||||||
|
unsigned char b_uchar() const { return static_cast<unsigned char>(m_data[2] * 255.0f); }
|
||||||
|
|
||||||
|
static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; }
|
||||||
|
static const ColorRGB BLUE() { return { 0.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGB BLUEISH() { return { 0.5f, 0.5f, 1.0f }; }
|
||||||
|
static const ColorRGB DARK_GRAY() { return { 0.25f, 0.25f, 0.25f }; }
|
||||||
|
static const ColorRGB DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f }; }
|
||||||
|
static const ColorRGB GRAY() { return { 0.5f, 0.5f, 0.5f }; }
|
||||||
|
static const ColorRGB GREEN() { return { 0.0f, 1.0f, 0.0f }; }
|
||||||
|
static const ColorRGB GREENISH() { return { 0.5f, 1.0f, 0.5f }; }
|
||||||
|
static const ColorRGB LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f }; }
|
||||||
|
static const ColorRGB ORANGE() { return { 0.92f, 0.50f, 0.26f }; }
|
||||||
|
static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; }
|
||||||
|
static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; }
|
||||||
|
static const ColorRGB YELLOW() { return { 1.0f, 1.0f, 0.0f }; }
|
||||||
|
static const ColorRGB WHITE() { return { 1.0f, 1.0f, 1.0f }; }
|
||||||
|
|
||||||
|
static const ColorRGB X() { return { 0.75f, 0.0f, 0.0f }; }
|
||||||
|
static const ColorRGB Y() { return { 0.0f, 0.75f, 0.0f }; }
|
||||||
|
static const ColorRGB Z() { return { 0.0f, 0.0f, 0.75f }; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ColorRGBA
|
||||||
|
{
|
||||||
|
std::array<float, 4> m_data{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
public:
|
||||||
|
ColorRGBA() = default;
|
||||||
|
ColorRGBA(float r, float g, float b, float a);
|
||||||
|
ColorRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
||||||
|
ColorRGBA(const ColorRGBA& other) = default;
|
||||||
|
|
||||||
|
ColorRGBA& operator = (const ColorRGBA& other) { m_data = other.m_data; return *this; }
|
||||||
|
|
||||||
|
bool operator == (const ColorRGBA& other) const { return m_data == other.m_data; }
|
||||||
|
bool operator != (const ColorRGBA& other) const { return !operator==(other); }
|
||||||
|
bool operator < (const ColorRGBA& other) const;
|
||||||
|
bool operator > (const ColorRGBA& other) const;
|
||||||
|
|
||||||
|
ColorRGBA operator + (const ColorRGBA& other) const;
|
||||||
|
ColorRGBA operator * (float value) const;
|
||||||
|
|
||||||
|
const float* const data() const { return m_data.data(); }
|
||||||
|
|
||||||
|
float r() const { return m_data[0]; }
|
||||||
|
float g() const { return m_data[1]; }
|
||||||
|
float b() const { return m_data[2]; }
|
||||||
|
float a() const { return m_data[3]; }
|
||||||
|
|
||||||
|
void r(float r) { m_data[0] = std::clamp(r, 0.0f, 1.0f); }
|
||||||
|
void g(float g) { m_data[1] = std::clamp(g, 0.0f, 1.0f); }
|
||||||
|
void b(float b) { m_data[2] = std::clamp(b, 0.0f, 1.0f); }
|
||||||
|
void a(float a) { m_data[3] = std::clamp(a, 0.0f, 1.0f); }
|
||||||
|
|
||||||
|
void set(unsigned int comp, float value) {
|
||||||
|
assert(0 <= comp && comp <= 3);
|
||||||
|
m_data[comp] = std::clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char r_uchar() const { return static_cast<unsigned char>(m_data[0] * 255.0f); }
|
||||||
|
unsigned char g_uchar() const { return static_cast<unsigned char>(m_data[1] * 255.0f); }
|
||||||
|
unsigned char b_uchar() const { return static_cast<unsigned char>(m_data[2] * 255.0f); }
|
||||||
|
unsigned char a_uchar() const { return static_cast<unsigned char>(m_data[3] * 255.0f); }
|
||||||
|
|
||||||
|
bool is_transparent() const { return m_data[3] < 1.0f; }
|
||||||
|
|
||||||
|
static const ColorRGBA BLACK() { return { 0.0f, 0.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA BLUE() { return { 0.0f, 0.0f, 1.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA BLUEISH() { return { 0.5f, 0.5f, 1.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA DARK_GRAY() { return { 0.25f, 0.25f, 0.25f, 1.0f }; }
|
||||||
|
static const ColorRGBA DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA GRAY() { return { 0.5f, 0.5f, 0.5f, 1.0f }; }
|
||||||
|
static const ColorRGBA GREEN() { return { 0.0f, 1.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA GREENISH() { return { 0.5f, 1.0f, 0.5f, 1.0f }; }
|
||||||
|
static const ColorRGBA LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f, 1.0f }; }
|
||||||
|
static const ColorRGBA ORANGE() { return { 0.923f, 0.504f, 0.264f, 1.0f }; }
|
||||||
|
static const ColorRGBA RED() { return { 1.0f, 0.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA REDISH() { return { 1.0f, 0.5f, 0.5f, 1.0f }; }
|
||||||
|
static const ColorRGBA YELLOW() { return { 1.0f, 1.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA WHITE() { return { 1.0f, 1.0f, 1.0f, 1.0f }; }
|
||||||
|
|
||||||
|
static const ColorRGBA X() { return { 0.75f, 0.0f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA Y() { return { 0.0f, 0.75f, 0.0f, 1.0f }; }
|
||||||
|
static const ColorRGBA Z() { return { 0.0f, 0.0f, 0.75f, 1.0f }; }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ColorRGB operator * (float value, const ColorRGB& other);
|
||||||
|
extern ColorRGBA operator * (float value, const ColorRGBA& other);
|
||||||
|
|
||||||
|
extern ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t);
|
||||||
|
extern ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t);
|
||||||
|
|
||||||
|
extern ColorRGB complementary(const ColorRGB& color);
|
||||||
|
extern ColorRGBA complementary(const ColorRGBA& color);
|
||||||
|
|
||||||
|
extern ColorRGB saturate(const ColorRGB& color, float factor);
|
||||||
|
extern ColorRGBA saturate(const ColorRGBA& color, float factor);
|
||||||
|
|
||||||
|
extern ColorRGB opposite(const ColorRGB& color);
|
||||||
|
extern ColorRGB opposite(const ColorRGB& a, const ColorRGB& b);
|
||||||
|
|
||||||
|
extern bool can_decode_color(const std::string& color);
|
||||||
|
|
||||||
|
extern bool decode_color(const std::string& color_in, ColorRGB& color_out);
|
||||||
|
extern bool decode_color(const std::string& color_in, ColorRGBA& color_out);
|
||||||
|
|
||||||
|
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out);
|
||||||
|
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out);
|
||||||
|
|
||||||
|
extern std::string encode_color(const ColorRGB& color);
|
||||||
|
extern std::string encode_color(const ColorRGBA& color);
|
||||||
|
|
||||||
|
extern ColorRGB to_rgb(const ColorRGBA& other_rgba);
|
||||||
|
extern ColorRGBA to_rgba(const ColorRGB& other_rgb);
|
||||||
|
extern ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha);
|
||||||
|
|
||||||
|
extern ColorRGBA picking_decode(unsigned int id);
|
||||||
|
extern unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b);
|
||||||
|
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
|
||||||
|
// were not interpolated by alpha blending or multi sampling.
|
||||||
|
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif /* slic3r_Color_hpp_ */
|
@ -189,6 +189,9 @@ void GCodeProcessor::TimeMachine::reset()
|
|||||||
max_travel_acceleration = 0.0f;
|
max_travel_acceleration = 0.0f;
|
||||||
extrude_factor_override_percentage = 1.0f;
|
extrude_factor_override_percentage = 1.0f;
|
||||||
time = 0.0f;
|
time = 0.0f;
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
travel_time = 0.0f;
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
stop_times = std::vector<StopTime>();
|
stop_times = std::vector<StopTime>();
|
||||||
curr.reset();
|
curr.reset();
|
||||||
prev.reset();
|
prev.reset();
|
||||||
@ -304,9 +307,17 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa
|
|||||||
block_time += additional_time;
|
block_time += additional_time;
|
||||||
|
|
||||||
time += block_time;
|
time += block_time;
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
if (block.move_type == EMoveType::Travel)
|
||||||
|
travel_time += block_time;
|
||||||
|
else
|
||||||
|
roles_time[static_cast<size_t>(block.role)] += block_time;
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
gcode_time.cache += block_time;
|
gcode_time.cache += block_time;
|
||||||
moves_time[static_cast<size_t>(block.move_type)] += block_time;
|
moves_time[static_cast<size_t>(block.move_type)] += block_time;
|
||||||
|
#if !ENABLE_TRAVEL_TIME
|
||||||
roles_time[static_cast<size_t>(block.role)] += block_time;
|
roles_time[static_cast<size_t>(block.role)] += block_time;
|
||||||
|
#endif // !ENABLE_TRAVEL_TIME
|
||||||
if (block.layer_id >= layers_time.size()) {
|
if (block.layer_id >= layers_time.size()) {
|
||||||
const size_t curr_size = layers_time.size();
|
const size_t curr_size = layers_time.size();
|
||||||
layers_time.resize(block.layer_id);
|
layers_time.resize(block.layer_id);
|
||||||
@ -1363,6 +1374,18 @@ std::string GCodeProcessor::get_time_dhm(PrintEstimatedStatistics::ETimeMode mod
|
|||||||
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].time)) : std::string("N/A");
|
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].time)) : std::string("N/A");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
float GCodeProcessor::get_travel_time(PrintEstimatedStatistics::ETimeMode mode) const
|
||||||
|
{
|
||||||
|
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast<size_t>(mode)].travel_time : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GCodeProcessor::get_travel_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const
|
||||||
|
{
|
||||||
|
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].travel_time)) : std::string("N/A");
|
||||||
|
}
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
|
|
||||||
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const
|
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const
|
||||||
{
|
{
|
||||||
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret;
|
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret;
|
||||||
@ -3372,6 +3395,9 @@ void GCodeProcessor::update_estimated_times_stats()
|
|||||||
auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) {
|
auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) {
|
||||||
PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast<size_t>(mode)];
|
PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast<size_t>(mode)];
|
||||||
data.time = get_time(mode);
|
data.time = get_time(mode);
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
data.travel_time = get_travel_time(mode);
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
data.custom_gcode_times = get_custom_gcode_times(mode, true);
|
data.custom_gcode_times = get_custom_gcode_times(mode, true);
|
||||||
data.moves_times = get_moves_time(mode);
|
data.moves_times = get_moves_time(mode);
|
||||||
data.roles_times = get_roles_time(mode);
|
data.roles_times = get_roles_time(mode);
|
||||||
|
@ -44,6 +44,9 @@ namespace Slic3r {
|
|||||||
struct Mode
|
struct Mode
|
||||||
{
|
{
|
||||||
float time;
|
float time;
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
float travel_time;
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> custom_gcode_times;
|
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> custom_gcode_times;
|
||||||
std::vector<std::pair<EMoveType, float>> moves_times;
|
std::vector<std::pair<EMoveType, float>> moves_times;
|
||||||
std::vector<std::pair<ExtrusionRole, float>> roles_times;
|
std::vector<std::pair<ExtrusionRole, float>> roles_times;
|
||||||
@ -51,6 +54,9 @@ namespace Slic3r {
|
|||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
time = 0.0f;
|
time = 0.0f;
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
travel_time = 0.0f;
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
custom_gcode_times.clear();
|
custom_gcode_times.clear();
|
||||||
moves_times.clear();
|
moves_times.clear();
|
||||||
roles_times.clear();
|
roles_times.clear();
|
||||||
@ -290,6 +296,9 @@ namespace Slic3r {
|
|||||||
float max_travel_acceleration; // mm/s^2
|
float max_travel_acceleration; // mm/s^2
|
||||||
float extrude_factor_override_percentage;
|
float extrude_factor_override_percentage;
|
||||||
float time; // s
|
float time; // s
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
float travel_time; // s
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
struct StopTime
|
struct StopTime
|
||||||
{
|
{
|
||||||
unsigned int g1_line_id;
|
unsigned int g1_line_id;
|
||||||
@ -596,6 +605,10 @@ namespace Slic3r {
|
|||||||
|
|
||||||
float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
|
std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
|
#if ENABLE_TRAVEL_TIME
|
||||||
|
float get_travel_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
|
std::string get_travel_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
|
#endif // ENABLE_TRAVEL_TIME
|
||||||
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const;
|
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const;
|
||||||
|
|
||||||
std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||||
|
@ -116,6 +116,8 @@ public:
|
|||||||
// This type is here to support PresetConfigSubstitutions for physical printers, however it does not belong to the Preset class,
|
// This type is here to support PresetConfigSubstitutions for physical printers, however it does not belong to the Preset class,
|
||||||
// PhysicalPrinter class is used instead.
|
// PhysicalPrinter class is used instead.
|
||||||
TYPE_PHYSICAL_PRINTER,
|
TYPE_PHYSICAL_PRINTER,
|
||||||
|
// This type is here to support search through the Preferences
|
||||||
|
TYPE_PREFERENCES,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type = TYPE_INVALID;
|
Type type = TYPE_INVALID;
|
||||||
|
@ -2753,7 +2753,8 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->label = L("Synchronize with object layers");
|
def->label = L("Synchronize with object layers");
|
||||||
def->category = L("Support material");
|
def->category = L("Support material");
|
||||||
def->tooltip = L("Synchronize support layers with the object print layers. This is useful "
|
def->tooltip = L("Synchronize support layers with the object print layers. This is useful "
|
||||||
"with multi-material printers, where the extruder switch is expensive.");
|
"with multi-material printers, where the extruder switch is expensive. "
|
||||||
|
"This option is only available when top contact Z distance is set to zero.");
|
||||||
def->mode = comExpert;
|
def->mode = comExpert;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <libslic3r/SLA/RasterBase.hpp>
|
#include <libslic3r/SLA/RasterBase.hpp>
|
||||||
#include "libslic3r/ExPolygon.hpp"
|
#include "libslic3r/ExPolygon.hpp"
|
||||||
#include "libslic3r/MTUtils.hpp"
|
|
||||||
|
|
||||||
// For rasterizing
|
// For rasterizing
|
||||||
#include <agg/agg_basics.h>
|
#include <agg/agg_basics.h>
|
||||||
|
@ -77,6 +77,8 @@ std::unique_ptr<RasterBase> create_raster_grayscale_aa(
|
|||||||
|
|
||||||
if (gamma > 0)
|
if (gamma > 0)
|
||||||
rst = std::make_unique<RasterGrayscaleAAGammaPower>(res, pxdim, tr, gamma);
|
rst = std::make_unique<RasterGrayscaleAAGammaPower>(res, pxdim, tr, gamma);
|
||||||
|
else if (std::abs(gamma - 1.) < 1e-6)
|
||||||
|
rst = std::make_unique<RasterGrayscaleAA>(res, pxdim, tr, agg::gamma_none());
|
||||||
else
|
else
|
||||||
rst = std::make_unique<RasterGrayscaleAA>(res, pxdim, tr, agg::gamma_threshold(.5));
|
rst = std::make_unique<RasterGrayscaleAA>(res, pxdim, tr, agg::gamma_threshold(.5));
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <libslic3r/ExPolygon.hpp>
|
#include <libslic3r/ExPolygon.hpp>
|
||||||
#include <libslic3r/SLA/Concurrency.hpp>
|
//#include <libslic3r/SLA/Concurrency.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "MTUtils.hpp"
|
#include "MTUtils.hpp"
|
||||||
#include "Zipper.hpp"
|
#include "Zipper.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/Execution/ExecutionTBB.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
enum SLAPrintStep : unsigned int {
|
enum SLAPrintStep : unsigned int {
|
||||||
|
@ -49,4 +49,19 @@
|
|||||||
#define ENABLE_NEW_CAMERA_MOVEMENTS_SHIFT_SELECTION (1 && ENABLE_2_4_1_RC)
|
#define ENABLE_NEW_CAMERA_MOVEMENTS_SHIFT_SELECTION (1 && ENABLE_2_4_1_RC)
|
||||||
|
|
||||||
|
|
||||||
|
//====================
|
||||||
|
// 2.5.0.alpha1 techs
|
||||||
|
//====================
|
||||||
|
#define ENABLE_2_5_0_ALPHA1 1
|
||||||
|
|
||||||
|
// Enable changes in preview layout
|
||||||
|
#define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
// Enable drawing the items in legend toolbar using icons
|
||||||
|
#define ENABLE_LEGEND_TOOLBAR_ICONS (1 && ENABLE_PREVIEW_LAYOUT)
|
||||||
|
// Enable coloring of toolpaths in preview by layer time
|
||||||
|
#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
// Enable showing time estimate for travel moves in legend
|
||||||
|
#define ENABLE_TRAVEL_TIME (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
|
||||||
|
|
||||||
#endif // _prusaslicer_technologies_h_
|
#endif // _prusaslicer_technologies_h_
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
@ -360,7 +361,7 @@ inline std::string get_time_dhms(float time_in_secs)
|
|||||||
else if (minutes > 0)
|
else if (minutes > 0)
|
||||||
::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs);
|
::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs);
|
||||||
else
|
else
|
||||||
::sprintf(buffer, "%ds", (int)time_in_secs);
|
::sprintf(buffer, "%ds", (int)std::round(time_in_secs));
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -169,9 +169,11 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/PrintHostDialogs.cpp
|
GUI/PrintHostDialogs.cpp
|
||||||
GUI/PrintHostDialogs.hpp
|
GUI/PrintHostDialogs.hpp
|
||||||
GUI/Jobs/Job.hpp
|
GUI/Jobs/Job.hpp
|
||||||
GUI/Jobs/Job.cpp
|
GUI/Jobs/Worker.hpp
|
||||||
GUI/Jobs/PlaterJob.hpp
|
GUI/Jobs/BoostThreadWorker.hpp
|
||||||
GUI/Jobs/PlaterJob.cpp
|
GUI/Jobs/BoostThreadWorker.cpp
|
||||||
|
GUI/Jobs/BusyCursorJob.hpp
|
||||||
|
GUI/Jobs/PlaterWorker.hpp
|
||||||
GUI/Jobs/ArrangeJob.hpp
|
GUI/Jobs/ArrangeJob.hpp
|
||||||
GUI/Jobs/ArrangeJob.cpp
|
GUI/Jobs/ArrangeJob.cpp
|
||||||
GUI/Jobs/RotoptimizeJob.hpp
|
GUI/Jobs/RotoptimizeJob.hpp
|
||||||
@ -183,6 +185,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/Jobs/ProgressIndicator.hpp
|
GUI/Jobs/ProgressIndicator.hpp
|
||||||
GUI/Jobs/NotificationProgressIndicator.hpp
|
GUI/Jobs/NotificationProgressIndicator.hpp
|
||||||
GUI/Jobs/NotificationProgressIndicator.cpp
|
GUI/Jobs/NotificationProgressIndicator.cpp
|
||||||
|
GUI/Jobs/ThreadSafeQueue.hpp
|
||||||
|
GUI/Jobs/SLAImportDialog.hpp
|
||||||
GUI/ProgressStatusBar.hpp
|
GUI/ProgressStatusBar.hpp
|
||||||
GUI/ProgressStatusBar.cpp
|
GUI/ProgressStatusBar.cpp
|
||||||
GUI/Mouse3DController.cpp
|
GUI/Mouse3DController.cpp
|
||||||
@ -258,6 +262,12 @@ endif ()
|
|||||||
|
|
||||||
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
|
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
|
||||||
|
|
||||||
|
foreach(_source IN ITEMS ${SLIC3R_GUI_SOURCES})
|
||||||
|
get_filename_component(_source_path "${_source}" PATH)
|
||||||
|
string(REPLACE "/" "\\" _group_path "${_source_path}")
|
||||||
|
source_group("${_group_path}" FILES "${_source}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
encoding_check(libslic3r_gui)
|
encoding_check(libslic3r_gui)
|
||||||
|
|
||||||
target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES})
|
target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES})
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
static const float GROUND_Z = -0.02f;
|
static const float GROUND_Z = -0.02f;
|
||||||
static const std::array<float, 4> DEFAULT_MODEL_COLOR = { 0.235f, 0.235f, 0.235f, 1.0f };
|
static const Slic3r::ColorRGBA DEFAULT_MODEL_COLOR = Slic3r::ColorRGBA::DARK_GRAY();
|
||||||
static const std::array<float, 4> PICKING_MODEL_COLOR = { 0.0f, 0.0f, 0.0f, 1.0f };
|
static const Slic3r::ColorRGBA PICKING_MODEL_COLOR = Slic3r::ColorRGBA::BLACK();
|
||||||
|
static const Slic3r::ColorRGBA DEFAULT_SOLID_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f };
|
||||||
|
static const Slic3r::ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 0.6f };
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -121,15 +123,15 @@ void Bed3D::Axes::render() const
|
|||||||
shader->set_uniform("emission_factor", 0.0f);
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
|
|
||||||
// x axis
|
// x axis
|
||||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.75f, 0.0f, 0.0f, 1.0f });
|
const_cast<GLModel*>(&m_arrow)->set_color(-1, ColorRGBA::X());
|
||||||
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
|
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
|
||||||
|
|
||||||
// y axis
|
// y axis
|
||||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.75f, 0.0f, 1.0f });
|
const_cast<GLModel*>(&m_arrow)->set_color(-1, ColorRGBA::Y());
|
||||||
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
|
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
|
||||||
|
|
||||||
// z axis
|
// z axis
|
||||||
const_cast<GLModel*>(&m_arrow)->set_color(-1, { 0.0f, 0.0f, 0.75f, 1.0f });
|
const_cast<GLModel*>(&m_arrow)->set_color(-1, ColorRGBA::Z());
|
||||||
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
|
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
@ -550,10 +552,7 @@ void Bed3D::render_default(bool bottom, bool picking) const
|
|||||||
if (!picking) {
|
if (!picking) {
|
||||||
// draw grid
|
// draw grid
|
||||||
glsafe(::glLineWidth(1.5f * m_scale_factor));
|
glsafe(::glLineWidth(1.5f * m_scale_factor));
|
||||||
if (has_model && !bottom)
|
glsafe(::glColor4fv(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR.data() : DEFAULT_TRANSPARENT_GRID_COLOR.data()));
|
||||||
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 1.0f));
|
|
||||||
else
|
|
||||||
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.6f));
|
|
||||||
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data()));
|
glsafe(::glVertexPointer(3, GL_FLOAT, m_triangles.get_vertex_data_size(), (GLvoid*)m_gridlines.get_vertices_data()));
|
||||||
glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)m_gridlines.get_vertices_count()));
|
glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)m_gridlines.get_vertices_count()));
|
||||||
}
|
}
|
||||||
|
@ -344,20 +344,20 @@ void GLVolume::SinkingContours::update()
|
|||||||
m_model.reset();
|
m_model.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::array<float, 4> GLVolume::SELECTED_COLOR = { 0.0f, 1.0f, 0.0f, 1.0f };
|
const ColorRGBA GLVolume::SELECTED_COLOR = ColorRGBA::GREEN();
|
||||||
const std::array<float, 4> GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f };
|
const ColorRGBA GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f };
|
||||||
const std::array<float, 4> GLVolume::HOVER_DESELECT_COLOR = { 1.0f, 0.75f, 0.75f, 1.0f };
|
const ColorRGBA GLVolume::HOVER_DESELECT_COLOR = { 1.0f, 0.75f, 0.75f, 1.0f };
|
||||||
const std::array<float, 4> GLVolume::OUTSIDE_COLOR = { 0.0f, 0.38f, 0.8f, 1.0f };
|
const ColorRGBA GLVolume::OUTSIDE_COLOR = { 0.0f, 0.38f, 0.8f, 1.0f };
|
||||||
const std::array<float, 4> GLVolume::SELECTED_OUTSIDE_COLOR = { 0.19f, 0.58f, 1.0f, 1.0f };
|
const ColorRGBA GLVolume::SELECTED_OUTSIDE_COLOR = { 0.19f, 0.58f, 1.0f, 1.0f };
|
||||||
const std::array<float, 4> GLVolume::DISABLED_COLOR = { 0.25f, 0.25f, 0.25f, 1.0f };
|
const ColorRGBA GLVolume::DISABLED_COLOR = ColorRGBA::DARK_GRAY();
|
||||||
const std::array<float, 4> GLVolume::SLA_SUPPORT_COLOR = { 0.75f, 0.75f, 0.75f, 1.0f };
|
const ColorRGBA GLVolume::SLA_SUPPORT_COLOR = ColorRGBA::LIGHT_GRAY();
|
||||||
const std::array<float, 4> GLVolume::SLA_PAD_COLOR = { 0.0f, 0.2f, 0.0f, 1.0f };
|
const ColorRGBA GLVolume::SLA_PAD_COLOR = { 0.0f, 0.2f, 0.0f, 1.0f };
|
||||||
const std::array<float, 4> GLVolume::NEUTRAL_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f };
|
const ColorRGBA GLVolume::NEUTRAL_COLOR = { 0.9f, 0.9f, 0.9f, 1.0f };
|
||||||
const std::array<std::array<float, 4>, 4> GLVolume::MODEL_COLOR = { {
|
const std::array<ColorRGBA, 4> GLVolume::MODEL_COLOR = { {
|
||||||
{ 1.0f, 1.0f, 0.0f, 1.f },
|
ColorRGBA::YELLOW(),
|
||||||
{ 1.0f, 0.5f, 0.5f, 1.f },
|
{ 1.0f, 0.5f, 0.5f, 1.0f },
|
||||||
{ 0.5f, 1.0f, 0.5f, 1.f },
|
{ 0.5f, 1.0f, 0.5f, 1.0f },
|
||||||
{ 0.5f, 0.5f, 1.0f, 1.f }
|
{ 0.5f, 0.5f, 1.0f, 1.0f }
|
||||||
} };
|
} };
|
||||||
|
|
||||||
GLVolume::GLVolume(float r, float g, float b, float a)
|
GLVolume::GLVolume(float r, float g, float b, float a)
|
||||||
@ -388,21 +388,6 @@ GLVolume::GLVolume(float r, float g, float b, float a)
|
|||||||
set_render_color(color);
|
set_render_color(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLVolume::set_color(const std::array<float, 4>& rgba)
|
|
||||||
{
|
|
||||||
color = rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLVolume::set_render_color(float r, float g, float b, float a)
|
|
||||||
{
|
|
||||||
render_color = { r, g, b, a };
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLVolume::set_render_color(const std::array<float, 4>& rgba)
|
|
||||||
{
|
|
||||||
render_color = rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLVolume::set_render_color()
|
void GLVolume::set_render_color()
|
||||||
{
|
{
|
||||||
bool outside = is_outside || is_below_printbed();
|
bool outside = is_outside || is_below_printbed();
|
||||||
@ -432,40 +417,28 @@ void GLVolume::set_render_color()
|
|||||||
set_render_color(color);
|
set_render_color(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!printable) {
|
if (!printable)
|
||||||
render_color[0] /= 4;
|
render_color = saturate(render_color, 0.25f);
|
||||||
render_color[1] /= 4;
|
|
||||||
render_color[2] /= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force_transparent)
|
if (force_transparent)
|
||||||
render_color[3] = color[3];
|
render_color.a(color.a());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume)
|
ColorRGBA color_from_model_volume(const ModelVolume& model_volume)
|
||||||
{
|
{
|
||||||
std::array<float, 4> color;
|
ColorRGBA color;
|
||||||
if (model_volume.is_negative_volume()) {
|
if (model_volume.is_negative_volume())
|
||||||
color[0] = 0.2f;
|
color = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||||
color[1] = 0.2f;
|
else if (model_volume.is_modifier())
|
||||||
color[2] = 0.2f;
|
color = { 1.0, 1.0f, 0.2f, 1.0f };
|
||||||
}
|
else if (model_volume.is_support_blocker())
|
||||||
else if (model_volume.is_modifier()) {
|
color = { 1.0f, 0.2f, 0.2f, 1.0f };
|
||||||
color[0] = 1.0f;
|
else if (model_volume.is_support_enforcer())
|
||||||
color[1] = 1.0f;
|
color = { 0.2f, 0.2f, 1.0f, 1.0f };
|
||||||
color[2] = 0.2f;
|
|
||||||
}
|
if (!model_volume.is_model_part())
|
||||||
else if (model_volume.is_support_blocker()) {
|
color.a(0.5f);
|
||||||
color[0] = 1.0f;
|
|
||||||
color[1] = 0.2f;
|
|
||||||
color[2] = 0.2f;
|
|
||||||
}
|
|
||||||
else if (model_volume.is_support_enforcer()) {
|
|
||||||
color[0] = 0.2f;
|
|
||||||
color[1] = 0.2f;
|
|
||||||
color[2] = 1.0f;
|
|
||||||
}
|
|
||||||
color[3] = model_volume.is_model_part() ? 1.f : 0.5f;
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,8 +598,8 @@ int GLVolumeCollection::load_object_volume(
|
|||||||
const int extruder_id = model_volume->extruder_id();
|
const int extruder_id = model_volume->extruder_id();
|
||||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||||
const TriangleMesh &mesh = model_volume->mesh();
|
const TriangleMesh &mesh = model_volume->mesh();
|
||||||
std::array<float, 4> color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4];
|
ColorRGBA color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4];
|
||||||
color[3] = model_volume->is_model_part() ? 1.f : 0.5f;
|
color.a(model_volume->is_model_part() ? 1.0f : 0.5f);
|
||||||
this->volumes.emplace_back(new GLVolume(color));
|
this->volumes.emplace_back(new GLVolume(color));
|
||||||
GLVolume& v = *this->volumes.back();
|
GLVolume& v = *this->volumes.back();
|
||||||
v.set_color(color_from_model_volume(*model_volume));
|
v.set_color(color_from_model_volume(*model_volume));
|
||||||
@ -707,13 +680,13 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
|||||||
height = 0.1f;
|
height = 0.1f;
|
||||||
|
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
std::array<float, 4> color = { 0.5f, 0.5f, 0.0f, 1.0f };
|
ColorRGBA color = ColorRGBA::DARK_YELLOW();
|
||||||
|
|
||||||
// In case we don't know precise dimensions of the wipe tower yet, we'll draw
|
// In case we don't know precise dimensions of the wipe tower yet, we'll draw
|
||||||
// the box with different color with one side jagged:
|
// the box with different color with one side jagged:
|
||||||
if (size_unknown) {
|
if (size_unknown) {
|
||||||
color[0] = 0.9f;
|
color.r(0.9f);
|
||||||
color[1] = 0.6f;
|
color.g(0.6f);
|
||||||
|
|
||||||
// Too narrow tower would interfere with the teeth. The estimate is not precise anyway.
|
// Too narrow tower would interfere with the teeth. The estimate is not precise anyway.
|
||||||
depth = std::max(depth, 10.f);
|
depth = std::max(depth, 10.f);
|
||||||
@ -769,14 +742,14 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
|||||||
return int(volumes.size() - 1);
|
return int(volumes.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLVolume* GLVolumeCollection::new_toolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats)
|
GLVolume* GLVolumeCollection::new_toolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats)
|
||||||
{
|
{
|
||||||
GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats);
|
GLVolume *out = new_nontoolpath_volume(rgba, reserve_vbo_floats);
|
||||||
out->is_extrusion_path = true;
|
out->is_extrusion_path = true;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLVolume* GLVolumeCollection::new_nontoolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats)
|
GLVolume* GLVolumeCollection::new_nontoolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats)
|
||||||
{
|
{
|
||||||
GLVolume *out = new GLVolume(rgba);
|
GLVolume *out = new GLVolume(rgba);
|
||||||
out->is_extrusion_path = false;
|
out->is_extrusion_path = false;
|
||||||
@ -793,7 +766,7 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) {
|
for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) {
|
||||||
GLVolume* volume = volumes[i];
|
GLVolume* volume = volumes[i];
|
||||||
bool is_transparent = (volume->render_color[3] < 1.0f);
|
bool is_transparent = volume->render_color.is_transparent();
|
||||||
if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) ||
|
if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) ||
|
||||||
(type == GLVolumeCollection::ERenderType::Transparent && is_transparent) ||
|
(type == GLVolumeCollection::ERenderType::Transparent && is_transparent) ||
|
||||||
type == GLVolumeCollection::ERenderType::All) &&
|
type == GLVolumeCollection::ERenderType::All) &&
|
||||||
@ -972,8 +945,7 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo
|
|||||||
|
|
||||||
void GLVolumeCollection::reset_outside_state()
|
void GLVolumeCollection::reset_outside_state()
|
||||||
{
|
{
|
||||||
for (GLVolume* volume : this->volumes)
|
for (GLVolume* volume : this->volumes) {
|
||||||
{
|
|
||||||
if (volume != nullptr)
|
if (volume != nullptr)
|
||||||
volume->is_outside = false;
|
volume->is_outside = false;
|
||||||
}
|
}
|
||||||
@ -981,46 +953,18 @@ void GLVolumeCollection::reset_outside_state()
|
|||||||
|
|
||||||
void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config)
|
void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config)
|
||||||
{
|
{
|
||||||
static const float inv_255 = 1.0f / 255.0f;
|
using ColorItem = std::pair<std::string, ColorRGBA>;
|
||||||
|
std::vector<ColorItem> colors;
|
||||||
|
|
||||||
struct Color
|
if (static_cast<PrinterTechnology>(config->opt_int("printer_technology")) == ptSLA) {
|
||||||
{
|
|
||||||
std::string text;
|
|
||||||
unsigned char rgb[3];
|
|
||||||
|
|
||||||
Color()
|
|
||||||
: text("")
|
|
||||||
{
|
|
||||||
rgb[0] = 255;
|
|
||||||
rgb[1] = 255;
|
|
||||||
rgb[2] = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(const std::string& text, unsigned char* rgb)
|
|
||||||
{
|
|
||||||
this->text = text;
|
|
||||||
::memcpy((void*)this->rgb, (const void*)rgb, 3 * sizeof(unsigned char));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (config == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
unsigned char rgb[3];
|
|
||||||
std::vector<Color> colors;
|
|
||||||
|
|
||||||
if (static_cast<PrinterTechnology>(config->opt_int("printer_technology")) == ptSLA)
|
|
||||||
{
|
|
||||||
const std::string& txt_color = config->opt_string("material_colour").empty() ?
|
const std::string& txt_color = config->opt_string("material_colour").empty() ?
|
||||||
print_config_def.get("material_colour")->get_default_value<ConfigOptionString>()->value :
|
print_config_def.get("material_colour")->get_default_value<ConfigOptionString>()->value :
|
||||||
config->opt_string("material_colour");
|
config->opt_string("material_colour");
|
||||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb)) {
|
ColorRGBA rgba;
|
||||||
colors.resize(1);
|
if (decode_color(txt_color, rgba))
|
||||||
colors[0].set(txt_color, rgb);
|
colors.push_back({ txt_color, rgba });
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("extruder_colour"));
|
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("extruder_colour"));
|
||||||
if (extruders_opt == nullptr)
|
if (extruders_opt == nullptr)
|
||||||
return;
|
return;
|
||||||
@ -1029,37 +973,35 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
|
|||||||
if (filamemts_opt == nullptr)
|
if (filamemts_opt == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size());
|
size_t colors_count = std::max(extruders_opt->values.size(), filamemts_opt->values.size());
|
||||||
if (colors_count == 0)
|
if (colors_count == 0)
|
||||||
return;
|
return;
|
||||||
colors.resize(colors_count);
|
colors.resize(colors_count);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < colors_count; ++i) {
|
for (unsigned int i = 0; i < colors_count; ++i) {
|
||||||
const std::string& txt_color = config->opt_string("extruder_colour", i);
|
const std::string& ext_color = config->opt_string("extruder_colour", i);
|
||||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
ColorRGBA rgba;
|
||||||
colors[i].set(txt_color, rgb);
|
if (decode_color(ext_color, rgba))
|
||||||
|
colors[i] = { ext_color, rgba };
|
||||||
else {
|
else {
|
||||||
const std::string& txt_color = config->opt_string("filament_colour", i);
|
const std::string& fil_color = config->opt_string("filament_colour", i);
|
||||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
if (decode_color(fil_color, rgba))
|
||||||
colors[i].set(txt_color, rgb);
|
colors[i] = { fil_color, rgba };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GLVolume* volume : volumes) {
|
for (GLVolume* volume : volumes) {
|
||||||
if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || (volume->volume_idx() < 0))
|
if (volume == nullptr || volume->is_modifier || volume->is_wipe_tower || volume->volume_idx() < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int extruder_id = volume->extruder_id - 1;
|
int extruder_id = volume->extruder_id - 1;
|
||||||
if (extruder_id < 0 || (int)colors.size() <= extruder_id)
|
if (extruder_id < 0 || (int)colors.size() <= extruder_id)
|
||||||
extruder_id = 0;
|
extruder_id = 0;
|
||||||
|
|
||||||
const Color& color = colors[extruder_id];
|
const ColorItem& color = colors[extruder_id];
|
||||||
if (!color.text.empty()) {
|
if (!color.first.empty())
|
||||||
for (int i = 0; i < 3; ++i) {
|
volume->color = color.second;
|
||||||
volume->color[i] = (float)color.rgb[i] * inv_255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
#include "GLModel.hpp"
|
#include "GLModel.hpp"
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ class ModelVolume;
|
|||||||
enum ModelInstanceEPrintVolumeState : unsigned char;
|
enum ModelInstanceEPrintVolumeState : unsigned char;
|
||||||
|
|
||||||
// Return appropriate color based on the ModelVolume.
|
// Return appropriate color based on the ModelVolume.
|
||||||
std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume);
|
extern ColorRGBA color_from_model_volume(const ModelVolume& model_volume);
|
||||||
|
|
||||||
// A container for interleaved arrays of 3D vertices and normals,
|
// A container for interleaved arrays of 3D vertices and normals,
|
||||||
// possibly indexed by triangles and / or quads.
|
// possibly indexed by triangles and / or quads.
|
||||||
@ -248,16 +249,16 @@ private:
|
|||||||
|
|
||||||
class GLVolume {
|
class GLVolume {
|
||||||
public:
|
public:
|
||||||
static const std::array<float, 4> SELECTED_COLOR;
|
static const ColorRGBA SELECTED_COLOR;
|
||||||
static const std::array<float, 4> HOVER_SELECT_COLOR;
|
static const ColorRGBA HOVER_SELECT_COLOR;
|
||||||
static const std::array<float, 4> HOVER_DESELECT_COLOR;
|
static const ColorRGBA HOVER_DESELECT_COLOR;
|
||||||
static const std::array<float, 4> OUTSIDE_COLOR;
|
static const ColorRGBA OUTSIDE_COLOR;
|
||||||
static const std::array<float, 4> SELECTED_OUTSIDE_COLOR;
|
static const ColorRGBA SELECTED_OUTSIDE_COLOR;
|
||||||
static const std::array<float, 4> DISABLED_COLOR;
|
static const ColorRGBA DISABLED_COLOR;
|
||||||
static const std::array<float, 4> SLA_SUPPORT_COLOR;
|
static const ColorRGBA SLA_SUPPORT_COLOR;
|
||||||
static const std::array<float, 4> SLA_PAD_COLOR;
|
static const ColorRGBA SLA_PAD_COLOR;
|
||||||
static const std::array<float, 4> NEUTRAL_COLOR;
|
static const ColorRGBA NEUTRAL_COLOR;
|
||||||
static const std::array<std::array<float, 4>, 4> MODEL_COLOR;
|
static const std::array<ColorRGBA, 4> MODEL_COLOR;
|
||||||
|
|
||||||
enum EHoverState : unsigned char
|
enum EHoverState : unsigned char
|
||||||
{
|
{
|
||||||
@ -267,8 +268,8 @@ public:
|
|||||||
HS_Deselect
|
HS_Deselect
|
||||||
};
|
};
|
||||||
|
|
||||||
GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f);
|
GLVolume(float r = 1.0f, float g = 1.0f, float b = 1.0f, float a = 1.0f);
|
||||||
GLVolume(const std::array<float, 4>& rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
|
GLVolume(const ColorRGBA& color) : GLVolume(color.r(), color.g(), color.b(), color.a()) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Geometry::Transformation m_instance_transformation;
|
Geometry::Transformation m_instance_transformation;
|
||||||
@ -305,9 +306,9 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Color of the triangles / quads held by this volume.
|
// Color of the triangles / quads held by this volume.
|
||||||
std::array<float, 4> color;
|
ColorRGBA color;
|
||||||
// Color used to render this volume.
|
// Color used to render this volume.
|
||||||
std::array<float, 4> render_color;
|
ColorRGBA render_color;
|
||||||
|
|
||||||
struct CompositeID {
|
struct CompositeID {
|
||||||
CompositeID(int object_id, int volume_id, int instance_id) : object_id(object_id), volume_id(volume_id), instance_id(instance_id) {}
|
CompositeID(int object_id, int volume_id, int instance_id) : object_id(object_id), volume_id(volume_id), instance_id(instance_id) {}
|
||||||
@ -393,9 +394,8 @@ public:
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_color(const std::array<float, 4>& rgba);
|
void set_color(const ColorRGBA& rgba) { color = rgba; }
|
||||||
void set_render_color(float r, float g, float b, float a);
|
void set_render_color(const ColorRGBA& rgba) { render_color = rgba; }
|
||||||
void set_render_color(const std::array<float, 4>& rgba);
|
|
||||||
// Sets render color in dependence of current state
|
// Sets render color in dependence of current state
|
||||||
void set_render_color();
|
void set_render_color();
|
||||||
// set color according to model volume
|
// set color according to model volume
|
||||||
@ -595,8 +595,8 @@ public:
|
|||||||
int load_wipe_tower_preview(
|
int load_wipe_tower_preview(
|
||||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
|
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
|
||||||
|
|
||||||
GLVolume* new_toolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats = 0);
|
GLVolume* new_toolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0);
|
||||||
GLVolume* new_nontoolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats = 0);
|
GLVolume* new_nontoolpath_volume(const ColorRGBA& rgba, size_t reserve_vbo_floats = 0);
|
||||||
|
|
||||||
// Render the volumes by OpenGL.
|
// Render the volumes by OpenGL.
|
||||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
|
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>()) const;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
|
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
@ -133,12 +134,12 @@ wxString CopyrightsDialog::get_html_text()
|
|||||||
wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
wxColour bgr_clr = wxGetApp().get_window_default_clr();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||||
|
|
||||||
const auto text_clr = wxGetApp().get_label_clr_default();
|
const auto text_clr = wxGetApp().get_label_clr_default();
|
||||||
const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue()));
|
||||||
const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
|
||||||
|
|
||||||
const wxString copyright_str = _(L("Copyright")) + "© ";
|
const wxString copyright_str = _L("Copyright") + "© ";
|
||||||
// TRN "Slic3r _is licensed under the_ License"
|
// TRN "Slic3r _is licensed under the_ License"
|
||||||
const wxString header_str = _(L("License agreements of all following programs (libraries) are part of application license agreement"));
|
const wxString header_str = _L("License agreements of all following programs (libraries) are part of application license agreement");
|
||||||
|
|
||||||
wxString text = wxString::Format(
|
wxString text = wxString::Format(
|
||||||
"<html>"
|
"<html>"
|
||||||
@ -257,8 +258,8 @@ AboutDialog::AboutDialog()
|
|||||||
m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit()));
|
m_html->SetMinSize(wxSize(-1, 16 * wxGetApp().em_unit()));
|
||||||
wxFont font = get_default_font(this);
|
wxFont font = get_default_font(this);
|
||||||
const auto text_clr = wxGetApp().get_label_clr_default();
|
const auto text_clr = wxGetApp().get_label_clr_default();
|
||||||
auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue()));
|
||||||
auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
|
||||||
|
|
||||||
const int fs = font.GetPointSize()-1;
|
const int fs = font.GetPointSize()-1;
|
||||||
int size[] = {fs,fs,fs,fs,fs,fs,fs};
|
int size[] = {fs,fs,fs,fs,fs,fs,fs};
|
||||||
|
@ -395,21 +395,5 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
|
|||||||
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
|
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
|
|
||||||
{
|
|
||||||
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;
|
|
||||||
if (scolor.size() != 7 || scolor.front() != '#')
|
|
||||||
return false;
|
|
||||||
const char* c = scolor.data() + 1;
|
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
|
||||||
int digit1 = hex_digit_to_int(*c++);
|
|
||||||
int digit2 = hex_digit_to_int(*c++);
|
|
||||||
if (digit1 == -1 || digit2 == -1)
|
|
||||||
return false;
|
|
||||||
rgb_out[i] = (unsigned char)(digit1 * 16 + digit2);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -9,9 +9,12 @@
|
|||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
struct NSVGimage;
|
struct NSVGimage;
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
class BitmapCache
|
class BitmapCache
|
||||||
{
|
{
|
||||||
@ -43,11 +46,9 @@ public:
|
|||||||
wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false, const std::string& new_color = "");
|
wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false, const std::string& new_color = "");
|
||||||
|
|
||||||
wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false);
|
wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false);
|
||||||
wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3], bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); }
|
wxBitmap mksolid(size_t width, size_t height, const ColorRGB& rgb, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar(), wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); }
|
||||||
wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
|
wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
|
||||||
|
|
||||||
static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, wxBitmap*> m_map;
|
std::map<std::string, wxBitmap*> m_map;
|
||||||
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
|
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Time.hpp"
|
#include "libslic3r/Time.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
@ -31,11 +32,9 @@ static wxString format_reason(const Config::Snapshot::Reason reason)
|
|||||||
|
|
||||||
static std::string get_color(wxColour colour)
|
static std::string get_color(wxColour colour)
|
||||||
{
|
{
|
||||||
wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
|
return encode_color(ColorRGB(colour.Red(), colour.Green(), colour.Blue()));
|
||||||
return clr_str.ToStdString();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_even, bool snapshot_active, bool dark_mode)
|
static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_even, bool snapshot_active, bool dark_mode)
|
||||||
{
|
{
|
||||||
// Start by declaring a row with an alternating background color.
|
// Start by declaring a row with an alternating background color.
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "libslic3r/Config.hpp"
|
#include "libslic3r/Config.hpp"
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
@ -746,9 +747,9 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
|
|||||||
wxSystemSettings::GetColour(wxSYS_COLOUR_MENU);
|
wxSystemSettings::GetColour(wxSYS_COLOUR_MENU);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
|
||||||
const auto text_clr = wxGetApp().get_label_clr_default();
|
const auto text_clr = wxGetApp().get_label_clr_default();
|
||||||
const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()));
|
||||||
|
const auto text_clr_str = encode_color(ColorRGB(text_clr.Red(), text_clr.Green(), text_clr.Blue()));
|
||||||
wxString first_line = format_wxstr(_L("%1% marked with <b>*</b> are <b>not</b> compatible with some installed printers."), materials->technology == T_FFF ? _L("Filaments") : _L("SLA materials"));
|
wxString first_line = format_wxstr(_L("%1% marked with <b>*</b> are <b>not</b> compatible with some installed printers."), materials->technology == T_FFF ? _L("Filaments") : _L("SLA materials"));
|
||||||
wxString text;
|
wxString text;
|
||||||
if (all_printers) {
|
if (all_printers) {
|
||||||
@ -2522,24 +2523,34 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||||||
{
|
{
|
||||||
wxString header, caption = _L("Configuration is edited in ConfigWizard");
|
wxString header, caption = _L("Configuration is edited in ConfigWizard");
|
||||||
const auto enabled_vendors = appconfig_new.vendors();
|
const auto enabled_vendors = appconfig_new.vendors();
|
||||||
|
const auto enabled_vendors_old = app_config->vendors();
|
||||||
|
|
||||||
bool suppress_sla_printer = model_has_multi_part_objects(wxGetApp().model());
|
bool suppress_sla_printer = model_has_multi_part_objects(wxGetApp().model());
|
||||||
PrinterTechnology preferred_pt = ptAny;
|
PrinterTechnology preferred_pt = ptAny;
|
||||||
auto get_preferred_printer_technology = [enabled_vendors, suppress_sla_printer](const std::string& bundle_name, const Bundle& bundle) {
|
auto get_preferred_printer_technology = [enabled_vendors, enabled_vendors_old, suppress_sla_printer](const std::string& bundle_name, const Bundle& bundle) {
|
||||||
const auto config = enabled_vendors.find(bundle_name);
|
const auto config = enabled_vendors.find(bundle_name);
|
||||||
PrinterTechnology pt = ptAny;
|
PrinterTechnology pt = ptAny;
|
||||||
if (config != enabled_vendors.end()) {
|
if (config != enabled_vendors.end()) {
|
||||||
for (const auto& model : bundle.vendor_profile->models) {
|
for (const auto& model : bundle.vendor_profile->models) {
|
||||||
if (const auto model_it = config->second.find(model.id);
|
if (const auto model_it = config->second.find(model.id);
|
||||||
model_it != config->second.end() && model_it->second.size() > 0) {
|
model_it != config->second.end() && model_it->second.size() > 0) {
|
||||||
if (pt == ptAny)
|
|
||||||
pt = model.technology;
|
pt = model.technology;
|
||||||
// if preferred printer model has SLA printer technology it's important to check the model for multypart state
|
const auto config_old = enabled_vendors_old.find(bundle_name);
|
||||||
|
if (config_old == enabled_vendors_old.end() || config_old->second.find(model.id) == config_old->second.end()) {
|
||||||
|
// if preferred printer model has SLA printer technology it's important to check the model for multi-part state
|
||||||
if (pt == ptSLA && suppress_sla_printer)
|
if (pt == ptSLA && suppress_sla_printer)
|
||||||
continue;
|
continue;
|
||||||
else
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const auto model_it_old = config_old->second.find(model.id);
|
||||||
|
model_it_old == config_old->second.end() || model_it_old->second != model_it->second) {
|
||||||
|
// if preferred printer model has SLA printer technology it's important to check the model for multi-part state
|
||||||
|
if (pt == ptSLA && suppress_sla_printer)
|
||||||
|
continue;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pt;
|
return pt;
|
||||||
@ -2645,7 +2656,6 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||||||
|
|
||||||
std::string preferred_model;
|
std::string preferred_model;
|
||||||
std::string preferred_variant;
|
std::string preferred_variant;
|
||||||
const auto enabled_vendors_old = app_config->vendors();
|
|
||||||
auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old, preferred_pt](const std::string& bundle_name, const Bundle& bundle, std::string& variant) {
|
auto get_preferred_printer_model = [enabled_vendors, enabled_vendors_old, preferred_pt](const std::string& bundle_name, const Bundle& bundle, std::string& variant) {
|
||||||
const auto config = enabled_vendors.find(bundle_name);
|
const auto config = enabled_vendors.find(bundle_name);
|
||||||
if (config == enabled_vendors.end())
|
if (config == enabled_vendors.end())
|
||||||
|
@ -2557,36 +2557,46 @@ bool Control::check_ticks_changed_event(Type type)
|
|||||||
|
|
||||||
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)
|
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)
|
||||||
{
|
{
|
||||||
|
auto opposite_one_color = [](const std::string& color) {
|
||||||
|
ColorRGB rgb;
|
||||||
|
decode_color(color, rgb);
|
||||||
|
return encode_color(opposite(rgb));
|
||||||
|
};
|
||||||
|
auto opposite_two_colors = [](const std::string& a, const std::string& b) {
|
||||||
|
ColorRGB rgb1; decode_color(a, rgb1);
|
||||||
|
ColorRGB rgb2; decode_color(b, rgb2);
|
||||||
|
return encode_color(opposite(rgb1, rgb2));
|
||||||
|
};
|
||||||
|
|
||||||
if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) {
|
if (mode == SingleExtruder && type == ColorChange && m_use_default_colors) {
|
||||||
#if 1
|
#if 1
|
||||||
if (ticks.empty())
|
if (ticks.empty())
|
||||||
return color_generator.get_opposite_color((*m_colors)[0]);
|
return opposite_one_color((*m_colors)[0]);
|
||||||
|
|
||||||
auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick);
|
auto before_tick_it = std::lower_bound(ticks.begin(), ticks.end(), tick);
|
||||||
if (before_tick_it == ticks.end())
|
if (before_tick_it == ticks.end()) {
|
||||||
{
|
|
||||||
while (before_tick_it != ticks.begin())
|
while (before_tick_it != ticks.begin())
|
||||||
if (--before_tick_it; before_tick_it->type == ColorChange)
|
if (--before_tick_it; before_tick_it->type == ColorChange)
|
||||||
break;
|
break;
|
||||||
if (before_tick_it->type == ColorChange)
|
if (before_tick_it->type == ColorChange)
|
||||||
return color_generator.get_opposite_color(before_tick_it->color);
|
return opposite_one_color(before_tick_it->color);
|
||||||
return color_generator.get_opposite_color((*m_colors)[0]);
|
|
||||||
|
return opposite_one_color((*m_colors)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (before_tick_it == ticks.begin())
|
if (before_tick_it == ticks.begin()) {
|
||||||
{
|
|
||||||
const std::string& frst_color = (*m_colors)[0];
|
const std::string& frst_color = (*m_colors)[0];
|
||||||
if (before_tick_it->type == ColorChange)
|
if (before_tick_it->type == ColorChange)
|
||||||
return color_generator.get_opposite_color(frst_color, before_tick_it->color);
|
return opposite_two_colors(frst_color, before_tick_it->color);
|
||||||
|
|
||||||
auto next_tick_it = before_tick_it;
|
auto next_tick_it = before_tick_it;
|
||||||
while (next_tick_it != ticks.end())
|
while (next_tick_it != ticks.end())
|
||||||
if (++next_tick_it; next_tick_it->type == ColorChange)
|
if (++next_tick_it; next_tick_it->type == ColorChange)
|
||||||
break;
|
break;
|
||||||
if (next_tick_it->type == ColorChange)
|
if (next_tick_it->type == ColorChange)
|
||||||
return color_generator.get_opposite_color(frst_color, next_tick_it->color);
|
return opposite_two_colors(frst_color, next_tick_it->color);
|
||||||
|
|
||||||
return color_generator.get_opposite_color(frst_color);
|
return opposite_one_color(frst_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string frst_color = "";
|
std::string frst_color = "";
|
||||||
@ -2607,13 +2617,15 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int
|
|||||||
|
|
||||||
if (before_tick_it->type == ColorChange) {
|
if (before_tick_it->type == ColorChange) {
|
||||||
if (frst_color.empty())
|
if (frst_color.empty())
|
||||||
return color_generator.get_opposite_color(before_tick_it->color);
|
return opposite_one_color(before_tick_it->color);
|
||||||
return color_generator.get_opposite_color(before_tick_it->color, frst_color);
|
|
||||||
|
return opposite_two_colors(before_tick_it->color, frst_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frst_color.empty())
|
if (frst_color.empty())
|
||||||
return color_generator.get_opposite_color((*m_colors)[0]);
|
return opposite_one_color((*m_colors)[0]);
|
||||||
return color_generator.get_opposite_color((*m_colors)[0], frst_color);
|
|
||||||
|
return opposite_two_colors((*m_colors)[0], frst_color);
|
||||||
#else
|
#else
|
||||||
const std::vector<std::string>& colors = ColorPrintColors::get();
|
const std::vector<std::string>& colors = ColorPrintColors::get();
|
||||||
if (ticks.empty())
|
if (ticks.empty())
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "libslic3r/CustomGCode.hpp"
|
#include "libslic3r/CustomGCode.hpp"
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
#include "DoubleSlider_Utils.hpp"
|
|
||||||
|
|
||||||
#include <wx/window.h>
|
#include <wx/window.h>
|
||||||
#include <wx/control.h>
|
#include <wx/control.h>
|
||||||
@ -119,7 +118,6 @@ class TickCodeInfo
|
|||||||
// int m_default_color_idx = 0;
|
// int m_default_color_idx = 0;
|
||||||
|
|
||||||
std::vector<std::string>* m_colors {nullptr};
|
std::vector<std::string>* m_colors {nullptr};
|
||||||
ColorGenerator color_generator;
|
|
||||||
|
|
||||||
std::string get_color_for_tick(TickCode tick, Type type, const int extruder);
|
std::string get_color_for_tick(TickCode tick, Type type, const int extruder);
|
||||||
|
|
||||||
|
@ -1,191 +1,8 @@
|
|||||||
|
#ifndef slic3r_GUI_DoubleSlider_Utils_hpp_
|
||||||
|
#define slic3r_GUI_DoubleSlider_Utils_hpp_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include "wx/colour.h"
|
|
||||||
|
|
||||||
class ColorGenerator
|
#endif // slic3r_GUI_DoubleSlider_Utils_hpp_
|
||||||
{
|
|
||||||
// Some of next code is borrowed from https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
|
|
||||||
typedef struct {
|
|
||||||
double r; // a fraction between 0 and 1
|
|
||||||
double g; // a fraction between 0 and 1
|
|
||||||
double b; // a fraction between 0 and 1
|
|
||||||
} rgb;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
double h; // angle in degrees
|
|
||||||
double s; // a fraction between 0 and 1
|
|
||||||
double v; // a fraction between 0 and 1
|
|
||||||
} hsv;
|
|
||||||
|
|
||||||
//static hsv rgb2hsv(rgb in);
|
|
||||||
//static rgb hsv2rgb(hsv in);
|
|
||||||
|
|
||||||
hsv rgb2hsv(rgb in)
|
|
||||||
{
|
|
||||||
hsv out;
|
|
||||||
double min, max, delta;
|
|
||||||
|
|
||||||
min = in.r < in.g ? in.r : in.g;
|
|
||||||
min = min < in.b ? min : in.b;
|
|
||||||
|
|
||||||
max = in.r > in.g ? in.r : in.g;
|
|
||||||
max = max > in.b ? max : in.b;
|
|
||||||
|
|
||||||
out.v = max; // v
|
|
||||||
delta = max - min;
|
|
||||||
if (delta < 0.00001)
|
|
||||||
{
|
|
||||||
out.s = 0;
|
|
||||||
out.h = 0; // undefined, maybe nan?
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
if (max > 0.0) { // NOTE: if Max is == 0, this divide would cause a crash
|
|
||||||
out.s = (delta / max); // s
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// if max is 0, then r = g = b = 0
|
|
||||||
// s = 0, h is undefined
|
|
||||||
out.s = 0.0;
|
|
||||||
out.h = NAN; // its now undefined
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
if (in.r >= max) // > is bogus, just keeps compilor happy
|
|
||||||
out.h = (in.g - in.b) / delta; // between yellow & magenta
|
|
||||||
else
|
|
||||||
if (in.g >= max)
|
|
||||||
out.h = 2.0 + (in.b - in.r) / delta; // between cyan & yellow
|
|
||||||
else
|
|
||||||
out.h = 4.0 + (in.r - in.g) / delta; // between magenta & cyan
|
|
||||||
|
|
||||||
out.h *= 60.0; // degrees
|
|
||||||
|
|
||||||
if (out.h < 0.0)
|
|
||||||
out.h += 360.0;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
hsv rgb2hsv(const std::string& str_clr_in)
|
|
||||||
{
|
|
||||||
wxColour clr(str_clr_in);
|
|
||||||
rgb in = { clr.Red() / 255.0, clr.Green() / 255.0, clr.Blue() / 255.0 };
|
|
||||||
return rgb2hsv(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rgb hsv2rgb(hsv in)
|
|
||||||
{
|
|
||||||
double hh, p, q, t, ff;
|
|
||||||
long i;
|
|
||||||
rgb out;
|
|
||||||
|
|
||||||
if (in.s <= 0.0) { // < is bogus, just shuts up warnings
|
|
||||||
out.r = in.v;
|
|
||||||
out.g = in.v;
|
|
||||||
out.b = in.v;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
hh = in.h;
|
|
||||||
if (hh >= 360.0) hh -= 360.0;//hh = 0.0;
|
|
||||||
hh /= 60.0;
|
|
||||||
i = (long)hh;
|
|
||||||
ff = hh - i;
|
|
||||||
p = in.v * (1.0 - in.s);
|
|
||||||
q = in.v * (1.0 - (in.s * ff));
|
|
||||||
t = in.v * (1.0 - (in.s * (1.0 - ff)));
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
out.r = in.v;
|
|
||||||
out.g = t;
|
|
||||||
out.b = p;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
out.r = q;
|
|
||||||
out.g = in.v;
|
|
||||||
out.b = p;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
out.r = p;
|
|
||||||
out.g = in.v;
|
|
||||||
out.b = t;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
out.r = p;
|
|
||||||
out.g = q;
|
|
||||||
out.b = in.v;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
out.r = t;
|
|
||||||
out.g = p;
|
|
||||||
out.b = in.v;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
default:
|
|
||||||
out.r = in.v;
|
|
||||||
out.g = p;
|
|
||||||
out.b = q;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::random_device rd;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ColorGenerator() {}
|
|
||||||
~ColorGenerator() {}
|
|
||||||
|
|
||||||
double rand_val()
|
|
||||||
{
|
|
||||||
std::mt19937 rand_generator(rd());
|
|
||||||
|
|
||||||
// this value will be used for Saturation and Value
|
|
||||||
// to avoid extremely light/dark colors, take this value from range [0.65; 1.0]
|
|
||||||
std::uniform_real_distribution<double> distrib(0.65, 1.0);
|
|
||||||
return distrib(rand_generator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string get_opposite_color(const std::string& color)
|
|
||||||
{
|
|
||||||
std::string opp_color = "";
|
|
||||||
|
|
||||||
hsv hsv_clr = rgb2hsv(color);
|
|
||||||
hsv_clr.h += 65; // 65 instead 60 to avoid circle values
|
|
||||||
hsv_clr.s = rand_val();
|
|
||||||
hsv_clr.v = rand_val();
|
|
||||||
|
|
||||||
rgb rgb_opp_color = hsv2rgb(hsv_clr);
|
|
||||||
|
|
||||||
wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255));
|
|
||||||
opp_color = clr_str.ToStdString();
|
|
||||||
|
|
||||||
return opp_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_opposite_color(const std::string& color_frst, const std::string& color_scnd)
|
|
||||||
{
|
|
||||||
std::string opp_color = "";
|
|
||||||
|
|
||||||
hsv hsv_frst = rgb2hsv(color_frst);
|
|
||||||
hsv hsv_scnd = rgb2hsv(color_scnd);
|
|
||||||
|
|
||||||
double delta_h = fabs(hsv_frst.h - hsv_scnd.h);
|
|
||||||
double start_h = delta_h > 180 ? std::min<double>(hsv_scnd.h, hsv_frst.h) : std::max<double>(hsv_scnd.h, hsv_frst.h);
|
|
||||||
start_h += 5; // to avoid circle change of colors for 120 deg
|
|
||||||
if (delta_h < 180)
|
|
||||||
delta_h = 360 - delta_h;
|
|
||||||
|
|
||||||
hsv hsv_opp = hsv{ start_h + 0.5 * delta_h, rand_val(), rand_val() };
|
|
||||||
rgb rgb_opp_color = hsv2rgb(hsv_opp);
|
|
||||||
|
|
||||||
wxString clr_str = wxString::Format(wxT("#%02X%02X%02X"), (unsigned char)(rgb_opp_color.r * 255), (unsigned char)(rgb_opp_color.g * 255), (unsigned char)(rgb_opp_color.b * 255));
|
|
||||||
opp_color = clr_str.ToStdString();
|
|
||||||
|
|
||||||
return opp_color;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -1387,12 +1387,7 @@ void ColourPicker::set_value(const boost::any& value, bool change_event)
|
|||||||
boost::any& ColourPicker::get_value()
|
boost::any& ColourPicker::get_value()
|
||||||
{
|
{
|
||||||
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
|
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
|
||||||
if (colour == wxTransparentColour)
|
m_value = (colour == wxTransparentColour) ? std::string("") : encode_color(ColorRGB(colour.Red(), colour.Green(), colour.Blue()));
|
||||||
m_value = std::string("");
|
|
||||||
else {
|
|
||||||
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
|
|
||||||
m_value = clr_str.ToStdString();
|
|
||||||
}
|
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ namespace GUI {
|
|||||||
class GCodeViewer
|
class GCodeViewer
|
||||||
{
|
{
|
||||||
using IBufferType = unsigned short;
|
using IBufferType = unsigned short;
|
||||||
using Color = std::array<float, 4>;
|
|
||||||
using VertexBuffer = std::vector<float>;
|
using VertexBuffer = std::vector<float>;
|
||||||
using MultiVertexBuffer = std::vector<VertexBuffer>;
|
using MultiVertexBuffer = std::vector<VertexBuffer>;
|
||||||
using IndexBuffer = std::vector<IBufferType>;
|
using IndexBuffer = std::vector<IBufferType>;
|
||||||
@ -31,12 +30,12 @@ class GCodeViewer
|
|||||||
using InstanceIdBuffer = std::vector<size_t>;
|
using InstanceIdBuffer = std::vector<size_t>;
|
||||||
using InstancesOffsets = std::vector<Vec3f>;
|
using InstancesOffsets = std::vector<Vec3f>;
|
||||||
|
|
||||||
static const std::vector<Color> Extrusion_Role_Colors;
|
static const std::vector<ColorRGBA> Extrusion_Role_Colors;
|
||||||
static const std::vector<Color> Options_Colors;
|
static const std::vector<ColorRGBA> Options_Colors;
|
||||||
static const std::vector<Color> Travel_Colors;
|
static const std::vector<ColorRGBA> Travel_Colors;
|
||||||
static const std::vector<Color> Range_Colors;
|
static const std::vector<ColorRGBA> Range_Colors;
|
||||||
static const Color Wipe_Color;
|
static const ColorRGBA Wipe_Color;
|
||||||
static const Color Neutral_Color;
|
static const ColorRGBA Neutral_Color;
|
||||||
|
|
||||||
enum class EOptionsColors : unsigned char
|
enum class EOptionsColors : unsigned char
|
||||||
{
|
{
|
||||||
@ -121,7 +120,7 @@ class GCodeViewer
|
|||||||
// vbo id
|
// vbo id
|
||||||
unsigned int vbo{ 0 };
|
unsigned int vbo{ 0 };
|
||||||
// Color to apply to the instances
|
// Color to apply to the instances
|
||||||
Color color;
|
ColorRGBA color;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Range> ranges;
|
std::vector<Range> ranges;
|
||||||
@ -243,7 +242,7 @@ class GCodeViewer
|
|||||||
// Index of the parent tbuffer
|
// Index of the parent tbuffer
|
||||||
unsigned char tbuffer_id;
|
unsigned char tbuffer_id;
|
||||||
// Render path property
|
// Render path property
|
||||||
Color color;
|
ColorRGBA color;
|
||||||
// Index of the buffer in TBuffer::indices
|
// Index of the buffer in TBuffer::indices
|
||||||
unsigned int ibuffer_id;
|
unsigned int ibuffer_id;
|
||||||
// Render path content
|
// Render path content
|
||||||
@ -263,12 +262,10 @@ class GCodeViewer
|
|||||||
bool operator() (const RenderPath &l, const RenderPath &r) const {
|
bool operator() (const RenderPath &l, const RenderPath &r) const {
|
||||||
if (l.tbuffer_id < r.tbuffer_id)
|
if (l.tbuffer_id < r.tbuffer_id)
|
||||||
return true;
|
return true;
|
||||||
for (int i = 0; i < 3; ++i) {
|
if (l.color < r.color)
|
||||||
if (l.color[i] < r.color[i])
|
|
||||||
return true;
|
return true;
|
||||||
else if (l.color[i] > r.color[i])
|
else if (l.color > r.color)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return l.ibuffer_id < r.ibuffer_id;
|
return l.ibuffer_id < r.ibuffer_id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -299,7 +296,7 @@ class GCodeViewer
|
|||||||
struct Model
|
struct Model
|
||||||
{
|
{
|
||||||
GLModel model;
|
GLModel model;
|
||||||
Color color;
|
ColorRGBA color;
|
||||||
InstanceVBuffer instances;
|
InstanceVBuffer instances;
|
||||||
GLModel::InitializationData data;
|
GLModel::InitializationData data;
|
||||||
|
|
||||||
@ -384,6 +381,14 @@ class GCodeViewer
|
|||||||
{
|
{
|
||||||
struct Range
|
struct Range
|
||||||
{
|
{
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
enum class EType : unsigned char
|
||||||
|
{
|
||||||
|
Linear,
|
||||||
|
Logarithmic
|
||||||
|
};
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
|
||||||
float min;
|
float min;
|
||||||
float max;
|
float max;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
@ -398,8 +403,13 @@ class GCodeViewer
|
|||||||
}
|
}
|
||||||
void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; }
|
void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; }
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
float step_size(EType type = EType::Linear) const;
|
||||||
|
ColorRGBA get_color_at(float value, EType type = EType::Linear) const;
|
||||||
|
#else
|
||||||
float step_size() const { return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f); }
|
float step_size() const { return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f); }
|
||||||
Color get_color_at(float value) const;
|
ColorRGBA get_color_at(float value) const;
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ranges
|
struct Ranges
|
||||||
@ -416,6 +426,10 @@ class GCodeViewer
|
|||||||
Range volumetric_rate;
|
Range volumetric_rate;
|
||||||
// Color mapping by extrusion temperature.
|
// Color mapping by extrusion temperature.
|
||||||
Range temperature;
|
Range temperature;
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
// Color mapping by layer time.
|
||||||
|
std::array<Range, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> layer_time;
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
height.reset();
|
height.reset();
|
||||||
@ -424,6 +438,11 @@ class GCodeViewer
|
|||||||
fan_speed.reset();
|
fan_speed.reset();
|
||||||
volumetric_rate.reset();
|
volumetric_rate.reset();
|
||||||
temperature.reset();
|
temperature.reset();
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
for (auto& range : layer_time) {
|
||||||
|
range.reset();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -443,42 +462,43 @@ class GCodeViewer
|
|||||||
class Layers
|
class Layers
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Endpoints
|
struct Range
|
||||||
{
|
{
|
||||||
size_t first{ 0 };
|
size_t first{ 0 };
|
||||||
size_t last{ 0 };
|
size_t last{ 0 };
|
||||||
|
|
||||||
bool operator == (const Endpoints& other) const { return first == other.first && last == other.last; }
|
bool operator == (const Range& other) const { return first == other.first && last == other.last; }
|
||||||
bool operator != (const Endpoints& other) const { return !operator==(other); }
|
bool operator != (const Range& other) const { return !operator==(other); }
|
||||||
|
bool contains(size_t id) const { return first <= id && id <= last; }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<double> m_zs;
|
std::vector<double> m_zs;
|
||||||
std::vector<Endpoints> m_endpoints;
|
std::vector<Range> m_ranges;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void append(double z, Endpoints endpoints) {
|
void append(double z, const Range& range) {
|
||||||
m_zs.emplace_back(z);
|
m_zs.emplace_back(z);
|
||||||
m_endpoints.emplace_back(endpoints);
|
m_ranges.emplace_back(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
m_zs = std::vector<double>();
|
m_zs = std::vector<double>();
|
||||||
m_endpoints = std::vector<Endpoints>();
|
m_ranges = std::vector<Range>();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const { return m_zs.size(); }
|
size_t size() const { return m_zs.size(); }
|
||||||
bool empty() const { return m_zs.empty(); }
|
bool empty() const { return m_zs.empty(); }
|
||||||
const std::vector<double>& get_zs() const { return m_zs; }
|
const std::vector<double>& get_zs() const { return m_zs; }
|
||||||
const std::vector<Endpoints>& get_endpoints() const { return m_endpoints; }
|
const std::vector<Range>& get_ranges() const { return m_ranges; }
|
||||||
std::vector<Endpoints>& get_endpoints() { return m_endpoints; }
|
std::vector<Range>& get_ranges() { return m_ranges; }
|
||||||
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
|
double get_z_at(unsigned int id) const { return (id < m_zs.size()) ? m_zs[id] : 0.0; }
|
||||||
Endpoints get_endpoints_at(unsigned int id) const { return (id < m_endpoints.size()) ? m_endpoints[id] : Endpoints(); }
|
Range get_range_at(unsigned int id) const { return (id < m_ranges.size()) ? m_ranges[id] : Range(); }
|
||||||
|
|
||||||
bool operator != (const Layers& other) const {
|
bool operator != (const Layers& other) const {
|
||||||
if (m_zs != other.m_zs)
|
if (m_zs != other.m_zs)
|
||||||
return true;
|
return true;
|
||||||
if (m_endpoints != other.m_endpoints)
|
if (m_ranges != other.m_ranges)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -491,7 +511,7 @@ class GCodeViewer
|
|||||||
TBuffer* buffer{ nullptr };
|
TBuffer* buffer{ nullptr };
|
||||||
unsigned int ibo{ 0 };
|
unsigned int ibo{ 0 };
|
||||||
unsigned int vbo{ 0 };
|
unsigned int vbo{ 0 };
|
||||||
Color color;
|
ColorRGBA color;
|
||||||
|
|
||||||
~SequentialRangeCap();
|
~SequentialRangeCap();
|
||||||
bool is_renderable() const { return buffer != nullptr; }
|
bool is_renderable() const { return buffer != nullptr; }
|
||||||
@ -680,6 +700,10 @@ public:
|
|||||||
FanSpeed,
|
FanSpeed,
|
||||||
Temperature,
|
Temperature,
|
||||||
VolumetricRate,
|
VolumetricRate,
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
LayerTimeLinear,
|
||||||
|
LayerTimeLogarithmic,
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
Tool,
|
Tool,
|
||||||
ColorPrint,
|
ColorPrint,
|
||||||
Count
|
Count
|
||||||
@ -695,7 +719,7 @@ private:
|
|||||||
// bounding box of toolpaths + marker tools
|
// bounding box of toolpaths + marker tools
|
||||||
BoundingBoxf3 m_max_bounding_box;
|
BoundingBoxf3 m_max_bounding_box;
|
||||||
float m_max_print_height{ 0.0f };
|
float m_max_print_height{ 0.0f };
|
||||||
std::vector<Color> m_tool_colors;
|
std::vector<ColorRGBA> m_tool_colors;
|
||||||
Layers m_layers;
|
Layers m_layers;
|
||||||
std::array<unsigned int, 2> m_layers_z_range;
|
std::array<unsigned int, 2> m_layers_z_range;
|
||||||
std::vector<ExtrusionRole> m_roles;
|
std::vector<ExtrusionRole> m_roles;
|
||||||
@ -708,6 +732,14 @@ private:
|
|||||||
Shells m_shells;
|
Shells m_shells;
|
||||||
EViewType m_view_type{ EViewType::FeatureType };
|
EViewType m_view_type{ EViewType::FeatureType };
|
||||||
bool m_legend_enabled{ true };
|
bool m_legend_enabled{ true };
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
struct LegendResizer
|
||||||
|
{
|
||||||
|
bool dirty{ true };
|
||||||
|
void reset() { dirty = true; }
|
||||||
|
};
|
||||||
|
LegendResizer m_legend_resizer;
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
PrintEstimatedStatistics m_print_statistics;
|
PrintEstimatedStatistics m_print_statistics;
|
||||||
PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
|
PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
|
||||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
@ -716,6 +748,9 @@ private:
|
|||||||
std::array<float, 2> m_detected_point_sizes = { 0.0f, 0.0f };
|
std::array<float, 2> m_detected_point_sizes = { 0.0f, 0.0f };
|
||||||
GCodeProcessorResult::SettingsIds m_settings_ids;
|
GCodeProcessorResult::SettingsIds m_settings_ids;
|
||||||
std::array<SequentialRangeCap, 2> m_sequential_range_caps;
|
std::array<SequentialRangeCap, 2> m_sequential_range_caps;
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
std::array<std::vector<float>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> m_layers_times;
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
|
||||||
std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;
|
std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;
|
||||||
|
|
||||||
@ -731,7 +766,11 @@ public:
|
|||||||
void load(const GCodeProcessorResult& gcode_result, const Print& print, bool initialized);
|
void load(const GCodeProcessorResult& gcode_result, const Print& print, bool initialized);
|
||||||
// recalculate ranges in dependence of what is visible and sets tool/print colors
|
// recalculate ranges in dependence of what is visible and sets tool/print colors
|
||||||
void refresh(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
void refresh(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
||||||
|
#else
|
||||||
void refresh_render_paths();
|
void refresh_render_paths();
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
void update_shells_color_by_extruder(const DynamicPrintConfig* config);
|
void update_shells_color_by_extruder(const DynamicPrintConfig* config);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
@ -775,10 +814,16 @@ public:
|
|||||||
std::vector<CustomGCode::Item>& get_custom_gcode_per_print_z() { return m_custom_gcode_per_print_z; }
|
std::vector<CustomGCode::Item>& get_custom_gcode_per_print_z() { return m_custom_gcode_per_print_z; }
|
||||||
size_t get_extruders_count() { return m_extruders_count; }
|
size_t get_extruders_count() { return m_extruders_count; }
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
void invalidate_legend() { m_legend_resizer.reset(); }
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load_toolpaths(const GCodeProcessorResult& gcode_result);
|
void load_toolpaths(const GCodeProcessorResult& gcode_result);
|
||||||
void load_shells(const Print& print, bool initialized);
|
void load_shells(const Print& print, bool initialized);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
void render_toolpaths();
|
void render_toolpaths();
|
||||||
void render_shells();
|
void render_shells();
|
||||||
void render_legend(float& legend_height);
|
void render_legend(float& legend_height);
|
||||||
@ -790,7 +835,7 @@ private:
|
|||||||
}
|
}
|
||||||
bool is_visible(const Path& path) const { return is_visible(path.role); }
|
bool is_visible(const Path& path) const { return is_visible(path.role); }
|
||||||
void log_memory_used(const std::string& label, int64_t additional = 0) const;
|
void log_memory_used(const std::string& label, int64_t additional = 0) const;
|
||||||
Color option_color(EMoveType move_type) const;
|
ColorRGBA option_color(EMoveType move_type) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -72,11 +72,10 @@
|
|||||||
|
|
||||||
static constexpr const float TRACKBALLSIZE = 0.8f;
|
static constexpr const float TRACKBALLSIZE = 0.8f;
|
||||||
|
|
||||||
static constexpr const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
|
static const Slic3r::ColorRGB DEFAULT_BG_DARK_COLOR = { 0.478f, 0.478f, 0.478f };
|
||||||
static constexpr const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
|
static const Slic3r::ColorRGB DEFAULT_BG_LIGHT_COLOR = { 0.753f, 0.753f, 0.753f };
|
||||||
static constexpr const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f };
|
static const Slic3r::ColorRGB ERROR_BG_DARK_COLOR = { 0.478f, 0.192f, 0.039f };
|
||||||
static constexpr const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f };
|
static const Slic3r::ColorRGB ERROR_BG_LIGHT_COLOR = { 0.753f, 0.192f, 0.039f };
|
||||||
//static constexpr const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
|
|
||||||
|
|
||||||
// Number of floats
|
// Number of floats
|
||||||
static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
|
static constexpr const size_t MAX_VERTEX_BUFFER_SIZE = 131072 * 6; // 3.15MB
|
||||||
@ -849,8 +848,8 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons
|
|||||||
|
|
||||||
void GLCanvas3D::SequentialPrintClearance::render()
|
void GLCanvas3D::SequentialPrintClearance::render()
|
||||||
{
|
{
|
||||||
std::array<float, 4> FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
|
const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||||
std::array<float, 4> NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
|
const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
@ -2115,12 +2114,21 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
|
|||||||
request_extra_frame();
|
request_extra_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
void GLCanvas3D::refresh_gcode_preview_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last)
|
||||||
|
{
|
||||||
|
m_gcode_viewer.refresh_render_paths(keep_sequential_current_first, keep_sequential_current_last);
|
||||||
|
set_as_dirty();
|
||||||
|
request_extra_frame();
|
||||||
|
}
|
||||||
|
#else
|
||||||
void GLCanvas3D::refresh_gcode_preview_render_paths()
|
void GLCanvas3D::refresh_gcode_preview_render_paths()
|
||||||
{
|
{
|
||||||
m_gcode_viewer.refresh_render_paths();
|
m_gcode_viewer.refresh_render_paths();
|
||||||
set_as_dirty();
|
set_as_dirty();
|
||||||
request_extra_frame();
|
request_extra_frame();
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
void GLCanvas3D::load_sla_preview()
|
void GLCanvas3D::load_sla_preview()
|
||||||
{
|
{
|
||||||
@ -2427,9 +2435,13 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||||||
case 'L':
|
case 'L':
|
||||||
case 'l': {
|
case 'l': {
|
||||||
if (!m_main_toolbar.is_enabled()) {
|
if (!m_main_toolbar.is_enabled()) {
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
show_legend(!is_legend_shown());
|
||||||
|
#else
|
||||||
m_gcode_viewer.enable_legend(!m_gcode_viewer.is_legend_enabled());
|
m_gcode_viewer.enable_legend(!m_gcode_viewer.is_legend_enabled());
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
wxGetApp().plater()->update_preview_bottom_toolbar();
|
wxGetApp().plater()->update_preview_bottom_toolbar();
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3812,6 +3824,9 @@ void GLCanvas3D::set_cursor(ECursorType type)
|
|||||||
|
|
||||||
void GLCanvas3D::msw_rescale()
|
void GLCanvas3D::msw_rescale()
|
||||||
{
|
{
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
m_gcode_viewer.invalidate_legend();
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::update_tooltip_for_settings_item_in_main_toolbar()
|
void GLCanvas3D::update_tooltip_for_settings_item_in_main_toolbar()
|
||||||
@ -4041,8 +4056,11 @@ bool GLCanvas3D::_render_search_list(float pos_x)
|
|||||||
action_taken = true;
|
action_taken = true;
|
||||||
else
|
else
|
||||||
sidebar.jump_to_option(selected);*/
|
sidebar.jump_to_option(selected);*/
|
||||||
if (selected != 9999)
|
if (selected != 9999) {
|
||||||
|
imgui->end(); // end imgui before the jump to option
|
||||||
sidebar.jump_to_option(selected);
|
sidebar.jump_to_option(selected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
action_taken = true;
|
action_taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4156,9 +4174,6 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::array<float, 4> orange = { 0.923f, 0.504f, 0.264f, 1.0f };
|
|
||||||
static const std::array<float, 4> gray = { 0.64f, 0.64f, 0.64f, 1.0f };
|
|
||||||
|
|
||||||
GLVolumePtrs visible_volumes;
|
GLVolumePtrs visible_volumes;
|
||||||
|
|
||||||
for (GLVolume* vol : volumes.volumes) {
|
for (GLVolume* vol : volumes.volumes) {
|
||||||
@ -4213,7 +4228,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||||||
shader->set_uniform("emission_factor", 0.0f);
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
|
|
||||||
for (GLVolume* vol : visible_volumes) {
|
for (GLVolume* vol : visible_volumes) {
|
||||||
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? (current_printer_technology() == ptSLA ? vol->color : orange) : gray);
|
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? (current_printer_technology() == ptSLA ? vol->color : ColorRGBA::ORANGE()) : ColorRGBA::GRAY());
|
||||||
// the volume may have been deactivated by an active gizmo
|
// the volume may have been deactivated by an active gizmo
|
||||||
bool is_active = vol->is_active;
|
bool is_active = vol->is_active;
|
||||||
vol->is_active = true;
|
vol->is_active = true;
|
||||||
@ -4944,19 +4959,20 @@ void GLCanvas3D::_picking_pass()
|
|||||||
int volume_id = -1;
|
int volume_id = -1;
|
||||||
int gizmo_id = -1;
|
int gizmo_id = -1;
|
||||||
|
|
||||||
GLubyte color[4] = { 0, 0, 0, 0 };
|
std::array<GLubyte, 4> color = { 0, 0, 0, 0 };
|
||||||
const Size& cnv_size = get_canvas_size();
|
const Size& cnv_size = get_canvas_size();
|
||||||
bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height();
|
bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height();
|
||||||
if (inside) {
|
if (inside) {
|
||||||
glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color));
|
glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position.y() - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color.data()));
|
||||||
if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) {
|
if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) {
|
||||||
// Only non-interpolated colors are valid, those have their lowest three bits zeroed.
|
// Only non-interpolated colors are valid, those have their lowest three bits zeroed.
|
||||||
// we reserve color = (0,0,0) for occluders (as the printbed)
|
// we reserve color = (0,0,0) for occluders (as the printbed)
|
||||||
// volumes' id are shifted by 1
|
// volumes' id are shifted by 1
|
||||||
// see: _render_volumes_for_picking()
|
// see: _render_volumes_for_picking()
|
||||||
volume_id = color[0] + (color[1] << 8) + (color[2] << 16) - 1;
|
unsigned int id = picking_encode(color[0], color[1], color[2]);
|
||||||
|
volume_id = id - 1;
|
||||||
// gizmos' id are instead properly encoded by the color
|
// gizmos' id are instead properly encoded by the color
|
||||||
gizmo_id = color[0] + (color[1] << 8) + (color[2] << 16);
|
gizmo_id = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) {
|
if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) {
|
||||||
@ -5072,19 +5088,11 @@ void GLCanvas3D::_render_background() const
|
|||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
::glBegin(GL_QUADS);
|
::glBegin(GL_QUADS);
|
||||||
if (use_error_color)
|
::glColor3fv(use_error_color ? ERROR_BG_DARK_COLOR.data(): DEFAULT_BG_DARK_COLOR.data());
|
||||||
::glColor3fv(ERROR_BG_DARK_COLOR);
|
|
||||||
else
|
|
||||||
::glColor3fv(DEFAULT_BG_DARK_COLOR);
|
|
||||||
|
|
||||||
::glVertex2f(-1.0f, -1.0f);
|
::glVertex2f(-1.0f, -1.0f);
|
||||||
::glVertex2f(1.0f, -1.0f);
|
::glVertex2f(1.0f, -1.0f);
|
||||||
|
|
||||||
if (use_error_color)
|
::glColor3fv(use_error_color ? ERROR_BG_LIGHT_COLOR.data() : DEFAULT_BG_LIGHT_COLOR.data());
|
||||||
::glColor3fv(ERROR_BG_LIGHT_COLOR);
|
|
||||||
else
|
|
||||||
::glColor3fv(DEFAULT_BG_LIGHT_COLOR);
|
|
||||||
|
|
||||||
::glVertex2f(1.0f, 1.0f);
|
::glVertex2f(1.0f, 1.0f);
|
||||||
::glVertex2f(-1.0f, 1.0f);
|
::glVertex2f(-1.0f, 1.0f);
|
||||||
glsafe(::glEnd());
|
glsafe(::glEnd());
|
||||||
@ -5367,8 +5375,6 @@ void GLCanvas3D::_render_overlays()
|
|||||||
|
|
||||||
void GLCanvas3D::_render_volumes_for_picking() const
|
void GLCanvas3D::_render_volumes_for_picking() const
|
||||||
{
|
{
|
||||||
static const GLfloat INV_255 = 1.0f / 255.0f;
|
|
||||||
|
|
||||||
// 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));
|
||||||
|
|
||||||
@ -5383,12 +5389,8 @@ void GLCanvas3D::_render_volumes_for_picking() const
|
|||||||
// 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.
|
||||||
// we reserve color = (0,0,0) for occluders (as the printbed)
|
// we reserve color = (0,0,0) for occluders (as the printbed)
|
||||||
// so we shift volumes' id by 1 to get the proper color
|
// so we shift volumes' id by 1 to get the proper color
|
||||||
unsigned int id = 1 + volume.second.first;
|
const unsigned int id = 1 + volume.second.first;
|
||||||
unsigned int r = (id & (0x000000FF << 0)) << 0;
|
glsafe(::glColor4fv(picking_decode(id).data()));
|
||||||
unsigned int g = (id & (0x000000FF << 8)) >> 8;
|
|
||||||
unsigned int b = (id & (0x000000FF << 16)) >> 16;
|
|
||||||
unsigned int a = picking_checksum_alpha_channel(r, g, b);
|
|
||||||
glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255));
|
|
||||||
volume.first->render();
|
volume.first->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5815,7 +5817,7 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume)
|
|||||||
if (!print->has_skirt() && !print->has_brim())
|
if (!print->has_skirt() && !print->has_brim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::array<float, 4> color = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish
|
const ColorRGBA color = ColorRGBA::GREENISH();
|
||||||
|
|
||||||
// number of skirt layers
|
// number of skirt layers
|
||||||
size_t total_layer_count = 0;
|
size_t total_layer_count = 0;
|
||||||
@ -5862,7 +5864,8 @@ void GLCanvas3D::_load_print_toolpaths(const BuildVolume &build_volume)
|
|||||||
|
|
||||||
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const BuildVolume& build_volume, const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values)
|
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const BuildVolume& build_volume, const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values)
|
||||||
{
|
{
|
||||||
std::vector<std::array<float, 4>> tool_colors = _parse_colors(str_tool_colors);
|
std::vector<ColorRGBA> tool_colors;
|
||||||
|
decode_colors(str_tool_colors, tool_colors);
|
||||||
|
|
||||||
struct Ctxt
|
struct Ctxt
|
||||||
{
|
{
|
||||||
@ -5871,20 +5874,20 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
|||||||
bool has_perimeters;
|
bool has_perimeters;
|
||||||
bool has_infill;
|
bool has_infill;
|
||||||
bool has_support;
|
bool has_support;
|
||||||
const std::vector<std::array<float, 4>>* tool_colors;
|
const std::vector<ColorRGBA>* tool_colors;
|
||||||
bool is_single_material_print;
|
bool is_single_material_print;
|
||||||
int extruders_cnt;
|
int extruders_cnt;
|
||||||
const std::vector<CustomGCode::Item>* color_print_values;
|
const std::vector<CustomGCode::Item>* color_print_values;
|
||||||
|
|
||||||
static const std::array<float, 4>& color_perimeters() { static std::array<float, 4> color = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
static ColorRGBA color_perimeters() { return ColorRGBA::YELLOW(); }
|
||||||
static const std::array<float, 4>& color_infill() { static std::array<float, 4> color = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
static ColorRGBA color_infill() { return ColorRGBA::REDISH(); }
|
||||||
static const std::array<float, 4>& color_support() { static std::array<float, 4> color = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
static ColorRGBA color_support() { return ColorRGBA::GREENISH(); }
|
||||||
static const std::array<float, 4>& color_pause_or_custom_code() { static std::array<float, 4> color = { 0.5f, 0.5f, 0.5f, 1.f }; return color; } // gray
|
static ColorRGBA color_pause_or_custom_code() { return ColorRGBA::GRAY(); }
|
||||||
|
|
||||||
// For cloring by a tool, return a parsed color.
|
// For cloring by a tool, return a parsed color.
|
||||||
bool color_by_tool() const { return tool_colors != nullptr; }
|
bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
size_t number_tools() const { return color_by_tool() ? tool_colors->size() : 0; }
|
size_t number_tools() const { return color_by_tool() ? tool_colors->size() : 0; }
|
||||||
const std::array<float, 4>& color_tool(size_t tool) const { return (*tool_colors)[tool]; }
|
const ColorRGBA& color_tool(size_t tool) const { return (*tool_colors)[tool]; }
|
||||||
|
|
||||||
// For coloring by a color_print(M600), return a parsed color.
|
// For coloring by a color_print(M600), return a parsed color.
|
||||||
bool color_by_color_print() const { return color_print_values!=nullptr; }
|
bool color_by_color_print() const { return color_print_values!=nullptr; }
|
||||||
@ -6024,7 +6027,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
|||||||
//FIXME Improve the heuristics for a grain size.
|
//FIXME Improve the heuristics for a grain size.
|
||||||
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
||||||
tbb::spin_mutex new_volume_mutex;
|
tbb::spin_mutex new_volume_mutex;
|
||||||
auto new_volume = [this, &new_volume_mutex](const std::array<float, 4>& color) {
|
auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) {
|
||||||
// Allocate the volume before locking.
|
// Allocate the volume before locking.
|
||||||
GLVolume *volume = new GLVolume(color);
|
GLVolume *volume = new GLVolume(color);
|
||||||
volume->is_extrusion_path = true;
|
volume->is_extrusion_path = true;
|
||||||
@ -6165,21 +6168,22 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
|||||||
if (!print->is_step_done(psWipeTower))
|
if (!print->is_step_done(psWipeTower))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<std::array<float, 4>> tool_colors = _parse_colors(str_tool_colors);
|
std::vector<ColorRGBA> tool_colors;
|
||||||
|
decode_colors(str_tool_colors, tool_colors);
|
||||||
|
|
||||||
struct Ctxt
|
struct Ctxt
|
||||||
{
|
{
|
||||||
const Print *print;
|
const Print *print;
|
||||||
const std::vector<std::array<float, 4>>* tool_colors;
|
const std::vector<ColorRGBA>* tool_colors;
|
||||||
Vec2f wipe_tower_pos;
|
Vec2f wipe_tower_pos;
|
||||||
float wipe_tower_angle;
|
float wipe_tower_angle;
|
||||||
|
|
||||||
static const std::array<float, 4>& color_support() { static std::array<float, 4> color = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
static ColorRGBA color_support() { return ColorRGBA::GREENISH(); }
|
||||||
|
|
||||||
// For cloring by a tool, return a parsed color.
|
// For cloring by a tool, return a parsed color.
|
||||||
bool color_by_tool() const { return tool_colors != nullptr; }
|
bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() : 0; }
|
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() : 0; }
|
||||||
const std::array<float, 4>& color_tool(size_t tool) const { return (*tool_colors)[tool]; }
|
const ColorRGBA& color_tool(size_t tool) const { return (*tool_colors)[tool]; }
|
||||||
int volume_idx(int tool, int feature) const {
|
int volume_idx(int tool, int feature) const {
|
||||||
return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature;
|
return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature;
|
||||||
}
|
}
|
||||||
@ -6211,7 +6215,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const BuildVolume& build_volume, con
|
|||||||
size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||||
size_t grain_size = std::max(n_items / 128, size_t(1));
|
size_t grain_size = std::max(n_items / 128, size_t(1));
|
||||||
tbb::spin_mutex new_volume_mutex;
|
tbb::spin_mutex new_volume_mutex;
|
||||||
auto new_volume = [this, &new_volume_mutex](const std::array<float, 4>& color) {
|
auto new_volume = [this, &new_volume_mutex](const ColorRGBA& color) {
|
||||||
auto *volume = new GLVolume(color);
|
auto *volume = new GLVolume(color);
|
||||||
volume->is_extrusion_path = true;
|
volume->is_extrusion_path = true;
|
||||||
tbb::spin_mutex::scoped_lock lock;
|
tbb::spin_mutex::scoped_lock lock;
|
||||||
@ -6330,7 +6334,7 @@ void GLCanvas3D::_load_sla_shells()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance,
|
auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance,
|
||||||
const TriangleMesh& mesh, const std::array<float, 4>& color, bool outside_printer_detection_enabled) {
|
const TriangleMesh& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) {
|
||||||
m_volumes.volumes.emplace_back(new GLVolume(color));
|
m_volumes.volumes.emplace_back(new GLVolume(color));
|
||||||
GLVolume& v = *m_volumes.volumes.back();
|
GLVolume& v = *m_volumes.volumes.back();
|
||||||
#if ENABLE_SMOOTH_NORMALS
|
#if ENABLE_SMOOTH_NORMALS
|
||||||
@ -6392,28 +6396,6 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
|
|||||||
_set_warning_notification(warning, show);
|
_set_warning_notification(warning, show);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::array<float, 4>> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
|
|
||||||
{
|
|
||||||
static const float INV_255 = 1.0f / 255.0f;
|
|
||||||
|
|
||||||
std::vector<std::array<float, 4>> output(colors.size(), { 1.0f, 1.0f, 1.0f, 1.0f });
|
|
||||||
for (size_t i = 0; i < colors.size(); ++i) {
|
|
||||||
const std::string& color = colors[i];
|
|
||||||
const char* c = color.data() + 1;
|
|
||||||
if (color.size() == 7 && color.front() == '#') {
|
|
||||||
for (size_t j = 0; j < 3; ++j) {
|
|
||||||
int digit1 = hex_digit_to_int(*c++);
|
|
||||||
int digit2 = hex_digit_to_int(*c++);
|
|
||||||
if (digit1 == -1 || digit2 == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
output[i][j] = float(digit1 * 16 + digit2) * INV_255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
|
void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
|
||||||
{
|
{
|
||||||
enum ErrorType{
|
enum ErrorType{
|
||||||
|
@ -731,7 +731,11 @@ public:
|
|||||||
void reload_scene(bool refresh_immediately, bool force_full_scene_refresh = false);
|
void reload_scene(bool refresh_immediately, bool force_full_scene_refresh = false);
|
||||||
|
|
||||||
void load_gcode_preview(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
void load_gcode_preview(const GCodeProcessorResult& gcode_result, const std::vector<std::string>& str_tool_colors);
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
void refresh_gcode_preview_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last);
|
||||||
|
#else
|
||||||
void refresh_gcode_preview_render_paths();
|
void refresh_gcode_preview_render_paths();
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); }
|
void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); }
|
||||||
GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); }
|
GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); }
|
||||||
void load_sla_preview();
|
void load_sla_preview();
|
||||||
@ -824,6 +828,11 @@ public:
|
|||||||
bool are_labels_shown() const { return m_labels.is_shown(); }
|
bool are_labels_shown() const { return m_labels.is_shown(); }
|
||||||
void show_labels(bool show) { m_labels.show(show); }
|
void show_labels(bool show) { m_labels.show(show); }
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
bool is_legend_shown() const { return m_gcode_viewer.is_legend_enabled(); }
|
||||||
|
void show_legend(bool show) { m_gcode_viewer.enable_legend(show); m_dirty = true; }
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
bool is_using_slope() const { return m_slope.is_used(); }
|
bool is_using_slope() const { return m_slope.is_used(); }
|
||||||
void use_slope(bool use) { m_slope.use(use); }
|
void use_slope(bool use) { m_slope.use(use); }
|
||||||
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }
|
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }
|
||||||
@ -981,8 +990,6 @@ private:
|
|||||||
bool _deactivate_arrange_menu();
|
bool _deactivate_arrange_menu();
|
||||||
|
|
||||||
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }
|
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }
|
||||||
|
|
||||||
static std::vector<std::array<float, 4>> _parse_colors(const std::vector<std::string>& colors);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -165,7 +165,7 @@ bool GLModel::init_from_file(const std::string& filename)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLModel::set_color(int entity_id, const std::array<float, 4>& color)
|
void GLModel::set_color(int entity_id, const ColorRGBA& color)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_render_data.size(); ++i) {
|
for (size_t i = 0; i < m_render_data.size(); ++i) {
|
||||||
if (entity_id == -1 || static_cast<int>(i) == entity_id)
|
if (entity_id == -1 || static_cast<int>(i) == entity_id)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ namespace GUI {
|
|||||||
unsigned int vbo_id{ 0 };
|
unsigned int vbo_id{ 0 };
|
||||||
unsigned int ibo_id{ 0 };
|
unsigned int ibo_id{ 0 };
|
||||||
size_t indices_count{ 0 };
|
size_t indices_count{ 0 };
|
||||||
std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
ColorRGBA color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InitializationData
|
struct InitializationData
|
||||||
@ -44,7 +45,7 @@ namespace GUI {
|
|||||||
std::vector<Vec3f> positions;
|
std::vector<Vec3f> positions;
|
||||||
std::vector<Vec3f> normals;
|
std::vector<Vec3f> normals;
|
||||||
std::vector<unsigned int> indices;
|
std::vector<unsigned int> indices;
|
||||||
std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
ColorRGBA color;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Entity> entities;
|
std::vector<Entity> entities;
|
||||||
@ -74,7 +75,7 @@ namespace GUI {
|
|||||||
bool init_from_file(const std::string& filename);
|
bool init_from_file(const std::string& filename);
|
||||||
|
|
||||||
// if entity_id == -1 set the color of all entities
|
// if entity_id == -1 set the color of all entities
|
||||||
void set_color(int entity_id, const std::array<float, 4>& color);
|
void set_color(int entity_id, const ColorRGBA& color);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void render() const;
|
void render() const;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/format.hpp"
|
#include "libslic3r/format.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
#include <boost/nowide/fstream.hpp>
|
#include <boost/nowide/fstream.hpp>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@ -206,154 +207,114 @@ void GLShaderProgram::stop_using() const
|
|||||||
glsafe(::glUseProgram(0));
|
glsafe(::glUseProgram(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, int value) const
|
void GLShaderProgram::set_uniform(int id, int value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
glsafe(::glUniform1i(id, value));
|
||||||
glsafe(::glUniform1i(id, static_cast<GLint>(value)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, bool value) const
|
void GLShaderProgram::set_uniform(int id, bool value) const
|
||||||
{
|
{
|
||||||
return set_uniform(name, value ? 1 : 0);
|
set_uniform(id, value ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, float value) const
|
void GLShaderProgram::set_uniform(int id, float value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
glsafe(::glUniform1f(id, value));
|
||||||
glsafe(::glUniform1f(id, static_cast<GLfloat>(value)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, double value) const
|
void GLShaderProgram::set_uniform(int id, double value) const
|
||||||
{
|
{
|
||||||
return set_uniform(name, static_cast<float>(value));
|
set_uniform(id, static_cast<float>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<int, 2>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<int, 2>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform2iv(id, 1, static_cast<const GLint*>(value.data())));
|
glsafe(::glUniform2iv(id, 1, static_cast<const GLint*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<int, 3>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<int, 3>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform3iv(id, 1, static_cast<const GLint*>(value.data())));
|
glsafe(::glUniform3iv(id, 1, static_cast<const GLint*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<int, 4>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<int, 4>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform4iv(id, 1, static_cast<const GLint*>(value.data())));
|
glsafe(::glUniform4iv(id, 1, static_cast<const GLint*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<float, 2>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<float, 2>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform2fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
glsafe(::glUniform2fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<float, 3>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<float, 3>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const std::array<float, 4>& value) const
|
void GLShaderProgram::set_uniform(int id, const std::array<float, 4>& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform4fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
glsafe(::glUniform4fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const float* value, size_t size) const
|
void GLShaderProgram::set_uniform(int id, const float* value, size_t size) const
|
||||||
{
|
{
|
||||||
if (size == 1)
|
|
||||||
return set_uniform(name, value[0]);
|
|
||||||
else if (size < 5) {
|
|
||||||
int id = get_uniform_location(name);
|
|
||||||
if (id >= 0) {
|
if (id >= 0) {
|
||||||
if (size == 2)
|
if (size == 1)
|
||||||
|
set_uniform(id, value[0]);
|
||||||
|
else if (size == 2)
|
||||||
glsafe(::glUniform2fv(id, 1, static_cast<const GLfloat*>(value)));
|
glsafe(::glUniform2fv(id, 1, static_cast<const GLfloat*>(value)));
|
||||||
else if (size == 3)
|
else if (size == 3)
|
||||||
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value)));
|
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value)));
|
||||||
else
|
else if (size == 4)
|
||||||
glsafe(::glUniform4fv(id, 1, static_cast<const GLfloat*>(value)));
|
glsafe(::glUniform4fv(id, 1, static_cast<const GLfloat*>(value)));
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const Transform3f& value) const
|
void GLShaderProgram::set_uniform(int id, const Transform3f& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniformMatrix4fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.matrix().data())));
|
glsafe(::glUniformMatrix4fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.matrix().data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const Transform3d& value) const
|
void GLShaderProgram::set_uniform(int id, const Transform3d& value) const
|
||||||
{
|
{
|
||||||
return set_uniform(name, value.cast<float>());
|
set_uniform(id, value.cast<float>());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const Matrix3f& value) const
|
void GLShaderProgram::set_uniform(int id, const Matrix3f& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniformMatrix3fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.data())));
|
glsafe(::glUniformMatrix3fv(id, 1, GL_FALSE, static_cast<const GLfloat*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const Vec3f& value) const
|
void GLShaderProgram::set_uniform(int id, const Vec3f& value) const
|
||||||
{
|
{
|
||||||
int id = get_uniform_location(name);
|
if (id >= 0)
|
||||||
if (id >= 0) {
|
|
||||||
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
glsafe(::glUniform3fv(id, 1, static_cast<const GLfloat*>(value.data())));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLShaderProgram::set_uniform(const char* name, const Vec3d& value) const
|
void GLShaderProgram::set_uniform(int id, const Vec3d& value) const
|
||||||
{
|
{
|
||||||
return set_uniform(name, static_cast<Vec3f>(value.cast<float>()));
|
set_uniform(id, static_cast<Vec3f>(value.cast<float>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShaderProgram::set_uniform(int id, const ColorRGB& value) const
|
||||||
|
{
|
||||||
|
set_uniform(id, value.data(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLShaderProgram::set_uniform(int id, const ColorRGBA& value) const
|
||||||
|
{
|
||||||
|
set_uniform(id, value.data(), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLShaderProgram::get_attrib_location(const char* name) const
|
int GLShaderProgram::get_attrib_location(const char* name) const
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class ColorRGB;
|
||||||
|
class ColorRGBA;
|
||||||
|
|
||||||
class GLShaderProgram
|
class GLShaderProgram
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -44,22 +47,43 @@ public:
|
|||||||
void start_using() const;
|
void start_using() const;
|
||||||
void stop_using() const;
|
void stop_using() const;
|
||||||
|
|
||||||
bool set_uniform(const char* name, int value) const;
|
void set_uniform(const char* name, int value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, bool value) const;
|
void set_uniform(const char* name, bool value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, float value) const;
|
void set_uniform(const char* name, float value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, double value) const;
|
void set_uniform(const char* name, double value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<int, 2>& value) const;
|
void set_uniform(const char* name, const std::array<int, 2>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<int, 3>& value) const;
|
void set_uniform(const char* name, const std::array<int, 3>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<int, 4>& value) const;
|
void set_uniform(const char* name, const std::array<int, 4>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<float, 2>& value) const;
|
void set_uniform(const char* name, const std::array<float, 2>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<float, 3>& value) const;
|
void set_uniform(const char* name, const std::array<float, 3>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const std::array<float, 4>& value) const;
|
void set_uniform(const char* name, const std::array<float, 4>& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const float* value, size_t size) const;
|
void set_uniform(const char* name, const float* value, size_t size) const { set_uniform(get_uniform_location(name), value, size); }
|
||||||
bool set_uniform(const char* name, const Transform3f& value) const;
|
void set_uniform(const char* name, const Transform3f& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const Transform3d& value) const;
|
void set_uniform(const char* name, const Transform3d& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const Matrix3f& value) const;
|
void set_uniform(const char* name, const Matrix3f& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const Vec3f& value) const;
|
void set_uniform(const char* name, const Vec3f& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
bool set_uniform(const char* name, const Vec3d& value) const;
|
void set_uniform(const char* name, const Vec3d& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
|
void set_uniform(const char* name, const ColorRGB& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
|
void set_uniform(const char* name, const ColorRGBA& value) const { set_uniform(get_uniform_location(name), value); }
|
||||||
|
|
||||||
|
void set_uniform(int id, int value) const;
|
||||||
|
void set_uniform(int id, bool value) const;
|
||||||
|
void set_uniform(int id, float value) const;
|
||||||
|
void set_uniform(int id, double value) const;
|
||||||
|
void set_uniform(int id, const std::array<int, 2>& value) const;
|
||||||
|
void set_uniform(int id, const std::array<int, 3>& value) const;
|
||||||
|
void set_uniform(int id, const std::array<int, 4>& value) const;
|
||||||
|
void set_uniform(int id, const std::array<float, 2>& value) const;
|
||||||
|
void set_uniform(int id, const std::array<float, 3>& value) const;
|
||||||
|
void set_uniform(int id, const std::array<float, 4>& value) const;
|
||||||
|
void set_uniform(int id, const float* value, size_t size) const;
|
||||||
|
void set_uniform(int id, const Transform3f& value) const;
|
||||||
|
void set_uniform(int id, const Transform3d& value) const;
|
||||||
|
void set_uniform(int id, const Matrix3f& value) const;
|
||||||
|
void set_uniform(int id, const Vec3f& value) const;
|
||||||
|
void set_uniform(int id, const Vec3d& value) const;
|
||||||
|
void set_uniform(int id, const ColorRGB& value) const;
|
||||||
|
void set_uniform(int id, const ColorRGBA& value) const;
|
||||||
|
|
||||||
// returns -1 if not found
|
// returns -1 if not found
|
||||||
int get_attrib_location(const char* name) const;
|
int get_attrib_location(const char* name) const;
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/I18N.hpp"
|
#include "libslic3r/I18N.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_Utils.hpp"
|
#include "GUI_Utils.hpp"
|
||||||
@ -1580,8 +1581,7 @@ void GUI_App::set_label_clr_modified(const wxColour& clr)
|
|||||||
if (m_color_label_modified == clr)
|
if (m_color_label_modified == clr)
|
||||||
return;
|
return;
|
||||||
m_color_label_modified = clr;
|
m_color_label_modified = clr;
|
||||||
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue());
|
const std::string str = encode_color(ColorRGB(clr.Red(), clr.Green(), clr.Blue()));
|
||||||
std::string str = clr_str.ToStdString();
|
|
||||||
app_config->set("label_clr_modified", str);
|
app_config->set("label_clr_modified", str);
|
||||||
app_config->save();
|
app_config->save();
|
||||||
}
|
}
|
||||||
@ -1591,8 +1591,7 @@ void GUI_App::set_label_clr_sys(const wxColour& clr)
|
|||||||
if (m_color_label_sys == clr)
|
if (m_color_label_sys == clr)
|
||||||
return;
|
return;
|
||||||
m_color_label_sys = clr;
|
m_color_label_sys = clr;
|
||||||
auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue());
|
const std::string str = encode_color(ColorRGB(clr.Red(), clr.Green(), clr.Blue()));
|
||||||
std::string str = clr_str.ToStdString();
|
|
||||||
app_config->set("label_clr_sys", str);
|
app_config->set("label_clr_sys", str);
|
||||||
app_config->save();
|
app_config->save();
|
||||||
}
|
}
|
||||||
@ -1796,6 +1795,7 @@ void GUI_App::update_ui_from_settings()
|
|||||||
m_force_colors_update = false;
|
m_force_colors_update = false;
|
||||||
mainframe->force_color_changed();
|
mainframe->force_color_changed();
|
||||||
mainframe->diff_dialog.force_color_changed();
|
mainframe->diff_dialog.force_color_changed();
|
||||||
|
mainframe->preferences_dialog->force_color_changed();
|
||||||
mainframe->printhost_queue_dlg()->force_color_changed();
|
mainframe->printhost_queue_dlg()->force_color_changed();
|
||||||
#ifdef _MSW_DARK_MODE
|
#ifdef _MSW_DARK_MODE
|
||||||
update_scrolls(mainframe);
|
update_scrolls(mainframe);
|
||||||
@ -2316,40 +2316,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||||||
break;
|
break;
|
||||||
case ConfigMenuPreferences:
|
case ConfigMenuPreferences:
|
||||||
{
|
{
|
||||||
bool app_layout_changed = false;
|
open_preferences();
|
||||||
{
|
|
||||||
// the dialog needs to be destroyed before the call to recreate_GUI()
|
|
||||||
// or sometimes the application crashes into wxDialogBase() destructor
|
|
||||||
// so we put it into an inner scope
|
|
||||||
PreferencesDialog dlg(mainframe);
|
|
||||||
dlg.ShowModal();
|
|
||||||
app_layout_changed = dlg.settings_layout_changed();
|
|
||||||
if (dlg.seq_top_layer_only_changed())
|
|
||||||
this->plater_->refresh_print();
|
|
||||||
|
|
||||||
if (dlg.recreate_GUI()) {
|
|
||||||
recreate_GUI(_L("Restart application") + dots);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (is_editor()) {
|
|
||||||
if (app_config->get("associate_3mf") == "1")
|
|
||||||
associate_3mf_files();
|
|
||||||
if (app_config->get("associate_stl") == "1")
|
|
||||||
associate_stl_files();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (app_config->get("associate_gcode") == "1")
|
|
||||||
associate_gcode_files();
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
}
|
|
||||||
if (app_layout_changed) {
|
|
||||||
// hide full main_sizer for mainFrame
|
|
||||||
mainframe->GetSizer()->Show(false);
|
|
||||||
mainframe->update_layout();
|
|
||||||
mainframe->select_tab(size_t(0));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ConfigMenuLanguage:
|
case ConfigMenuLanguage:
|
||||||
@ -2397,22 +2364,20 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||||||
menu->Append(local_menu, _L("&Configuration"));
|
menu->Append(local_menu, _L("&Configuration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option)
|
void GUI_App::open_preferences(const std::string& highlight_option /*= std::string()*/, const std::string& tab_name/*= std::string()*/)
|
||||||
{
|
{
|
||||||
bool app_layout_changed = false;
|
mainframe->preferences_dialog->show(highlight_option, tab_name);
|
||||||
{
|
|
||||||
// the dialog needs to be destroyed before the call to recreate_GUI()
|
if (mainframe->preferences_dialog->recreate_GUI())
|
||||||
// or sometimes the application crashes into wxDialogBase() destructor
|
recreate_GUI(_L("Restart application") + dots);
|
||||||
// so we put it into an inner scope
|
|
||||||
PreferencesDialog dlg(mainframe, open_on_tab, highlight_option);
|
|
||||||
dlg.ShowModal();
|
|
||||||
app_layout_changed = dlg.settings_layout_changed();
|
|
||||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||||
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
|
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
|
||||||
#else
|
#else
|
||||||
if (dlg.seq_top_layer_only_changed())
|
if (mainframe->preferences_dialog->seq_top_layer_only_changed())
|
||||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||||
this->plater_->refresh_print();
|
this->plater_->refresh_print();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (is_editor()) {
|
if (is_editor()) {
|
||||||
if (app_config->get("associate_3mf") == "1")
|
if (app_config->get("associate_3mf") == "1")
|
||||||
@ -2425,8 +2390,8 @@ void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_
|
|||||||
associate_gcode_files();
|
associate_gcode_files();
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
|
||||||
if (app_layout_changed) {
|
if (mainframe->preferences_dialog->settings_layout_changed()) {
|
||||||
// hide full main_sizer for mainFrame
|
// hide full main_sizer for mainFrame
|
||||||
mainframe->GetSizer()->Show(false);
|
mainframe->GetSizer()->Show(false);
|
||||||
mainframe->update_layout();
|
mainframe->update_layout();
|
||||||
|
@ -264,7 +264,7 @@ public:
|
|||||||
wxString current_language_code_safe() const;
|
wxString current_language_code_safe() const;
|
||||||
bool is_localized() const { return m_wxLocale->GetLocale() != "English"; }
|
bool is_localized() const { return m_wxLocale->GetLocale() != "English"; }
|
||||||
|
|
||||||
void open_preferences(size_t open_on_tab = 0, const std::string& highlight_option = std::string());
|
void open_preferences(const std::string& highlight_option = std::string(), const std::string& tab_name = std::string());
|
||||||
|
|
||||||
virtual bool OnExceptionInMainLoop() override;
|
virtual bool OnExceptionInMainLoop() override;
|
||||||
// Calls wxLaunchDefaultBrowser if user confirms in dialog.
|
// Calls wxLaunchDefaultBrowser if user confirms in dialog.
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "slic3r/GUI/format.hpp"
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "slic3r/GUI/MainFrame.hpp"
|
#include "slic3r/GUI/MainFrame.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
|
||||||
|
|
||||||
// To show a message box if GUI initialization ends up with an exception thrown.
|
// To show a message box if GUI initialization ends up with an exception thrown.
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
@ -208,6 +208,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
m_layers_slider_sizer = create_layers_slider_sizer();
|
m_layers_slider_sizer = create_layers_slider_sizer();
|
||||||
|
|
||||||
wxGetApp().UpdateDarkUI(m_bottom_toolbar_panel = new wxPanel(this));
|
wxGetApp().UpdateDarkUI(m_bottom_toolbar_panel = new wxPanel(this));
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
m_label_view_type = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("View"));
|
m_label_view_type = new wxStaticText(m_bottom_toolbar_panel, wxID_ANY, _L("View"));
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wxGetApp().UpdateDarkUI(m_choice_view_type = new BitmapComboBox(m_bottom_toolbar_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY));
|
wxGetApp().UpdateDarkUI(m_choice_view_type = new BitmapComboBox(m_bottom_toolbar_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY));
|
||||||
@ -221,6 +222,10 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
m_choice_view_type->Append(_L("Fan speed"));
|
m_choice_view_type->Append(_L("Fan speed"));
|
||||||
m_choice_view_type->Append(_L("Temperature"));
|
m_choice_view_type->Append(_L("Temperature"));
|
||||||
m_choice_view_type->Append(_L("Volumetric flow rate"));
|
m_choice_view_type->Append(_L("Volumetric flow rate"));
|
||||||
|
#if ENABLE_PREVIEW_LAYER_TIME
|
||||||
|
m_choice_view_type->Append(_L("Layer time (linear)"));
|
||||||
|
m_choice_view_type->Append(_L("Layer time (logarithmic)"));
|
||||||
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
m_choice_view_type->Append(_L("Tool"));
|
m_choice_view_type->Append(_L("Tool"));
|
||||||
m_choice_view_type->Append(_L("Color Print"));
|
m_choice_view_type->Append(_L("Color Print"));
|
||||||
m_choice_view_type->SetSelection(0);
|
m_choice_view_type->SetSelection(0);
|
||||||
@ -232,6 +237,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
#else
|
#else
|
||||||
long combo_style = wxCB_READONLY;
|
long combo_style = wxCB_READONLY;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_combochecklist_features = new wxComboCtrl();
|
m_combochecklist_features = new wxComboCtrl();
|
||||||
m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, combo_style);
|
m_combochecklist_features->Create(m_bottom_toolbar_panel, wxID_ANY, _L("Feature types"), wxDefaultPosition, wxDefaultSize, combo_style);
|
||||||
std::string feature_items = GUI::into_u8(
|
std::string feature_items = GUI::into_u8(
|
||||||
@ -270,6 +276,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
get_option_type_string(OptionType::Legend) + "|1"
|
get_option_type_string(OptionType::Legend) + "|1"
|
||||||
);
|
);
|
||||||
Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
|
Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
m_left_sizer = new wxBoxSizer(wxVERTICAL);
|
m_left_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
m_left_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
m_left_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
||||||
@ -281,6 +288,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView);
|
m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView);
|
||||||
|
|
||||||
wxBoxSizer* bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
bottom_toolbar_sizer->AddSpacer(5);
|
bottom_toolbar_sizer->AddSpacer(5);
|
||||||
bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
|
bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
|
||||||
bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 0);
|
bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||||
@ -292,6 +300,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
|
|||||||
bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
|
bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
|
||||||
bottom_toolbar_sizer->Hide(m_combochecklist_features);
|
bottom_toolbar_sizer->Hide(m_combochecklist_features);
|
||||||
bottom_toolbar_sizer->AddSpacer(5);
|
bottom_toolbar_sizer->AddSpacer(5);
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 0);
|
bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 0);
|
||||||
m_bottom_toolbar_panel->SetSizer(bottom_toolbar_sizer);
|
m_bottom_toolbar_panel->SetSizer(bottom_toolbar_sizer);
|
||||||
|
|
||||||
@ -353,7 +362,9 @@ void Preview::load_print(bool keep_z_range)
|
|||||||
else if (tech == ptSLA)
|
else if (tech == ptSLA)
|
||||||
load_print_as_sla();
|
load_print_as_sla();
|
||||||
|
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
update_bottom_toolbar();
|
update_bottom_toolbar();
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,10 +407,12 @@ void Preview::refresh_print()
|
|||||||
|
|
||||||
void Preview::msw_rescale()
|
void Preview::msw_rescale()
|
||||||
{
|
{
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_choice_view_type->Rescale();
|
m_choice_view_type->Rescale();
|
||||||
m_choice_view_type->SetMinSize(m_choice_view_type->GetSize());
|
m_choice_view_type->SetMinSize(m_choice_view_type->GetSize());
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
// rescale slider
|
// rescale slider
|
||||||
if (m_layers_slider != nullptr) m_layers_slider->msw_rescale();
|
if (m_layers_slider != nullptr) m_layers_slider->msw_rescale();
|
||||||
if (m_moves_slider != nullptr) m_moves_slider->msw_rescale();
|
if (m_moves_slider != nullptr) m_moves_slider->msw_rescale();
|
||||||
@ -417,11 +430,13 @@ void Preview::sys_color_changed()
|
|||||||
wxWindowUpdateLocker noUpdates(this);
|
wxWindowUpdateLocker noUpdates(this);
|
||||||
|
|
||||||
wxGetApp().UpdateAllStaticTextDarkUI(m_bottom_toolbar_panel);
|
wxGetApp().UpdateAllStaticTextDarkUI(m_bottom_toolbar_panel);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
wxGetApp().UpdateDarkUI(m_choice_view_type);
|
wxGetApp().UpdateDarkUI(m_choice_view_type);
|
||||||
wxGetApp().UpdateDarkUI(m_combochecklist_features);
|
wxGetApp().UpdateDarkUI(m_combochecklist_features);
|
||||||
wxGetApp().UpdateDarkUI(static_cast<wxCheckListBoxComboPopup*>(m_combochecklist_features->GetPopupControl()));
|
wxGetApp().UpdateDarkUI(static_cast<wxCheckListBoxComboPopup*>(m_combochecklist_features->GetPopupControl()));
|
||||||
wxGetApp().UpdateDarkUI(m_combochecklist_options);
|
wxGetApp().UpdateDarkUI(m_combochecklist_options);
|
||||||
wxGetApp().UpdateDarkUI(static_cast<wxCheckListBoxComboPopup*>(m_combochecklist_options->GetPopupControl()));
|
wxGetApp().UpdateDarkUI(static_cast<wxCheckListBoxComboPopup*>(m_combochecklist_options->GetPopupControl()));
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_layers_slider != nullptr)
|
if (m_layers_slider != nullptr)
|
||||||
@ -445,19 +460,23 @@ void Preview::edit_layers_slider(wxKeyEvent& evt)
|
|||||||
|
|
||||||
void Preview::bind_event_handlers()
|
void Preview::bind_event_handlers()
|
||||||
{
|
{
|
||||||
this->Bind(wxEVT_SIZE, &Preview::on_size, this);
|
Bind(wxEVT_SIZE, &Preview::on_size, this);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
m_choice_view_type->Bind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this);
|
m_choice_view_type->Bind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this);
|
||||||
m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
||||||
m_combochecklist_options->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
|
m_combochecklist_options->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
|
m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preview::unbind_event_handlers()
|
void Preview::unbind_event_handlers()
|
||||||
{
|
{
|
||||||
this->Unbind(wxEVT_SIZE, &Preview::on_size, this);
|
Unbind(wxEVT_SIZE, &Preview::on_size, this);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
m_choice_view_type->Unbind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this);
|
m_choice_view_type->Unbind(wxEVT_COMBOBOX, &Preview::on_choice_view_type, this);
|
||||||
m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
||||||
m_combochecklist_options->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
|
m_combochecklist_options->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_options, this);
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
|
m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,6 +497,7 @@ void Preview::on_size(wxSizeEvent& evt)
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
void Preview::on_choice_view_type(wxCommandEvent& evt)
|
void Preview::on_choice_view_type(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
int selection = m_choice_view_type->GetCurrentSelection();
|
int selection = m_choice_view_type->GetCurrentSelection();
|
||||||
@ -544,6 +564,7 @@ void Preview::update_bottom_toolbar()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
wxBoxSizer* Preview::create_layers_slider_sizer()
|
wxBoxSizer* Preview::create_layers_slider_sizer()
|
||||||
{
|
{
|
||||||
@ -953,10 +974,20 @@ void Preview::load_print_as_fff(bool keep_z_range)
|
|||||||
std::vector<Item> gcodes = wxGetApp().is_editor() ?
|
std::vector<Item> gcodes = wxGetApp().is_editor() ?
|
||||||
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes :
|
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes :
|
||||||
m_canvas->get_custom_gcode_per_print_z();
|
m_canvas->get_custom_gcode_per_print_z();
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
const GCodeViewer::EViewType choice = !gcodes.empty() ?
|
||||||
|
GCodeViewer::EViewType::ColorPrint :
|
||||||
|
(number_extruders > 1) ? GCodeViewer::EViewType::Tool : GCodeViewer::EViewType::FeatureType;
|
||||||
|
if (choice != gcode_view_type) {
|
||||||
|
m_canvas->set_gcode_view_preview_type(choice);
|
||||||
|
if (wxGetApp().is_gcode_viewer())
|
||||||
|
m_keep_current_preview_type = true;
|
||||||
|
refresh_print();
|
||||||
|
}
|
||||||
|
#else
|
||||||
const wxString choice = !gcodes.empty() ?
|
const wxString choice = !gcodes.empty() ?
|
||||||
_L("Color Print") :
|
_L("Color Print") :
|
||||||
(number_extruders > 1) ? _L("Tool") : _L("Feature type");
|
(number_extruders > 1) ? _L("Tool") : _L("Feature type");
|
||||||
|
|
||||||
int type = m_choice_view_type->FindString(choice);
|
int type = m_choice_view_type->FindString(choice);
|
||||||
if (m_choice_view_type->GetSelection() != type) {
|
if (m_choice_view_type->GetSelection() != type) {
|
||||||
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count)) {
|
if (0 <= type && type < static_cast<int>(GCodeViewer::EViewType::Count)) {
|
||||||
@ -967,6 +998,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
|
|||||||
refresh_print();
|
refresh_print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zs.empty()) {
|
if (zs.empty()) {
|
||||||
@ -1042,6 +1074,7 @@ void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event)
|
|||||||
m_canvas->render();
|
m_canvas->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
wxString Preview::get_option_type_string(OptionType type) const
|
wxString Preview::get_option_type_string(OptionType type) const
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -1061,6 +1094,7 @@ wxString Preview::get_option_type_string(OptionType type) const
|
|||||||
default: { return ""; }
|
default: { return ""; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -80,16 +80,18 @@ class Preview : public wxPanel
|
|||||||
wxBoxSizer* m_left_sizer { nullptr };
|
wxBoxSizer* m_left_sizer { nullptr };
|
||||||
wxBoxSizer* m_layers_slider_sizer { nullptr };
|
wxBoxSizer* m_layers_slider_sizer { nullptr };
|
||||||
wxPanel* m_bottom_toolbar_panel { nullptr };
|
wxPanel* m_bottom_toolbar_panel { nullptr };
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
wxStaticText* m_label_view_type { nullptr };
|
wxStaticText* m_label_view_type { nullptr };
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BitmapComboBox* m_choice_view_type { nullptr };
|
BitmapComboBox* m_choice_view_type { nullptr };
|
||||||
#else
|
#else
|
||||||
wxComboBox* m_choice_view_type { nullptr };
|
wxComboBox* m_choice_view_type { nullptr };
|
||||||
#endif
|
#endif
|
||||||
wxStaticText* m_label_show { nullptr };
|
wxStaticText* m_label_show{ nullptr };
|
||||||
wxComboCtrl* m_combochecklist_features { nullptr };
|
wxComboCtrl* m_combochecklist_features { nullptr };
|
||||||
size_t m_combochecklist_features_pos { 0 };
|
size_t m_combochecklist_features_pos { 0 };
|
||||||
wxComboCtrl* m_combochecklist_options { nullptr };
|
wxComboCtrl* m_combochecklist_options { nullptr };
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
DynamicPrintConfig* m_config;
|
DynamicPrintConfig* m_config;
|
||||||
BackgroundSlicingProcess* m_process;
|
BackgroundSlicingProcess* m_process;
|
||||||
@ -126,7 +128,9 @@ public:
|
|||||||
CustomGCodes,
|
CustomGCodes,
|
||||||
Shells,
|
Shells,
|
||||||
ToolMarker,
|
ToolMarker,
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
Legend
|
Legend
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
};
|
};
|
||||||
|
|
||||||
Preview(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
|
Preview(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
|
||||||
@ -154,12 +158,18 @@ public:
|
|||||||
|
|
||||||
bool is_loaded() const { return m_loaded; }
|
bool is_loaded() const { return m_loaded; }
|
||||||
|
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
void update_bottom_toolbar();
|
void update_bottom_toolbar();
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
void update_moves_slider();
|
void update_moves_slider();
|
||||||
void enable_moves_slider(bool enable);
|
void enable_moves_slider(bool enable);
|
||||||
void move_moves_slider(wxKeyEvent& evt);
|
void move_moves_slider(wxKeyEvent& evt);
|
||||||
void hide_layers_slider();
|
void hide_layers_slider();
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
void set_keep_current_preview_type(bool value) { m_keep_current_preview_type = value; }
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init(wxWindow* parent, Bed3D& bed, Model* model);
|
bool init(wxWindow* parent, Bed3D& bed, Model* model);
|
||||||
|
|
||||||
@ -167,9 +177,11 @@ private:
|
|||||||
void unbind_event_handlers();
|
void unbind_event_handlers();
|
||||||
|
|
||||||
void on_size(wxSizeEvent& evt);
|
void on_size(wxSizeEvent& evt);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
void on_choice_view_type(wxCommandEvent& evt);
|
void on_choice_view_type(wxCommandEvent& evt);
|
||||||
void on_combochecklist_features(wxCommandEvent& evt);
|
void on_combochecklist_features(wxCommandEvent& evt);
|
||||||
void on_combochecklist_options(wxCommandEvent& evt);
|
void on_combochecklist_options(wxCommandEvent& evt);
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
// Create/Update/Reset double slider on 3dPreview
|
// Create/Update/Reset double slider on 3dPreview
|
||||||
wxBoxSizer* create_layers_slider_sizer();
|
wxBoxSizer* create_layers_slider_sizer();
|
||||||
@ -186,7 +198,9 @@ private:
|
|||||||
|
|
||||||
void on_layers_slider_scroll_changed(wxCommandEvent& event);
|
void on_layers_slider_scroll_changed(wxCommandEvent& event);
|
||||||
void on_moves_slider_scroll_changed(wxCommandEvent& event);
|
void on_moves_slider_scroll_changed(wxCommandEvent& event);
|
||||||
|
#if !ENABLE_PREVIEW_LAYOUT
|
||||||
wxString get_option_type_string(OptionType type) const;
|
wxString get_option_type_string(OptionType type) const;
|
||||||
|
#endif // !ENABLE_PREVIEW_LAYOUT
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -406,14 +406,6 @@ public:
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);
|
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);
|
||||||
|
|
||||||
inline int hex_digit_to_int(const char c)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(c >= '0' && c <= '9') ? int(c - '0') :
|
|
||||||
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
|
|
||||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TaskTimer
|
class TaskTimer
|
||||||
{
|
{
|
||||||
std::chrono::milliseconds start_timer;
|
std::chrono::milliseconds start_timer;
|
||||||
|
@ -25,15 +25,9 @@ GLGizmoBase::Grabber::Grabber()
|
|||||||
|
|
||||||
void GLGizmoBase::Grabber::render(bool hover, float size) const
|
void GLGizmoBase::Grabber::render(bool hover, float size) const
|
||||||
{
|
{
|
||||||
std::array<float, 4> render_color;
|
ColorRGBA render_color = color;
|
||||||
if (hover) {
|
if (hover)
|
||||||
render_color[0] = (1.0f - color[0]);
|
render_color = complementary(render_color);
|
||||||
render_color[1] = (1.0f - color[1]);
|
|
||||||
render_color[2] = (1.0f - color[2]);
|
|
||||||
render_color[3] = color[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
render_color = color;
|
|
||||||
|
|
||||||
render(size, render_color, false);
|
render(size, render_color, false);
|
||||||
}
|
}
|
||||||
@ -48,15 +42,14 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
|
|||||||
return get_half_size(size) * DraggingScaleFactor;
|
return get_half_size(size) * DraggingScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoBase::Grabber::render(float size, const std::array<float, 4>& render_color, bool picking) const
|
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) const
|
||||||
{
|
{
|
||||||
if (! cube_initialized) {
|
if (!cube.is_initialized()) {
|
||||||
// This cannot be done in constructor, OpenGL is not yet
|
// This cannot be done in constructor, OpenGL is not yet
|
||||||
// initialized at that point (on Linux at least).
|
// initialized at that point (on Linux at least).
|
||||||
indexed_triangle_set mesh = its_make_cube(1., 1., 1.);
|
indexed_triangle_set mesh = its_make_cube(1., 1., 1.);
|
||||||
its_translate(mesh, Vec3f(-0.5, -0.5, -0.5));
|
its_translate(mesh, Vec3f(-0.5, -0.5, -0.5));
|
||||||
const_cast<GLModel&>(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
|
const_cast<GLModel&>(cube).init_from(mesh, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
|
||||||
const_cast<bool&>(cube_initialized) = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size));
|
float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size));
|
||||||
@ -90,25 +83,16 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, u
|
|||||||
m_base_color = DEFAULT_BASE_COLOR;
|
m_base_color = DEFAULT_BASE_COLOR;
|
||||||
m_drag_color = DEFAULT_DRAG_COLOR;
|
m_drag_color = DEFAULT_DRAG_COLOR;
|
||||||
m_highlight_color = DEFAULT_HIGHLIGHT_COLOR;
|
m_highlight_color = DEFAULT_HIGHLIGHT_COLOR;
|
||||||
m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24));
|
|
||||||
m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.));
|
|
||||||
m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoBase::set_hover_id(int id)
|
void GLGizmoBase::set_hover_id(int id)
|
||||||
{
|
{
|
||||||
if (m_grabbers.empty() || (id < (int)m_grabbers.size()))
|
if (m_grabbers.empty() || id < (int)m_grabbers.size()) {
|
||||||
{
|
|
||||||
m_hover_id = id;
|
m_hover_id = id;
|
||||||
on_set_hover_id();
|
on_set_hover_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoBase::set_highlight_color(const std::array<float, 4>& color)
|
|
||||||
{
|
|
||||||
m_highlight_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoBase::enable_grabber(unsigned int id)
|
void GLGizmoBase::enable_grabber(unsigned int id)
|
||||||
{
|
{
|
||||||
if (id < m_grabbers.size())
|
if (id < m_grabbers.size())
|
||||||
@ -162,22 +146,13 @@ bool GLGizmoBase::update_items_state()
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<float, 4> GLGizmoBase::picking_color_component(unsigned int id) const
|
ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
|
||||||
{
|
{
|
||||||
static const float INV_255 = 1.0f / 255.0f;
|
|
||||||
|
|
||||||
id = BASE_ID - id;
|
id = BASE_ID - id;
|
||||||
|
|
||||||
if (m_group_id > -1)
|
if (m_group_id > -1)
|
||||||
id -= m_group_id;
|
id -= m_group_id;
|
||||||
|
|
||||||
// color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass()
|
return picking_decode(id);
|
||||||
return std::array<float, 4> {
|
|
||||||
float((id >> 0) & 0xff) * INV_255, // red
|
|
||||||
float((id >> 8) & 0xff) * INV_255, // green
|
|
||||||
float((id >> 16) & 0xff) * INV_255, // blue
|
|
||||||
float(picking_checksum_alpha_channel(id & 0xff, (id >> 8) & 0xff, (id >> 16) & 0xff))* INV_255 // checksum for validating against unwanted alpha blending and multi sampling
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
|
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
|
||||||
@ -205,8 +180,7 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) {
|
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) {
|
||||||
if (m_grabbers[i].enabled) {
|
if (m_grabbers[i].enabled) {
|
||||||
std::array<float, 4> color = picking_color_component(i);
|
m_grabbers[i].color = picking_color_component(i);
|
||||||
m_grabbers[i].color = color;
|
|
||||||
m_grabbers[i].render_for_picking(mean_size);
|
m_grabbers[i].render_for_picking(mean_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,22 +218,5 @@ std::string GLGizmoBase::get_name(bool include_shortcut) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
|
|
||||||
// were not interpolated by alpha blending or multi sampling.
|
|
||||||
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue)
|
|
||||||
{
|
|
||||||
// 8 bit hash for the color
|
|
||||||
unsigned char b = ((((37 * red) + green) & 0x0ff) * 37 + blue) & 0x0ff;
|
|
||||||
// Increase enthropy by a bit reversal
|
|
||||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
|
||||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
|
||||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
|
||||||
// Flip every second bit to increase the enthropy even more.
|
|
||||||
b ^= 0x55;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define slic3r_GLGizmoBase_hpp_
|
#define slic3r_GLGizmoBase_hpp_
|
||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
#include "slic3r/GUI/I18N.hpp"
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
#include "slic3r/GUI/GLModel.hpp"
|
#include "slic3r/GUI/GLModel.hpp"
|
||||||
@ -18,15 +19,11 @@ class ModelObject;
|
|||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
static const std::array<float, 4> DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f };
|
static const ColorRGBA DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f };
|
||||||
static const std::array<float, 4> DEFAULT_DRAG_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };
|
static const ColorRGBA DEFAULT_DRAG_COLOR = ColorRGBA::WHITE();
|
||||||
static const std::array<float, 4> DEFAULT_HIGHLIGHT_COLOR = { 1.0f, 0.38f, 0.0f, 1.0f };
|
static const ColorRGBA DEFAULT_HIGHLIGHT_COLOR = ColorRGBA::ORANGE();
|
||||||
static const std::array<std::array<float, 4>, 3> AXES_COLOR = {{
|
static const std::array<ColorRGBA, 3> AXES_COLOR = {{ ColorRGBA::X(), ColorRGBA::Y(), ColorRGBA::Z() }};
|
||||||
{ 0.75f, 0.0f, 0.0f, 1.0f },
|
static const ColorRGBA CONSTRAINED_COLOR = ColorRGBA::GRAY();
|
||||||
{ 0.0f, 0.75f, 0.0f, 1.0f },
|
|
||||||
{ 0.0f, 0.0f, 0.75f, 1.0f }
|
|
||||||
}};
|
|
||||||
static const std::array<float, 4> CONSTRAINED_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|
||||||
|
|
||||||
class ImGuiWrapper;
|
class ImGuiWrapper;
|
||||||
class GLCanvas3D;
|
class GLCanvas3D;
|
||||||
@ -50,7 +47,7 @@ protected:
|
|||||||
|
|
||||||
Vec3d center;
|
Vec3d center;
|
||||||
Vec3d angles;
|
Vec3d angles;
|
||||||
std::array<float, 4> color;
|
ColorRGBA color;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool dragging;
|
bool dragging;
|
||||||
|
|
||||||
@ -63,10 +60,9 @@ protected:
|
|||||||
float get_dragging_half_size(float size) const;
|
float get_dragging_half_size(float size) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void render(float size, const std::array<float, 4>& render_color, bool picking) const;
|
void render(float size, const ColorRGBA& render_color, bool picking) const;
|
||||||
|
|
||||||
GLModel cube;
|
GLModel cube;
|
||||||
bool cube_initialized = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -97,17 +93,14 @@ protected:
|
|||||||
unsigned int m_sprite_id;
|
unsigned int m_sprite_id;
|
||||||
int m_hover_id;
|
int m_hover_id;
|
||||||
bool m_dragging;
|
bool m_dragging;
|
||||||
std::array<float, 4> m_base_color;
|
ColorRGBA m_base_color;
|
||||||
std::array<float, 4> m_drag_color;
|
ColorRGBA m_drag_color;
|
||||||
std::array<float, 4> m_highlight_color;
|
ColorRGBA m_highlight_color;
|
||||||
mutable std::vector<Grabber> m_grabbers;
|
mutable std::vector<Grabber> m_grabbers;
|
||||||
ImGuiWrapper* m_imgui;
|
ImGuiWrapper* m_imgui;
|
||||||
bool m_first_input_window_render;
|
bool m_first_input_window_render;
|
||||||
mutable std::string m_tooltip;
|
mutable std::string m_tooltip;
|
||||||
CommonGizmosDataPool* m_c;
|
CommonGizmosDataPool* m_c;
|
||||||
GLModel m_cone;
|
|
||||||
GLModel m_cylinder;
|
|
||||||
GLModel m_sphere;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoBase(GLCanvas3D& parent,
|
GLGizmoBase(GLCanvas3D& parent,
|
||||||
@ -146,7 +139,7 @@ public:
|
|||||||
int get_hover_id() const { return m_hover_id; }
|
int get_hover_id() const { return m_hover_id; }
|
||||||
void set_hover_id(int id);
|
void set_hover_id(int id);
|
||||||
|
|
||||||
void set_highlight_color(const std::array<float, 4>& color);
|
void set_highlight_color(const ColorRGBA& color) { m_highlight_color = color; }
|
||||||
|
|
||||||
void enable_grabber(unsigned int id);
|
void enable_grabber(unsigned int id);
|
||||||
void disable_grabber(unsigned int id);
|
void disable_grabber(unsigned int id);
|
||||||
@ -188,7 +181,8 @@ protected:
|
|||||||
|
|
||||||
// Returns the picking color for the given id, based on the BASE_ID constant
|
// Returns the picking color for the given id, based on the BASE_ID constant
|
||||||
// No check is made for clashing with other picking color (i.e. GLVolumes)
|
// No check is made for clashing with other picking color (i.e. GLVolumes)
|
||||||
std::array<float, 4> picking_color_component(unsigned int id) const;
|
ColorRGBA picking_color_component(unsigned int id) const;
|
||||||
|
|
||||||
void render_grabbers(const BoundingBoxf3& box) const;
|
void render_grabbers(const BoundingBoxf3& box) const;
|
||||||
void render_grabbers(float size) const;
|
void render_grabbers(float size) const;
|
||||||
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
|
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
|
||||||
@ -203,10 +197,6 @@ private:
|
|||||||
bool m_dirty;
|
bool m_dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
|
|
||||||
// were not interpolated by alpha blending or multi sampling.
|
|
||||||
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ namespace GUI {
|
|||||||
|
|
||||||
const double GLGizmoCut::Offset = 10.0;
|
const double GLGizmoCut::Offset = 10.0;
|
||||||
const double GLGizmoCut::Margin = 20.0;
|
const double GLGizmoCut::Margin = 20.0;
|
||||||
const std::array<float, 4> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0, 1.0 };
|
static const ColorRGBA GRABBER_COLOR = ColorRGBA::ORANGE();
|
||||||
|
static const ColorRGBA PLANE_COLOR = { 0.8f, 0.8f, 0.8f, 0.5f };
|
||||||
|
|
||||||
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
@ -103,7 +104,7 @@ void GLGizmoCut::on_render()
|
|||||||
|
|
||||||
// Draw the cutting plane
|
// Draw the cutting plane
|
||||||
::glBegin(GL_QUADS);
|
::glBegin(GL_QUADS);
|
||||||
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
|
::glColor4fv(PLANE_COLOR.data());
|
||||||
::glVertex3f(min_x, min_y, plane_center.z());
|
::glVertex3f(min_x, min_y, plane_center.z());
|
||||||
::glVertex3f(max_x, min_y, plane_center.z());
|
::glVertex3f(max_x, min_y, plane_center.z());
|
||||||
::glVertex3f(max_x, max_y, plane_center.z());
|
::glVertex3f(max_x, max_y, plane_center.z());
|
||||||
@ -134,7 +135,7 @@ void GLGizmoCut::on_render()
|
|||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.1f);
|
shader->set_uniform("emission_factor", 0.1f);
|
||||||
|
|
||||||
m_grabbers[0].color = GrabberColor;
|
m_grabbers[0].color = GRABBER_COLOR;
|
||||||
m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0));
|
m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0));
|
||||||
|
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
@ -13,7 +13,6 @@ class GLGizmoCut : public GLGizmoBase
|
|||||||
{
|
{
|
||||||
static const double Offset;
|
static const double Offset;
|
||||||
static const double Margin;
|
static const double Margin;
|
||||||
static const std::array<float, 4> GrabberColor;
|
|
||||||
|
|
||||||
double m_cut_z{ 0.0 };
|
double m_cut_z{ 0.0 };
|
||||||
double m_max_z{ 0.0 };
|
double m_max_z{ 0.0 };
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
static const Slic3r::ColorRGBA DEFAULT_PLANE_COLOR = { 0.9f, 0.9f, 0.9f, 0.5f };
|
||||||
|
static const Slic3r::ColorRGBA DEFAULT_HOVER_PLANE_COLOR = { 0.9f, 0.9f, 0.9f, 0.75f };
|
||||||
|
|
||||||
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
@ -74,11 +76,7 @@ void GLGizmoFlatten::on_render()
|
|||||||
if (this->is_plane_update_necessary())
|
if (this->is_plane_update_necessary())
|
||||||
update_planes();
|
update_planes();
|
||||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||||
if (i == m_hover_id)
|
glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data()));
|
||||||
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.75f));
|
|
||||||
else
|
|
||||||
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f));
|
|
||||||
|
|
||||||
if (m_planes[i].vbo.has_VBOs())
|
if (m_planes[i].vbo.has_VBOs())
|
||||||
m_planes[i].vbo.render();
|
m_planes[i].vbo.render();
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ namespace GUI {
|
|||||||
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
{
|
{
|
||||||
m_vbo_cylinder.init_from(its_make_cylinder(1., 1.));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,6 +62,9 @@ void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&)
|
|||||||
|
|
||||||
void GLGizmoHollow::on_render()
|
void GLGizmoHollow::on_render()
|
||||||
{
|
{
|
||||||
|
if (!m_cylinder.is_initialized())
|
||||||
|
m_cylinder.init_from(its_make_cylinder(1.0, 1.0));
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info();
|
const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info();
|
||||||
|
|
||||||
@ -114,7 +116,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift()));
|
glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift()));
|
||||||
glsafe(::glMultMatrixd(instance_matrix.data()));
|
glsafe(::glMultMatrixd(instance_matrix.data()));
|
||||||
|
|
||||||
std::array<float, 4> render_color;
|
ColorRGBA render_color;
|
||||||
const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
|
const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
|
||||||
size_t cache_size = drain_holes.size();
|
size_t cache_size = drain_holes.size();
|
||||||
|
|
||||||
@ -126,33 +128,25 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// First decide about the color of the point.
|
// First decide about the color of the point.
|
||||||
if (picking) {
|
if (picking)
|
||||||
std::array<float, 4> color = picking_color_component(i);
|
render_color = picking_color_component(i);
|
||||||
render_color = color;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
if (size_t(m_hover_id) == i) {
|
if (size_t(m_hover_id) == i)
|
||||||
render_color = {0.f, 1.f, 1.f, 1.f};
|
render_color = {0.0f, 1.0f, 1.0f, 1.0f};
|
||||||
}
|
|
||||||
else if (m_c->hollowed_mesh() &&
|
else if (m_c->hollowed_mesh() &&
|
||||||
i < m_c->hollowed_mesh()->get_drainholes().size() &&
|
i < m_c->hollowed_mesh()->get_drainholes().size() &&
|
||||||
m_c->hollowed_mesh()->get_drainholes()[i].failed) {
|
m_c->hollowed_mesh()->get_drainholes()[i].failed) {
|
||||||
render_color = {1.f, 0.f, 0.f, .5f};
|
render_color = {1.0f, 0.0f, 0.0f, 0.5f};
|
||||||
}
|
|
||||||
else { // neigher hover nor picking
|
|
||||||
|
|
||||||
render_color[0] = point_selected ? 1.0f : 1.f;
|
|
||||||
render_color[1] = point_selected ? 0.3f : 1.f;
|
|
||||||
render_color[2] = point_selected ? 0.3f : 1.f;
|
|
||||||
render_color[3] = 0.5f;
|
|
||||||
}
|
}
|
||||||
|
else // neither hover nor picking
|
||||||
|
render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_cast<GLModel*>(&m_vbo_cylinder)->set_color(-1, render_color);
|
const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color);
|
||||||
|
|
||||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2)));
|
glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z()));
|
||||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
@ -166,7 +160,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||||
m_vbo_cylinder.render();
|
m_cylinder.render();
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
|
@ -48,7 +48,8 @@ private:
|
|||||||
|
|
||||||
ObjectID m_old_mo_id = -1;
|
ObjectID m_old_mo_id = -1;
|
||||||
|
|
||||||
GLModel m_vbo_cylinder;
|
GLModel m_cylinder;
|
||||||
|
|
||||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||||
float m_new_hole_height = 6.f;
|
float m_new_hole_height = 6.f;
|
||||||
mutable std::vector<bool> m_selected; // which holes are currently selected
|
mutable std::vector<bool> m_selected; // which holes are currently selected
|
||||||
|
@ -56,18 +56,12 @@ bool GLGizmoMmuSegmentation::on_is_activable() const
|
|||||||
return GLGizmoPainterBase::on_is_activable() && wxGetApp().extruders_edited_cnt() > 1;
|
return GLGizmoPainterBase::on_is_activable() && wxGetApp().extruders_edited_cnt() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::array<float, 4>> get_extruders_colors()
|
static std::vector<ColorRGBA> get_extruders_colors()
|
||||||
{
|
{
|
||||||
unsigned char rgb_color[3] = {};
|
|
||||||
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||||
std::vector<std::array<float, 4>> colors_out(colors.size());
|
std::vector<ColorRGBA> ret;
|
||||||
for (const std::string &color : colors) {
|
decode_colors(colors, ret);
|
||||||
Slic3r::GUI::BitmapCache::parse_color(color, rgb_color);
|
return ret;
|
||||||
size_t color_idx = &color - &colors.front();
|
|
||||||
colors_out[color_idx] = {float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f};
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> get_extruders_names()
|
static std::vector<std::string> get_extruders_names()
|
||||||
@ -212,18 +206,14 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_extruders_combo(const std::string &label,
|
static void render_extruders_combo(const std::string& label,
|
||||||
const std::vector<std::string> &extruders,
|
const std::vector<std::string>& extruders,
|
||||||
const std::vector<std::array<float, 4>> &extruders_colors,
|
const std::vector<ColorRGBA>& extruders_colors,
|
||||||
size_t &selection_idx)
|
size_t& selection_idx)
|
||||||
{
|
{
|
||||||
assert(!extruders_colors.empty());
|
assert(!extruders_colors.empty());
|
||||||
assert(extruders_colors.size() == extruders_colors.size());
|
assert(extruders_colors.size() == extruders_colors.size());
|
||||||
|
|
||||||
auto convert_to_imu32 = [](const std::array<float, 4> &color) -> ImU32 {
|
|
||||||
return IM_COL32(uint8_t(color[0] * 255.f), uint8_t(color[1] * 255.f), uint8_t(color[2] * 255.f), uint8_t(color[3] * 255.f));
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t selection_out = selection_idx;
|
size_t selection_out = selection_idx;
|
||||||
// It is necessary to use BeginGroup(). Otherwise, when using SameLine() is called, then other items will be drawn inside the combobox.
|
// It is necessary to use BeginGroup(). Otherwise, when using SameLine() is called, then other items will be drawn inside the combobox.
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
@ -239,7 +229,7 @@ static void render_extruders_combo(const std::string &labe
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGuiStyle &style = ImGui::GetStyle();
|
ImGuiStyle &style = ImGui::GetStyle();
|
||||||
float height = ImGui::GetTextLineHeight();
|
float height = ImGui::GetTextLineHeight();
|
||||||
ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), convert_to_imu32(extruders_colors[extruder_idx]));
|
ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), ImGuiWrapper::to_ImU32(extruders_colors[extruder_idx]));
|
||||||
ImGui::GetWindowDrawList()->AddRect(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), IM_COL32_BLACK);
|
ImGui::GetWindowDrawList()->AddRect(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), IM_COL32_BLACK);
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(ImVec2(start_position.x + height + height / 2 + style.FramePadding.x, start_position.y));
|
ImGui::SetCursorScreenPos(ImVec2(start_position.x + height + height / 2 + style.FramePadding.x, start_position.y));
|
||||||
@ -257,7 +247,7 @@ static void render_extruders_combo(const std::string &labe
|
|||||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
float height = ImGui::GetTextLineHeight();
|
float height = ImGui::GetTextLineHeight();
|
||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), convert_to_imu32(extruders_colors[selection_idx]));
|
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), ImGuiWrapper::to_ImU32(extruders_colors[selection_idx]));
|
||||||
ImGui::GetWindowDrawList()->AddRect(p, ImVec2(p.x + height + height / 2, p.y + height), IM_COL32_BLACK);
|
ImGui::GetWindowDrawList()->AddRect(p, ImVec2(p.x + height + height / 2, p.y + height), IM_COL32_BLACK);
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(ImVec2(p.x + height + height / 2 + style.FramePadding.x, p.y));
|
ImGui::SetCursorScreenPos(ImVec2(p.x + height + height / 2 + style.FramePadding.x, p.y));
|
||||||
@ -339,10 +329,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
|||||||
render_extruders_combo("##first_color_combo", m_original_extruders_names, m_original_extruders_colors, m_first_selected_extruder_idx);
|
render_extruders_combo("##first_color_combo", m_original_extruders_names, m_original_extruders_colors, m_first_selected_extruder_idx);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
const std::array<float, 4> &select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx];
|
const ColorRGBA& select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx];
|
||||||
ImVec4 first_color = ImVec4(select_first_color[0], select_first_color[1], select_first_color[2], select_first_color[3]);
|
ImVec4 first_color = ImGuiWrapper::to_ImVec4(select_first_color);
|
||||||
if(ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
|
if (ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
|
||||||
m_modified_extruders_colors[m_first_selected_extruder_idx] = {first_color.x, first_color.y, first_color.z, first_color.w};
|
m_modified_extruders_colors[m_first_selected_extruder_idx] = ImGuiWrapper::from_ImVec4(first_color);
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(m_desc.at("second_color"));
|
m_imgui->text(m_desc.at("second_color"));
|
||||||
@ -351,10 +341,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
|||||||
render_extruders_combo("##second_color_combo", m_original_extruders_names, m_original_extruders_colors, m_second_selected_extruder_idx);
|
render_extruders_combo("##second_color_combo", m_original_extruders_names, m_original_extruders_colors, m_second_selected_extruder_idx);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
const std::array<float, 4> &select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx];
|
const ColorRGBA& select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx];
|
||||||
ImVec4 second_color = ImVec4(select_second_color[0], select_second_color[1], select_second_color[2], select_second_color[3]);
|
ImVec4 second_color = ImGuiWrapper::to_ImVec4(select_second_color);
|
||||||
if(ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
|
if (ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
|
||||||
m_modified_extruders_colors[m_second_selected_extruder_idx] = {second_color.x, second_color.y, second_color.z, second_color.w};
|
m_modified_extruders_colors[m_second_selected_extruder_idx] = ImGuiWrapper::from_ImVec4(second_color);
|
||||||
|
|
||||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||||
|
|
||||||
@ -565,16 +555,18 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
|
|||||||
return PainterGizmoType::MMU_SEGMENTATION;
|
return PainterGizmoType::MMU_SEGMENTATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<float, 4> GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const
|
ColorRGBA GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const
|
||||||
{
|
{
|
||||||
const std::array<float, 4> &color = m_modified_extruders_colors[m_first_selected_extruder_idx];
|
ColorRGBA color = m_modified_extruders_colors[m_first_selected_extruder_idx];
|
||||||
return {color[0], color[1], color[2], 0.25f};
|
color.a(0.25f);
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<float, 4> GLGizmoMmuSegmentation::get_cursor_sphere_right_button_color() const
|
ColorRGBA GLGizmoMmuSegmentation::get_cursor_sphere_right_button_color() const
|
||||||
{
|
{
|
||||||
const std::array<float, 4> &color = m_modified_extruders_colors[m_second_selected_extruder_idx];
|
ColorRGBA color = m_modified_extruders_colors[m_second_selected_extruder_idx];
|
||||||
return {color[0], color[1], color[2], 0.25f};
|
color.a(0.25f);
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
|
void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
class TriangleSelectorMmGui : public TriangleSelectorGUI {
|
class TriangleSelectorMmGui : public TriangleSelectorGUI {
|
||||||
public:
|
public:
|
||||||
// Plus 1 in the initialization of m_gizmo_scene is because the first position is allocated for non-painted triangles, and the indices above colors.size() are allocated for seed fill.
|
// Plus 1 in the initialization of m_gizmo_scene is because the first position is allocated for non-painted triangles, and the indices above colors.size() are allocated for seed fill.
|
||||||
explicit TriangleSelectorMmGui(const TriangleMesh &mesh, const std::vector<std::array<float, 4>> &colors, const std::array<float, 4> &default_volume_color)
|
TriangleSelectorMmGui(const TriangleMesh& mesh, const std::vector<ColorRGBA>& colors, const ColorRGBA& default_volume_color)
|
||||||
: TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color), m_gizmo_scene(2 * (colors.size() + 1)) {}
|
: TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color), m_gizmo_scene(2 * (colors.size() + 1)) {}
|
||||||
~TriangleSelectorMmGui() override = default;
|
~TriangleSelectorMmGui() override = default;
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void update_render_data();
|
void update_render_data();
|
||||||
|
|
||||||
const std::vector<std::array<float, 4>> &m_colors;
|
const std::vector<ColorRGBA>& m_colors;
|
||||||
const std::array<float, 4> m_default_volume_color;
|
const ColorRGBA m_default_volume_color;
|
||||||
GLMmSegmentationGizmo3DScene m_gizmo_scene;
|
GLMmSegmentationGizmo3DScene m_gizmo_scene;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ public:
|
|||||||
const float get_cursor_radius_min() const override { return CursorRadiusMin; }
|
const float get_cursor_radius_min() const override { return CursorRadiusMin; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::array<float, 4> get_cursor_sphere_left_button_color() const override;
|
ColorRGBA get_cursor_sphere_left_button_color() const override;
|
||||||
std::array<float, 4> get_cursor_sphere_right_button_color() const override;
|
ColorRGBA get_cursor_sphere_right_button_color() const override;
|
||||||
|
|
||||||
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); }
|
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); }
|
||||||
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); }
|
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); }
|
||||||
@ -121,8 +121,8 @@ protected:
|
|||||||
size_t m_first_selected_extruder_idx = 0;
|
size_t m_first_selected_extruder_idx = 0;
|
||||||
size_t m_second_selected_extruder_idx = 1;
|
size_t m_second_selected_extruder_idx = 1;
|
||||||
std::vector<std::string> m_original_extruders_names;
|
std::vector<std::string> m_original_extruders_names;
|
||||||
std::vector<std::array<float, 4>> m_original_extruders_colors;
|
std::vector<ColorRGBA> m_original_extruders_colors;
|
||||||
std::vector<std::array<float, 4>> m_modified_extruders_colors;
|
std::vector<ColorRGBA> m_modified_extruders_colors;
|
||||||
std::vector<int> m_original_volumes_extruder_idxs;
|
std::vector<int> m_original_volumes_extruder_idxs;
|
||||||
|
|
||||||
static const constexpr float CursorRadiusMin = 0.1f; // cannot be zero
|
static const constexpr float CursorRadiusMin = 0.1f; // cannot be zero
|
||||||
|
@ -20,7 +20,6 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
|
|||||||
, m_starting_box_center(Vec3d::Zero())
|
, m_starting_box_center(Vec3d::Zero())
|
||||||
, m_starting_box_bottom_center(Vec3d::Zero())
|
, m_starting_box_bottom_center(Vec3d::Zero())
|
||||||
{
|
{
|
||||||
m_vbo_cone.init_from(its_make_cone(1., 1., 2*PI/36));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLGizmoMove3D::get_tooltip() const
|
std::string GLGizmoMove3D::get_tooltip() const
|
||||||
@ -89,6 +88,9 @@ void GLGizmoMove3D::on_update(const UpdateData& data)
|
|||||||
|
|
||||||
void GLGizmoMove3D::on_render()
|
void GLGizmoMove3D::on_render()
|
||||||
{
|
{
|
||||||
|
if (!m_cone.is_initialized())
|
||||||
|
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
@ -193,19 +195,15 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
|||||||
float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
|
float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
|
||||||
double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size);
|
double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size);
|
||||||
|
|
||||||
std::array<float, 4> color = m_grabbers[axis].color;
|
ColorRGBA color = m_grabbers[axis].color;
|
||||||
if (!picking && m_hover_id != -1) {
|
if (!picking && m_hover_id != -1)
|
||||||
color[0] = 1.0f - color[0];
|
color = complementary(color);
|
||||||
color[1] = 1.0f - color[1];
|
|
||||||
color[2] = 1.0f - color[2];
|
|
||||||
color[3] = color[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const_cast<GLModel*>(&m_vbo_cone)->set_color(-1, color);
|
const_cast<GLModel*>(&m_cone)->set_color(-1, color);
|
||||||
if (!picking) {
|
if (!picking) {
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.1f);
|
shader->set_uniform("emission_factor", 0.1f);
|
||||||
@ -220,7 +218,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
|
|||||||
|
|
||||||
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
|
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
|
||||||
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
|
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
|
||||||
m_vbo_cone.render();
|
m_cone.render();
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
|
|
||||||
if (! picking)
|
if (! picking)
|
||||||
|
@ -19,7 +19,7 @@ class GLGizmoMove3D : public GLGizmoBase
|
|||||||
Vec3d m_starting_box_center;
|
Vec3d m_starting_box_center;
|
||||||
Vec3d m_starting_box_bottom_center;
|
Vec3d m_starting_box_bottom_center;
|
||||||
|
|
||||||
GLModel m_vbo_cone;
|
GLModel m_cone;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
|
@ -18,13 +18,17 @@
|
|||||||
|
|
||||||
namespace Slic3r::GUI {
|
namespace Slic3r::GUI {
|
||||||
|
|
||||||
|
std::shared_ptr<GLIndexedVertexArray> GLGizmoPainterBase::s_sphere = nullptr;
|
||||||
|
|
||||||
GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
{
|
{
|
||||||
// Make sphere and save it into a vertex buffer.
|
}
|
||||||
m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.));
|
|
||||||
m_vbo_sphere.finalize_geometry(true);
|
GLGizmoPainterBase::~GLGizmoPainterBase()
|
||||||
|
{
|
||||||
|
if (s_sphere != nullptr && s_sphere->has_VBOs())
|
||||||
|
s_sphere->release_geometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection)
|
void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection)
|
||||||
@ -184,6 +188,12 @@ void GLGizmoPainterBase::render_cursor_circle() const
|
|||||||
|
|
||||||
void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
||||||
{
|
{
|
||||||
|
if (s_sphere == nullptr) {
|
||||||
|
s_sphere = std::make_shared<GLIndexedVertexArray>();
|
||||||
|
s_sphere->load_its_flat_shading(its_make_sphere(1.0, double(PI) / 12.0));
|
||||||
|
s_sphere->finalize_geometry(true);
|
||||||
|
}
|
||||||
|
|
||||||
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
|
const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse();
|
||||||
const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed();
|
const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed();
|
||||||
|
|
||||||
@ -197,14 +207,15 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
|
|||||||
if (is_left_handed)
|
if (is_left_handed)
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
|
|
||||||
std::array<float, 4> render_color = {0.f, 0.f, 0.f, 0.25f};
|
ColorRGBA render_color = { 0.0f, 0.0f, 0.0f, 0.25f };
|
||||||
if (m_button_down == Button::Left)
|
if (m_button_down == Button::Left)
|
||||||
render_color = this->get_cursor_sphere_left_button_color();
|
render_color = this->get_cursor_sphere_left_button_color();
|
||||||
else if (m_button_down == Button::Right)
|
else if (m_button_down == Button::Right)
|
||||||
render_color = this->get_cursor_sphere_right_button_color();
|
render_color = this->get_cursor_sphere_right_button_color();
|
||||||
glsafe(::glColor4fv(render_color.data()));
|
glsafe(::glColor4fv(render_color.data()));
|
||||||
|
|
||||||
m_vbo_sphere.render();
|
assert(s_sphere != nullptr);
|
||||||
|
s_sphere->render();
|
||||||
|
|
||||||
if (is_left_handed)
|
if (is_left_handed)
|
||||||
glFrontFace(GL_CCW);
|
glFrontFace(GL_CCW);
|
||||||
@ -698,15 +709,15 @@ TriangleSelector::ClippingPlane GLGizmoPainterBase::get_clipping_plane_in_volume
|
|||||||
return TriangleSelector::ClippingPlane({float(normal_transformed.x()), float(normal_transformed.y()), float(normal_transformed.z()), offset_transformed});
|
return TriangleSelector::ClippingPlane({float(normal_transformed.x()), float(normal_transformed.y()), float(normal_transformed.z()), offset_transformed});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<float, 4> TriangleSelectorGUI::get_seed_fill_color(const std::array<float, 4> &base_color)
|
ColorRGBA TriangleSelectorGUI::get_seed_fill_color(const ColorRGBA& base_color)
|
||||||
{
|
{
|
||||||
return {base_color[0] * 0.75f, base_color[1] * 0.75f, base_color[2] * 0.75f, 1.f};
|
return saturate(base_color, 0.75f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
||||||
{
|
{
|
||||||
static constexpr std::array<float, 4> enforcers_color{0.47f, 0.47f, 1.f, 1.f};
|
static const ColorRGBA enforcers_color = { 0.47f, 0.47f, 1.0f, 1.0f };
|
||||||
static constexpr std::array<float, 4> blockers_color{1.f, 0.44f, 0.44f, 1.f};
|
static const ColorRGBA blockers_color = { 1.0f, 0.44f, 0.44f, 1.0f };
|
||||||
|
|
||||||
if (m_update_render_data) {
|
if (m_update_render_data) {
|
||||||
update_render_data();
|
update_render_data();
|
||||||
@ -730,7 +741,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
|
|||||||
for (auto &iva : m_iva_seed_fills)
|
for (auto &iva : m_iva_seed_fills)
|
||||||
if (iva.has_VBOs()) {
|
if (iva.has_VBOs()) {
|
||||||
size_t color_idx = &iva - &m_iva_seed_fills.front();
|
size_t color_idx = &iva - &m_iva_seed_fills.front();
|
||||||
const std::array<float, 4> &color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color :
|
const ColorRGBA& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color :
|
||||||
color_idx == 2 ? blockers_color :
|
color_idx == 2 ? blockers_color :
|
||||||
GLVolume::NEUTRAL_COLOR);
|
GLVolume::NEUTRAL_COLOR);
|
||||||
shader->set_uniform("uniform_color", color);
|
shader->set_uniform("uniform_color", color);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r::GUI {
|
namespace Slic3r::GUI {
|
||||||
@ -85,7 +86,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
bool m_update_render_data = false;
|
bool m_update_render_data = false;
|
||||||
|
|
||||||
static std::array<float, 4> get_seed_fill_color(const std::array<float, 4> &base_color);
|
static ColorRGBA get_seed_fill_color(const ColorRGBA& base_color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_render_data();
|
void update_render_data();
|
||||||
@ -112,7 +113,7 @@ private:
|
|||||||
void on_render_for_picking() override {}
|
void on_render_for_picking() override {}
|
||||||
public:
|
public:
|
||||||
GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
~GLGizmoPainterBase() override = default;
|
virtual ~GLGizmoPainterBase() override;
|
||||||
virtual void set_painter_gizmo_data(const Selection& selection);
|
virtual void set_painter_gizmo_data(const Selection& selection);
|
||||||
virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||||
|
|
||||||
@ -134,8 +135,8 @@ protected:
|
|||||||
virtual void update_model_object() const = 0;
|
virtual void update_model_object() const = 0;
|
||||||
virtual void update_from_model_object() = 0;
|
virtual void update_from_model_object() = 0;
|
||||||
|
|
||||||
virtual std::array<float, 4> get_cursor_sphere_left_button_color() const { return {0.f, 0.f, 1.f, 0.25f}; }
|
virtual ColorRGBA get_cursor_sphere_left_button_color() const { return { 0.0f, 0.0f, 1.0f, 0.25f }; }
|
||||||
virtual std::array<float, 4> get_cursor_sphere_right_button_color() const { return {1.f, 0.f, 0.f, 0.25f}; }
|
virtual ColorRGBA get_cursor_sphere_right_button_color() const { return { 1.0f, 0.0f, 0.0f, 0.25f }; }
|
||||||
|
|
||||||
virtual EnforcerBlockerType get_left_button_state_type() const { return EnforcerBlockerType::ENFORCER; }
|
virtual EnforcerBlockerType get_left_button_state_type() const { return EnforcerBlockerType::ENFORCER; }
|
||||||
virtual EnforcerBlockerType get_right_button_state_type() const { return EnforcerBlockerType::BLOCKER; }
|
virtual EnforcerBlockerType get_right_button_state_type() const { return EnforcerBlockerType::BLOCKER; }
|
||||||
@ -202,7 +203,7 @@ private:
|
|||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const std::vector<Transform3d>& trafo_matrices) const;
|
const std::vector<Transform3d>& trafo_matrices) const;
|
||||||
|
|
||||||
GLIndexedVertexArray m_vbo_sphere;
|
static std::shared_ptr<GLIndexedVertexArray> s_sphere;
|
||||||
|
|
||||||
bool m_internal_stack_active = false;
|
bool m_internal_stack_active = false;
|
||||||
bool m_schedule_update = false;
|
bool m_schedule_update = false;
|
||||||
|
@ -39,20 +39,6 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other)
|
|
||||||
: GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id)
|
|
||||||
, m_axis(other.m_axis)
|
|
||||||
, m_angle(other.m_angle)
|
|
||||||
, m_center(other.m_center)
|
|
||||||
, m_radius(other.m_radius)
|
|
||||||
, m_snap_coarse_in_radius(other.m_snap_coarse_in_radius)
|
|
||||||
, m_snap_coarse_out_radius(other.m_snap_coarse_out_radius)
|
|
||||||
, m_snap_fine_in_radius(other.m_snap_fine_in_radius)
|
|
||||||
, m_snap_fine_out_radius(other.m_snap_fine_out_radius)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoRotate::set_angle(double angle)
|
void GLGizmoRotate::set_angle(double angle)
|
||||||
{
|
{
|
||||||
if (std::abs(angle - 2.0 * (double)PI) < EPSILON)
|
if (std::abs(angle - 2.0 * (double)PI) < EPSILON)
|
||||||
@ -130,6 +116,9 @@ void GLGizmoRotate::on_render()
|
|||||||
if (!m_grabbers[0].enabled)
|
if (!m_grabbers[0].enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!m_cone.is_initialized())
|
||||||
|
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0));
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
|
|
||||||
@ -325,12 +314,9 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
|
|||||||
float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
|
float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
|
||||||
double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size);
|
double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size);
|
||||||
|
|
||||||
std::array<float, 4> color = m_grabbers[0].color;
|
ColorRGBA color = m_grabbers[0].color;
|
||||||
if (!picking && m_hover_id != -1) {
|
if (!picking && m_hover_id != -1)
|
||||||
color[0] = 1.0f - color[0];
|
color = complementary(color);
|
||||||
color[1] = 1.0f - color[1];
|
|
||||||
color[2] = 1.0f - color[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
@ -433,11 +419,8 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
|||||||
|
|
||||||
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
|
, m_gizmos({ GLGizmoRotate(parent, GLGizmoRotate::X), GLGizmoRotate(parent, GLGizmoRotate::Y), GLGizmoRotate(parent, GLGizmoRotate::Z) })
|
||||||
{
|
{
|
||||||
m_gizmos.emplace_back(parent, GLGizmoRotate::X);
|
|
||||||
m_gizmos.emplace_back(parent, GLGizmoRotate::Y);
|
|
||||||
m_gizmos.emplace_back(parent, GLGizmoRotate::Z);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 3; ++i) {
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
m_gizmos[i].set_group_id(i);
|
m_gizmos[i].set_group_id(i);
|
||||||
}
|
}
|
||||||
@ -554,11 +537,12 @@ GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
|
|||||||
ImVec2 button_sz = {btn_txt_sz.x + padding.x, btn_txt_sz.y + padding.y};
|
ImVec2 button_sz = {btn_txt_sz.x + padding.x, btn_txt_sz.y + padding.y};
|
||||||
ImGui::SetCursorPosX(padding.x + sz.x - button_sz.x);
|
ImGui::SetCursorPosX(padding.x + sz.x - button_sz.x);
|
||||||
|
|
||||||
if (wxGetApp().plater()->is_any_job_running())
|
if (!wxGetApp().plater()->get_ui_job_worker().is_idle())
|
||||||
imgui->disabled_begin(true);
|
imgui->disabled_begin(true);
|
||||||
|
|
||||||
if ( imgui->button(btn_txt) ) {
|
if ( imgui->button(btn_txt) ) {
|
||||||
wxGetApp().plater()->optimize_rotation();
|
replace_job(wxGetApp().plater()->get_ui_job_worker(),
|
||||||
|
std::make_unique<RotoptimizeJob>());
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui->disabled_end();
|
imgui->disabled_end();
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#define slic3r_GLGizmoRotate_hpp_
|
#define slic3r_GLGizmoRotate_hpp_
|
||||||
|
|
||||||
#include "GLGizmoBase.hpp"
|
#include "GLGizmoBase.hpp"
|
||||||
#include "../Jobs/RotoptimizeJob.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -40,9 +38,10 @@ private:
|
|||||||
mutable float m_snap_fine_in_radius;
|
mutable float m_snap_fine_in_radius;
|
||||||
mutable float m_snap_fine_out_radius;
|
mutable float m_snap_fine_out_radius;
|
||||||
|
|
||||||
|
GLModel m_cone;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoRotate(GLCanvas3D& parent, Axis axis);
|
GLGizmoRotate(GLCanvas3D& parent, Axis axis);
|
||||||
GLGizmoRotate(const GLGizmoRotate& other);
|
|
||||||
virtual ~GLGizmoRotate() = default;
|
virtual ~GLGizmoRotate() = default;
|
||||||
|
|
||||||
double get_angle() const { return m_angle; }
|
double get_angle() const { return m_angle; }
|
||||||
@ -74,7 +73,7 @@ private:
|
|||||||
|
|
||||||
class GLGizmoRotate3D : public GLGizmoBase
|
class GLGizmoRotate3D : public GLGizmoBase
|
||||||
{
|
{
|
||||||
std::vector<GLGizmoRotate> m_gizmos;
|
std::array<GLGizmoRotate, 3> m_gizmos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
|
@ -77,6 +77,13 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
|
|||||||
|
|
||||||
void GLGizmoSlaSupports::on_render()
|
void GLGizmoSlaSupports::on_render()
|
||||||
{
|
{
|
||||||
|
if (!m_cone.is_initialized())
|
||||||
|
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0));
|
||||||
|
if (!m_sphere.is_initialized())
|
||||||
|
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0));
|
||||||
|
if (!m_cylinder.is_initialized())
|
||||||
|
m_cylinder.init_from(its_make_cylinder(1.0, 1.0, double(PI) / 12.0));
|
||||||
|
|
||||||
ModelObject* mo = m_c->selection_info()->model_object();
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
|
||||||
@ -137,7 +144,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
glsafe(::glTranslated(0.0, 0.0, z_shift));
|
glsafe(::glTranslated(0.0, 0.0, z_shift));
|
||||||
glsafe(::glMultMatrixd(instance_matrix.data()));
|
glsafe(::glMultMatrixd(instance_matrix.data()));
|
||||||
|
|
||||||
std::array<float, 4> render_color;
|
ColorRGBA render_color;
|
||||||
for (size_t i = 0; i < cache_size; ++i) {
|
for (size_t i = 0; i < cache_size; ++i) {
|
||||||
const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i];
|
const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i];
|
||||||
const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
|
const bool& point_selected = m_editing_mode ? m_editing_cache[i].selected : false;
|
||||||
@ -219,10 +226,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
|
|
||||||
// Now render the drain holes:
|
// Now render the drain holes:
|
||||||
if (has_holes && ! picking) {
|
if (has_holes && ! picking) {
|
||||||
render_color[0] = 0.7f;
|
render_color = { 0.7f, 0.7f, 0.7f, 0.7f };
|
||||||
render_color[1] = 0.7f;
|
|
||||||
render_color[2] = 0.7f;
|
|
||||||
render_color[3] = 0.7f;
|
|
||||||
const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color);
|
const_cast<GLModel*>(&m_cylinder)->set_color(-1, render_color);
|
||||||
if (shader)
|
if (shader)
|
||||||
shader->set_uniform("emission_factor", 0.5f);
|
shader->set_uniform("emission_factor", 0.5f);
|
||||||
|
@ -91,6 +91,10 @@ private:
|
|||||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||||
ObjectID m_old_mo_id;
|
ObjectID m_old_mo_id;
|
||||||
|
|
||||||
|
GLModel m_cone;
|
||||||
|
GLModel m_cylinder;
|
||||||
|
GLModel m_sphere;
|
||||||
|
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
std::map<std::string, wxString> m_desc;
|
std::map<std::string, wxString> m_desc;
|
||||||
|
@ -216,8 +216,8 @@ void InstancesHider::render_cut() const
|
|||||||
if (mv->is_model_part())
|
if (mv->is_model_part())
|
||||||
glsafe(::glColor3f(0.8f, 0.3f, 0.0f));
|
glsafe(::glColor3f(0.8f, 0.3f, 0.0f));
|
||||||
else {
|
else {
|
||||||
const std::array<float, 4>& c = color_from_model_volume(*mv);
|
const ColorRGBA color = color_from_model_volume(*mv);
|
||||||
glsafe(::glColor4f(c[0], c[1], c[2], c[3]));
|
glsafe(::glColor4fv(color.data()));
|
||||||
}
|
}
|
||||||
glsafe(::glPushAttrib(GL_DEPTH_TEST));
|
glsafe(::glPushAttrib(GL_DEPTH_TEST));
|
||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
@ -417,9 +417,9 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
|
|||||||
m_loaded_hints.emplace_back(hint_data);
|
m_loaded_hints.emplace_back(hint_data);
|
||||||
// open preferences
|
// open preferences
|
||||||
} else if(dict["hypertext_type"] == "preferences") {
|
} else if(dict["hypertext_type"] == "preferences") {
|
||||||
int page = static_cast<Preset::Type>(std::atoi(dict["hypertext_preferences_page"].c_str()));
|
std::string page = dict["hypertext_preferences_page"];
|
||||||
std::string item = dict["hypertext_preferences_item"];
|
std::string item = dict["hypertext_preferences_item"];
|
||||||
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [page, item]() { wxGetApp().open_preferences(page, item); } };
|
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [page, item]() { wxGetApp().open_preferences(item, page); } };
|
||||||
m_loaded_hints.emplace_back(hint_data);
|
m_loaded_hints.emplace_back(hint_data);
|
||||||
} else if (dict["hypertext_type"] == "plater") {
|
} else if (dict["hypertext_type"] == "plater") {
|
||||||
std::string item = dict["hypertext_plater_item"];
|
std::string item = dict["hypertext_plater_item"];
|
||||||
@ -924,7 +924,7 @@ void NotificationManager::HintNotification::render_preferences_button(ImGuiWrapp
|
|||||||
}
|
}
|
||||||
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
|
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
|
||||||
{
|
{
|
||||||
wxGetApp().open_preferences(2, "show_hints");
|
wxGetApp().open_preferences("show_hints", "GUI");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleColor(5);
|
ImGui::PopStyleColor(5);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
@ -52,7 +53,22 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
|||||||
{ImGui::PreferencesButton , "notification_preferences" },
|
{ImGui::PreferencesButton , "notification_preferences" },
|
||||||
{ImGui::PreferencesHoverButton, "notification_preferences_hover"},
|
{ImGui::PreferencesHoverButton, "notification_preferences_hover"},
|
||||||
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
|
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
|
||||||
|
{ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" },
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
{ImGui::LegendTravel , "legend_travel" },
|
||||||
|
{ImGui::LegendWipe , "legend_wipe" },
|
||||||
|
{ImGui::LegendRetract , "legend_retract" },
|
||||||
|
{ImGui::LegendDeretract , "legend_deretract" },
|
||||||
|
{ImGui::LegendSeams , "legend_seams" },
|
||||||
|
{ImGui::LegendToolChanges , "legend_toolchanges" },
|
||||||
|
{ImGui::LegendColorChanges , "legend_colorchanges" },
|
||||||
|
{ImGui::LegendPausePrints , "legend_pauseprints" },
|
||||||
|
{ImGui::LegendCustomGCodes , "legend_customgcodes" },
|
||||||
|
{ImGui::LegendShells , "legend_shells" },
|
||||||
|
{ImGui::LegendToolMarker , "legend_toolmarker" },
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||||
{ImGui::CloseNotifButton , "notification_close" },
|
{ImGui::CloseNotifButton , "notification_close" },
|
||||||
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
|
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
|
||||||
@ -78,14 +94,14 @@ static const std::map<const wchar_t, std::string> font_icons_extra_large = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f };
|
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f };
|
||||||
const ImVec4 ImGuiWrapper::COL_GREY_LIGHT = { 0.4f, 0.4f, 0.4f, 1.0f };
|
const ImVec4 ImGuiWrapper::COL_GREY_LIGHT = { 0.4f, 0.4f, 0.4f, 1.0f };
|
||||||
const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.757f, 0.404f, 0.216f, 1.0f };
|
const ImVec4 ImGuiWrapper::COL_ORANGE_DARK = { 0.67f, 0.36f, 0.19f, 1.0f };
|
||||||
const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = { 1.0f, 0.49f, 0.216f, 1.0f };
|
const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT = to_ImVec4(ColorRGBA::ORANGE());
|
||||||
const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.133f, 0.133f, 0.133f, 0.8f };
|
const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROUND = { 0.13f, 0.13f, 0.13f, 0.8f };
|
||||||
const ImVec4 ImGuiWrapper::COL_BUTTON_BACKGROUND = COL_ORANGE_DARK;
|
const ImVec4 ImGuiWrapper::COL_BUTTON_BACKGROUND = COL_ORANGE_DARK;
|
||||||
const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT;
|
const ImVec4 ImGuiWrapper::COL_BUTTON_HOVERED = COL_ORANGE_LIGHT;
|
||||||
const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = ImGuiWrapper::COL_BUTTON_HOVERED;
|
const ImVec4 ImGuiWrapper::COL_BUTTON_ACTIVE = COL_BUTTON_HOVERED;
|
||||||
|
|
||||||
ImGuiWrapper::ImGuiWrapper()
|
ImGuiWrapper::ImGuiWrapper()
|
||||||
{
|
{
|
||||||
@ -370,10 +386,41 @@ bool ImGuiWrapper::radio_button(const wxString &label, bool active)
|
|||||||
return ImGui::RadioButton(label_utf8.c_str(), active);
|
return ImGui::RadioButton(label_utf8.c_str(), active);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiWrapper::image_button()
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
bool ImGuiWrapper::draw_radio_button(const std::string& name, float size, bool active,
|
||||||
|
std::function<void(ImGuiWindow& window, const ImVec2& pos, float size)> draw_callback)
|
||||||
{
|
{
|
||||||
|
ImGuiWindow& window = *ImGui::GetCurrentWindow();
|
||||||
|
if (window.SkipItems)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
const ImGuiStyle& style = g.Style;
|
||||||
|
const ImGuiID id = window.GetID(name.c_str());
|
||||||
|
|
||||||
|
const ImVec2 pos = window.DC.CursorPos;
|
||||||
|
const ImRect total_bb(pos, pos + ImVec2(size, size + style.FramePadding.y * 2.0f));
|
||||||
|
ImGui::ItemSize(total_bb, style.FramePadding.y);
|
||||||
|
if (!ImGui::ItemAdd(total_bb, id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool hovered, held;
|
||||||
|
bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held);
|
||||||
|
if (pressed)
|
||||||
|
ImGui::MarkItemEdited(id);
|
||||||
|
|
||||||
|
if (hovered)
|
||||||
|
window.DrawList->AddRect({ pos.x - 1.0f, pos.y - 1.0f }, { pos.x + size + 1.0f, pos.y + size + 1.0f }, ImGui::GetColorU32(ImGuiCol_CheckMark));
|
||||||
|
|
||||||
|
if (active)
|
||||||
|
window.DrawList->AddRect(pos, { pos.x + size, pos.y + size }, ImGui::GetColorU32(ImGuiCol_CheckMark));
|
||||||
|
|
||||||
|
draw_callback(window, pos, size);
|
||||||
|
|
||||||
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window.DC.LastItemStatusFlags);
|
||||||
|
return pressed;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format)
|
bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format)
|
||||||
{
|
{
|
||||||
@ -497,6 +544,9 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float
|
|||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
str_label = str_label.substr(0, pos) + str_label.substr(pos + 2);
|
str_label = str_label.substr(0, pos) + str_label.substr(pos + 2);
|
||||||
|
|
||||||
|
// the current slider edit state needs to be detected here before calling SliderFloat()
|
||||||
|
bool slider_editing = ImGui::GetCurrentWindow()->GetID(str_label.c_str()) == ImGui::GetActiveID();
|
||||||
|
|
||||||
bool ret = ImGui::SliderFloat(str_label.c_str(), v, v_min, v_max, format, power);
|
bool ret = ImGui::SliderFloat(str_label.c_str(), v, v_min, v_max, format, power);
|
||||||
|
|
||||||
m_last_slider_status.hovered = ImGui::IsItemHovered();
|
m_last_slider_status.hovered = ImGui::IsItemHovered();
|
||||||
@ -514,15 +564,42 @@ bool ImGuiWrapper::slider_float(const char* label, float* v, float v_min, float
|
|||||||
if (show_edit_btn) {
|
if (show_edit_btn) {
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 1, style.ItemSpacing.y });
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 1, style.ItemSpacing.y });
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
std::wstring btn_name = ImGui::SliderFloatEditBtnIcon + boost::nowide::widen(str_label);
|
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
assert(io.Fonts->TexWidth > 0 && io.Fonts->TexHeight > 0);
|
||||||
|
float inv_tex_w = 1.0f / float(io.Fonts->TexWidth);
|
||||||
|
float inv_tex_h = 1.0f / float(io.Fonts->TexHeight);
|
||||||
|
|
||||||
|
const ImFontAtlasCustomRect* const rect = GetTextureCustomRect(slider_editing ? ImGui::SliderFloatEditBtnPressedIcon : ImGui::SliderFloatEditBtnIcon);
|
||||||
|
const ImVec2 size = { float(rect->Width), float(rect->Height) };
|
||||||
|
const ImVec2 uv0 = ImVec2(float(rect->X) * inv_tex_w, float(rect->Y) * inv_tex_h);
|
||||||
|
const ImVec2 uv1 = ImVec2(float(rect->X + rect->Width) * inv_tex_w, float(rect->Y + rect->Height) * inv_tex_h);
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f });
|
ImGui::PushStyleColor(ImGuiCol_Button, { 0.25f, 0.25f, 0.25f, 0.0f });
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.5f, 0.5f, 0.5f, 1.0f });
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.4f, 0.4f, 0.4f, 1.0f });
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.5f, 0.5f, 0.5f, 1.0f });
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.4f, 0.4f, 0.4f, 1.0f });
|
||||||
|
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
const ImTextureID tex_id = io.Fonts->TexID;
|
||||||
|
if (image_button(tex_id, size, uv0, uv1, -1, ImVec4(0.0, 0.0, 0.0, 0.0), ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags_PressedOnClick)) {
|
||||||
|
if (!slider_editing)
|
||||||
|
ImGui::SetKeyboardFocusHere(-1);
|
||||||
|
else
|
||||||
|
ImGui::ClearActiveID();
|
||||||
|
this->set_requires_extra_frame();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::wstring btn_name = ImGui::SliderFloatEditBtnIcon + boost::nowide::widen(str_label);
|
||||||
if (ImGui::Button(into_u8(btn_name).c_str())) {
|
if (ImGui::Button(into_u8(btn_name).c_str())) {
|
||||||
ImGui::SetKeyboardFocusHere(-1);
|
ImGui::SetKeyboardFocusHere(-1);
|
||||||
this->set_requires_extra_frame();
|
this->set_requires_extra_frame();
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
|
||||||
ImGui::PopStyleColor(3);
|
ImGui::PopStyleColor(3);
|
||||||
|
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
this->tooltip(into_u8(_L("Edit")).c_str(), max_tooltip_width);
|
this->tooltip(into_u8(_L("Edit")).c_str(), max_tooltip_width);
|
||||||
|
|
||||||
@ -556,17 +633,65 @@ bool ImGuiWrapper::slider_float(const wxString& label, float* v, float v_min, fl
|
|||||||
return this->slider_float(label_utf8.c_str(), v, v_min, v_max, format, power, clamp, tooltip, show_edit_btn);
|
return this->slider_float(label_utf8.c_str(), v, v_min, v_max, format, power, clamp, tooltip, show_edit_btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection)
|
static bool image_button_ex(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
|
||||||
|
ImGui::ItemSize(bb);
|
||||||
|
if (!ImGui::ItemAdd(bb, id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool hovered, held;
|
||||||
|
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
|
// Render
|
||||||
|
const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||||
|
ImGui::RenderNavHighlight(bb, id);
|
||||||
|
ImGui::RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
|
||||||
|
if (bg_col.w > 0.0f)
|
||||||
|
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, ImGui::GetColorU32(bg_col));
|
||||||
|
window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, ImGui::GetColorU32(tint_col));
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGuiWrapper::image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
if (window->SkipItems)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Default to using texture ID as ID. User can still push string/integer prefixes.
|
||||||
|
ImGui::PushID((void*)(intptr_t)user_texture_id);
|
||||||
|
const ImGuiID id = window->GetID("#image");
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding;
|
||||||
|
return image_button_ex(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags)
|
||||||
{
|
{
|
||||||
// this is to force the label to the left of the widget:
|
// this is to force the label to the left of the widget:
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
if (!label.empty()) {
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
text(label);
|
text(label);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
int selection_out = selection;
|
int selection_out = selection;
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
const char *selection_str = selection < int(options.size()) && selection >= 0 ? options[selection].c_str() : "";
|
const char *selection_str = selection < int(options.size()) && selection >= 0 ? options[selection].c_str() : "";
|
||||||
if (ImGui::BeginCombo("", selection_str)) {
|
if (ImGui::BeginCombo("", selection_str, flags)) {
|
||||||
for (int i = 0; i < (int)options.size(); i++) {
|
for (int i = 0; i < (int)options.size(); i++) {
|
||||||
if (ImGui::Selectable(options[i].c_str(), i == selection)) {
|
if (ImGui::Selectable(options[i].c_str(), i == selection)) {
|
||||||
selection_out = i;
|
selection_out = i;
|
||||||
@ -1010,6 +1135,34 @@ bool ImGuiWrapper::want_any_input() const
|
|||||||
return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput;
|
return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
ImFontAtlasCustomRect* ImGuiWrapper::GetTextureCustomRect(const wchar_t& tex_id)
|
||||||
|
{
|
||||||
|
auto item = m_custom_glyph_rects_ids.find(tex_id);
|
||||||
|
return (item != m_custom_glyph_rects_ids.end()) ? ImGui::GetIO().Fonts->GetCustomRectByIndex(m_custom_glyph_rects_ids[tex_id]) : nullptr;
|
||||||
|
}
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
|
||||||
|
ImU32 ImGuiWrapper::to_ImU32(const ColorRGBA& color)
|
||||||
|
{
|
||||||
|
return ImGui::GetColorU32({ color.r(), color.g(), color.b(), color.a() });
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec4 ImGuiWrapper::to_ImVec4(const ColorRGBA& color)
|
||||||
|
{
|
||||||
|
return { color.r(), color.g(), color.b(), color.a() };
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA ImGuiWrapper::from_ImU32(const ImU32& color)
|
||||||
|
{
|
||||||
|
return from_ImVec4(ImGui::ColorConvertU32ToFloat4(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorRGBA ImGuiWrapper::from_ImVec4(const ImVec4& color)
|
||||||
|
{
|
||||||
|
return { color.x, color.y, color.z, color.w };
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
static const ImWchar ranges_keyboard_shortcuts[] =
|
static const ImWchar ranges_keyboard_shortcuts[] =
|
||||||
{
|
{
|
||||||
@ -1098,12 +1251,27 @@ void ImGuiWrapper::init_font(bool compress)
|
|||||||
|
|
||||||
int rect_id = io.Fonts->CustomRects.Size; // id of the rectangle added next
|
int rect_id = io.Fonts->CustomRects.Size; // id of the rectangle added next
|
||||||
// add rectangles for the icons to the font atlas
|
// add rectangles for the icons to the font atlas
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
for (auto& icon : font_icons) {
|
||||||
|
m_custom_glyph_rects_ids[icon.first] =
|
||||||
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz);
|
||||||
|
}
|
||||||
|
for (auto& icon : font_icons_large) {
|
||||||
|
m_custom_glyph_rects_ids[icon.first] =
|
||||||
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 2, icon_sz * 2, 3.0 * font_scale + icon_sz * 2);
|
||||||
|
}
|
||||||
|
for (auto& icon : font_icons_extra_large) {
|
||||||
|
m_custom_glyph_rects_ids[icon.first] =
|
||||||
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4);
|
||||||
|
}
|
||||||
|
#else
|
||||||
for (auto& icon : font_icons)
|
for (auto& icon : font_icons)
|
||||||
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz);
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz, icon_sz, 3.0 * font_scale + icon_sz);
|
||||||
for (auto& icon : font_icons_large)
|
for (auto& icon : font_icons_large)
|
||||||
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 2, icon_sz * 2, 3.0 * font_scale + icon_sz * 2);
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 2, icon_sz * 2, 3.0 * font_scale + icon_sz * 2);
|
||||||
for (auto& icon : font_icons_extra_large)
|
for (auto& icon : font_icons_extra_large)
|
||||||
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4);
|
io.Fonts->AddCustomRectFontGlyph(font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4);
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
|
||||||
// Build texture atlas
|
// Build texture atlas
|
||||||
unsigned char* pixels;
|
unsigned char* pixels;
|
||||||
|
@ -9,15 +9,21 @@
|
|||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
|
#include "libslic3r/Color.hpp"
|
||||||
|
|
||||||
namespace Slic3r {namespace Search {
|
namespace Slic3r {
|
||||||
|
namespace Search {
|
||||||
struct OptionViewParameters;
|
struct OptionViewParameters;
|
||||||
}}
|
} // namespace Search
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
class wxString;
|
class wxString;
|
||||||
class wxMouseEvent;
|
class wxMouseEvent;
|
||||||
class wxKeyEvent;
|
class wxKeyEvent;
|
||||||
|
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
struct IMGUI_API ImGuiWindow;
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -34,6 +40,9 @@ class ImGuiWrapper
|
|||||||
bool m_disabled{ false };
|
bool m_disabled{ false };
|
||||||
bool m_new_frame_open{ false };
|
bool m_new_frame_open{ false };
|
||||||
bool m_requires_extra_frame{ false };
|
bool m_requires_extra_frame{ false };
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
std::map<wchar_t, int> m_custom_glyph_rects_ids;
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
std::string m_clipboard_text;
|
std::string m_clipboard_text;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -83,7 +92,9 @@ public:
|
|||||||
bool button(const wxString &label);
|
bool button(const wxString &label);
|
||||||
bool button(const wxString& label, float width, float height);
|
bool button(const wxString& label, float width, float height);
|
||||||
bool radio_button(const wxString &label, bool active);
|
bool radio_button(const wxString &label, bool active);
|
||||||
bool image_button();
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
bool draw_radio_button(const std::string& name, float size, bool active, std::function<void(ImGuiWindow& window, const ImVec2& pos, float size)> draw_callback);
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
|
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
|
||||||
bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f");
|
bool input_double(const wxString &label, const double &value, const std::string &format = "%.3f");
|
||||||
bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f");
|
bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f");
|
||||||
@ -106,7 +117,10 @@ public:
|
|||||||
bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
|
bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
|
||||||
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
|
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f, bool clamp = true, const wxString& tooltip = {}, bool show_edit_btn = true);
|
||||||
|
|
||||||
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
|
bool image_button(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0.0, 0.0), const ImVec2& uv1 = ImVec2(1.0, 1.0), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0.0, 0.0, 0.0, 0.0), const ImVec4& tint_col = ImVec4(1.0, 1.0, 1.0, 1.0), ImGuiButtonFlags flags = 0);
|
||||||
|
|
||||||
|
// Use selection = -1 to not mark any option as selected
|
||||||
|
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection, ImGuiComboFlags flags = 0);
|
||||||
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel);
|
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel);
|
||||||
void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
|
void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
|
||||||
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized);
|
Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized);
|
||||||
@ -124,6 +138,15 @@ public:
|
|||||||
void set_requires_extra_frame() { m_requires_extra_frame = true; }
|
void set_requires_extra_frame() { m_requires_extra_frame = true; }
|
||||||
void reset_requires_extra_frame() { m_requires_extra_frame = false; }
|
void reset_requires_extra_frame() { m_requires_extra_frame = false; }
|
||||||
|
|
||||||
|
static ImU32 to_ImU32(const ColorRGBA& color);
|
||||||
|
static ImVec4 to_ImVec4(const ColorRGBA& color);
|
||||||
|
static ColorRGBA from_ImU32(const ImU32& color);
|
||||||
|
static ColorRGBA from_ImVec4(const ImVec4& color);
|
||||||
|
|
||||||
|
#if ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
ImFontAtlasCustomRect* GetTextureCustomRect(const wchar_t& tex_id);
|
||||||
|
#endif // ENABLE_LEGEND_TOOLBAR_ICONS
|
||||||
|
|
||||||
static const ImVec4 COL_GREY_DARK;
|
static const ImVec4 COL_GREY_DARK;
|
||||||
static const ImVec4 COL_GREY_LIGHT;
|
static const ImVec4 COL_GREY_LIGHT;
|
||||||
static const ImVec4 COL_ORANGE_DARK;
|
static const ImVec4 COL_ORANGE_DARK;
|
||||||
|
@ -162,49 +162,43 @@ void ArrangeJob::prepare()
|
|||||||
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
|
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrangeJob::on_exception(const std::exception_ptr &eptr)
|
void ArrangeJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
try {
|
static const auto arrangestr = _u8L("Arranging");
|
||||||
if (eptr)
|
|
||||||
std::rethrow_exception(eptr);
|
|
||||||
} catch (libnest2d::GeometryException &) {
|
|
||||||
show_error(m_plater, _(L("Could not arrange model objects! "
|
|
||||||
"Some geometries may be invalid.")));
|
|
||||||
} catch (std::exception &) {
|
|
||||||
PlaterJob::on_exception(eptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArrangeJob::process()
|
ctl.update_status(0, arrangestr);
|
||||||
{
|
ctl.call_on_main_thread([this]{ prepare(); }).wait();;
|
||||||
static const auto arrangestr = _(L("Arranging"));
|
|
||||||
|
|
||||||
arrangement::ArrangeParams params = get_arrange_params(m_plater);
|
arrangement::ArrangeParams params = get_arrange_params(m_plater);
|
||||||
|
|
||||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||||
Points bedpts = get_bed_shape(*m_plater->config());
|
Points bedpts = get_bed_shape(*m_plater->config());
|
||||||
|
|
||||||
params.stopcondition = [this]() { return was_canceled(); };
|
params.stopcondition = [&ctl]() { return ctl.was_canceled(); };
|
||||||
|
|
||||||
params.progressind = [this, count](unsigned st) {
|
params.progressind = [this, count, &ctl](unsigned st) {
|
||||||
st += m_unprintable.size();
|
st += m_unprintable.size();
|
||||||
if (st > 0) update_status(int(count - st), arrangestr);
|
if (st > 0) ctl.update_status(int(count - st) * 100 / status_range(), arrangestr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ctl.update_status(0, arrangestr);
|
||||||
|
|
||||||
arrangement::arrange(m_selected, m_unselected, bedpts, params);
|
arrangement::arrange(m_selected, m_unselected, bedpts, params);
|
||||||
|
|
||||||
params.progressind = [this, count](unsigned st) {
|
params.progressind = [this, count, &ctl](unsigned st) {
|
||||||
if (st > 0) update_status(int(count - st), arrangestr);
|
if (st > 0) ctl.update_status(int(count - st) * 100 / status_range(), arrangestr);
|
||||||
};
|
};
|
||||||
|
|
||||||
arrangement::arrange(m_unprintable, {}, bedpts, params);
|
arrangement::arrange(m_unprintable, {}, bedpts, params);
|
||||||
|
|
||||||
// finalize just here.
|
// finalize just here.
|
||||||
update_status(int(count),
|
ctl.update_status(int(count) * 100 / status_range(), ctl.was_canceled() ?
|
||||||
was_canceled() ? _(L("Arranging canceled."))
|
_u8L("Arranging canceled.") :
|
||||||
: _(L("Arranging done.")));
|
_u8L("Arranging done."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrangeJob::ArrangeJob() : m_plater{wxGetApp().plater()} {}
|
||||||
|
|
||||||
static std::string concat_strings(const std::set<std::string> &strings,
|
static std::string concat_strings(const std::set<std::string> &strings,
|
||||||
const std::string &delim = "\n")
|
const std::string &delim = "\n")
|
||||||
{
|
{
|
||||||
@ -215,9 +209,20 @@ static std::string concat_strings(const std::set<std::string> &strings,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrangeJob::finalize() {
|
void ArrangeJob::finalize(bool canceled, std::exception_ptr &eptr) {
|
||||||
// Ignore the arrange result if aborted.
|
try {
|
||||||
if (was_canceled()) return;
|
if (eptr)
|
||||||
|
std::rethrow_exception(eptr);
|
||||||
|
} catch (libnest2d::GeometryException &) {
|
||||||
|
show_error(m_plater, _(L("Could not arrange model objects! "
|
||||||
|
"Some geometries may be invalid.")));
|
||||||
|
eptr = nullptr;
|
||||||
|
} catch(...) {
|
||||||
|
eptr = std::current_exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canceled || eptr)
|
||||||
|
return;
|
||||||
|
|
||||||
// Unprintable items go to the last virtual bed
|
// Unprintable items go to the last virtual bed
|
||||||
int beds = 0;
|
int beds = 0;
|
||||||
@ -250,8 +255,6 @@ void ArrangeJob::finalize() {
|
|||||||
_L("Arrangement ignored the following objects which can't fit into a single bed:\n%s"),
|
_L("Arrangement ignored the following objects which can't fit into a single bed:\n%s"),
|
||||||
concat_strings(names, "\n")));
|
concat_strings(names, "\n")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Job::finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<arrangement::ArrangePolygon>
|
std::optional<arrangement::ArrangePolygon>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#ifndef ARRANGEJOB_HPP
|
#ifndef ARRANGEJOB_HPP
|
||||||
#define ARRANGEJOB_HPP
|
#define ARRANGEJOB_HPP
|
||||||
|
|
||||||
#include "PlaterJob.hpp"
|
#include <optional>
|
||||||
|
|
||||||
|
#include "Job.hpp"
|
||||||
#include "libslic3r/Arrange.hpp"
|
#include "libslic3r/Arrange.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -10,13 +12,16 @@ class ModelInstance;
|
|||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
class ArrangeJob : public PlaterJob
|
class Plater;
|
||||||
|
|
||||||
|
class ArrangeJob : public Job
|
||||||
{
|
{
|
||||||
using ArrangePolygon = arrangement::ArrangePolygon;
|
using ArrangePolygon = arrangement::ArrangePolygon;
|
||||||
using ArrangePolygons = arrangement::ArrangePolygons;
|
using ArrangePolygons = arrangement::ArrangePolygons;
|
||||||
|
|
||||||
ArrangePolygons m_selected, m_unselected, m_unprintable;
|
ArrangePolygons m_selected, m_unselected, m_unprintable;
|
||||||
std::vector<ModelInstance*> m_unarranged;
|
std::vector<ModelInstance*> m_unarranged;
|
||||||
|
Plater *m_plater;
|
||||||
|
|
||||||
// clear m_selected and m_unselected, reserve space for next usage
|
// clear m_selected and m_unselected, reserve space for next usage
|
||||||
void clear_input();
|
void clear_input();
|
||||||
@ -30,25 +35,20 @@ class ArrangeJob : public PlaterJob
|
|||||||
|
|
||||||
ArrangePolygon get_arrange_poly_(ModelInstance *mi);
|
ArrangePolygon get_arrange_poly_(ModelInstance *mi);
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void prepare() override;
|
|
||||||
|
|
||||||
void on_exception(const std::exception_ptr &) override;
|
|
||||||
|
|
||||||
void process() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArrangeJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
|
||||||
: PlaterJob{std::move(pri), plater}
|
|
||||||
{}
|
|
||||||
|
|
||||||
int status_range() const override
|
void prepare();
|
||||||
|
|
||||||
|
void process(Ctl &ctl) override;
|
||||||
|
|
||||||
|
ArrangeJob();
|
||||||
|
|
||||||
|
int status_range() const
|
||||||
{
|
{
|
||||||
return int(m_selected.size() + m_unprintable.size());
|
return int(m_selected.size() + m_unprintable.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalize() override;
|
void finalize(bool canceled, std::exception_ptr &e) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<arrangement::ArrangePolygon> get_wipe_tower_arrangepoly(const Plater &);
|
std::optional<arrangement::ArrangePolygon> get_wipe_tower_arrangepoly(const Plater &);
|
||||||
|
181
src/slic3r/GUI/Jobs/BoostThreadWorker.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "BoostThreadWorker.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
void BoostThreadWorker::WorkerMessage::deliver(BoostThreadWorker &runner)
|
||||||
|
{
|
||||||
|
switch(MsgType(get_type())) {
|
||||||
|
case Empty: break;
|
||||||
|
case Status: {
|
||||||
|
auto info = boost::get<StatusInfo>(m_data);
|
||||||
|
if (runner.get_pri()) {
|
||||||
|
runner.get_pri()->set_progress(info.status);
|
||||||
|
runner.get_pri()->set_status_text(info.msg.c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Finalize: {
|
||||||
|
auto& entry = boost::get<JobEntry>(m_data);
|
||||||
|
entry.job->finalize(entry.canceled, entry.eptr);
|
||||||
|
|
||||||
|
// Unhandled exceptions are rethrown without mercy.
|
||||||
|
if (entry.eptr)
|
||||||
|
std::rethrow_exception(entry.eptr);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MainThreadCall: {
|
||||||
|
auto &calldata = boost::get<MainThreadCallData >(m_data);
|
||||||
|
calldata.fn();
|
||||||
|
calldata.promise.set_value();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostThreadWorker::run()
|
||||||
|
{
|
||||||
|
bool stop = false;
|
||||||
|
while (!stop) {
|
||||||
|
m_input_queue
|
||||||
|
.consume_one(BlockingWait{0, &m_running}, [this, &stop](JobEntry &e) {
|
||||||
|
if (!e.job)
|
||||||
|
stop = true;
|
||||||
|
else {
|
||||||
|
m_canceled.store(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
e.job->process(*this);
|
||||||
|
} catch (...) {
|
||||||
|
e.eptr = std::current_exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
e.canceled = m_canceled.load();
|
||||||
|
m_output_queue.push(std::move(e)); // finalization message
|
||||||
|
}
|
||||||
|
m_running.store(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostThreadWorker::update_status(int st, const std::string &msg)
|
||||||
|
{
|
||||||
|
m_output_queue.push(st, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<void> BoostThreadWorker::call_on_main_thread(std::function<void ()> fn)
|
||||||
|
{
|
||||||
|
MainThreadCallData cbdata{std::move(fn), {}};
|
||||||
|
std::future<void> future = cbdata.promise.get_future();
|
||||||
|
|
||||||
|
m_output_queue.push(std::move(cbdata));
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoostThreadWorker::BoostThreadWorker(std::shared_ptr<ProgressIndicator> pri,
|
||||||
|
boost::thread::attributes &attribs,
|
||||||
|
const char * name)
|
||||||
|
: m_progress(std::move(pri)), m_name{name}
|
||||||
|
{
|
||||||
|
if (m_progress)
|
||||||
|
m_progress->set_cancel_callback([this](){ cancel(); });
|
||||||
|
|
||||||
|
m_thread = create_thread(attribs, [this] { this->run(); });
|
||||||
|
|
||||||
|
std::string nm{name};
|
||||||
|
if (!nm.empty()) set_thread_name(m_thread, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int ABORT_WAIT_MAX_MS = 10000;
|
||||||
|
|
||||||
|
BoostThreadWorker::~BoostThreadWorker()
|
||||||
|
{
|
||||||
|
bool joined = false;
|
||||||
|
try {
|
||||||
|
cancel_all();
|
||||||
|
wait_for_idle(ABORT_WAIT_MAX_MS);
|
||||||
|
m_input_queue.push(JobEntry{nullptr});
|
||||||
|
joined = join(ABORT_WAIT_MAX_MS);
|
||||||
|
} catch(...) {}
|
||||||
|
|
||||||
|
if (!joined)
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< "Could not join worker thread '" << m_name << "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoostThreadWorker::join(int timeout_ms)
|
||||||
|
{
|
||||||
|
if (!m_thread.joinable())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (timeout_ms <= 0) {
|
||||||
|
m_thread.join();
|
||||||
|
}
|
||||||
|
else if (m_thread.try_join_for(boost::chrono::milliseconds(timeout_ms))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoostThreadWorker::process_events()
|
||||||
|
{
|
||||||
|
while (m_output_queue.consume_one([this](WorkerMessage &msg) {
|
||||||
|
msg.deliver(*this);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoostThreadWorker::wait_for_current_job(unsigned timeout_ms)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!is_idle()) {
|
||||||
|
bool was_finish = false;
|
||||||
|
bool timeout_reached = false;
|
||||||
|
while (!timeout_reached && !was_finish) {
|
||||||
|
timeout_reached =
|
||||||
|
!m_output_queue.consume_one(BlockingWait{timeout_ms},
|
||||||
|
[this, &was_finish](
|
||||||
|
WorkerMessage &msg) {
|
||||||
|
msg.deliver(*this);
|
||||||
|
if (msg.get_type() ==
|
||||||
|
WorkerMessage::Finalize)
|
||||||
|
was_finish = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = !timeout_reached;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoostThreadWorker::wait_for_idle(unsigned timeout_ms)
|
||||||
|
{
|
||||||
|
bool timeout_reached = false;
|
||||||
|
while (!timeout_reached && !is_idle()) {
|
||||||
|
timeout_reached = !m_output_queue
|
||||||
|
.consume_one(BlockingWait{timeout_ms},
|
||||||
|
[this](WorkerMessage &msg) {
|
||||||
|
msg.deliver(*this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return !timeout_reached;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoostThreadWorker::push(std::unique_ptr<Job> job)
|
||||||
|
{
|
||||||
|
if (job)
|
||||||
|
m_input_queue.push(JobEntry{std::move(job)});
|
||||||
|
|
||||||
|
return bool{job};
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
140
src/slic3r/GUI/Jobs/BoostThreadWorker.hpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#ifndef BOOSTTHREADWORKER_HPP
|
||||||
|
#define BOOSTTHREADWORKER_HPP
|
||||||
|
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
|
#include "Worker.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/Thread.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
#include "ThreadSafeQueue.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
// An implementation of the Worker interface which uses the boost::thread
|
||||||
|
// API and two thread safe message queues to communicate with the main thread
|
||||||
|
// back and forth. The queue from the main thread to the worker thread holds the
|
||||||
|
// job entries that will be performed on the worker. The other queue holds messages
|
||||||
|
// from the worker to the main thread. These messages include status updates,
|
||||||
|
// finishing operation and arbitrary functiors that need to be performed
|
||||||
|
// on the main thread during the jobs execution, like displaying intermediate
|
||||||
|
// results.
|
||||||
|
class BoostThreadWorker : public Worker, private Job::Ctl
|
||||||
|
{
|
||||||
|
struct JobEntry // Goes into worker and also out of worker as a finalize msg
|
||||||
|
{
|
||||||
|
std::unique_ptr<Job> job;
|
||||||
|
bool canceled = false;
|
||||||
|
std::exception_ptr eptr = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A message data for status updates. Only goes from worker to main thread.
|
||||||
|
struct StatusInfo { int status; std::string msg; };
|
||||||
|
|
||||||
|
// An arbitrary callback to be called on the main thread. Only from worker
|
||||||
|
// to main thread.
|
||||||
|
struct MainThreadCallData
|
||||||
|
{
|
||||||
|
std::function<void()> fn;
|
||||||
|
std::promise<void> promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EmptyMessage {};
|
||||||
|
|
||||||
|
class WorkerMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MsgType { Empty, Status, Finalize, MainThreadCall };
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::variant<EmptyMessage, StatusInfo, JobEntry, MainThreadCallData> m_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WorkerMessage() = default;
|
||||||
|
WorkerMessage(int s, std::string txt)
|
||||||
|
: m_data{StatusInfo{s, std::move(txt)}}
|
||||||
|
{}
|
||||||
|
WorkerMessage(JobEntry &&entry) : m_data{std::move(entry)} {}
|
||||||
|
WorkerMessage(MainThreadCallData fn) : m_data{std::move(fn)} {}
|
||||||
|
|
||||||
|
int get_type () const { return m_data.which(); }
|
||||||
|
|
||||||
|
void deliver(BoostThreadWorker &runner);
|
||||||
|
};
|
||||||
|
|
||||||
|
using JobQueue = ThreadSafeQueueSPSC<JobEntry>;
|
||||||
|
using MessageQueue = ThreadSafeQueueSPSC<WorkerMessage>;
|
||||||
|
|
||||||
|
boost::thread m_thread;
|
||||||
|
std::atomic<bool> m_running{false}, m_canceled{false};
|
||||||
|
std::shared_ptr<ProgressIndicator> m_progress;
|
||||||
|
JobQueue m_input_queue; // from main thread to worker
|
||||||
|
MessageQueue m_output_queue; // form worker to main thread
|
||||||
|
std::string m_name;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
|
||||||
|
bool join(int timeout_ms = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Implement Job::Ctl interface:
|
||||||
|
|
||||||
|
void update_status(int st, const std::string &msg = "") override;
|
||||||
|
|
||||||
|
bool was_canceled() const override { return m_canceled.load(); }
|
||||||
|
|
||||||
|
std::future<void> call_on_main_thread(std::function<void()> fn) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BoostThreadWorker(std::shared_ptr<ProgressIndicator> pri,
|
||||||
|
boost::thread::attributes & attr,
|
||||||
|
const char * name = "");
|
||||||
|
|
||||||
|
explicit BoostThreadWorker(std::shared_ptr<ProgressIndicator> pri,
|
||||||
|
boost::thread::attributes && attr,
|
||||||
|
const char * name = "")
|
||||||
|
: BoostThreadWorker{std::move(pri), attr, name}
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit BoostThreadWorker(std::shared_ptr<ProgressIndicator> pri,
|
||||||
|
const char * name = "")
|
||||||
|
: BoostThreadWorker{std::move(pri), {}, name}
|
||||||
|
{}
|
||||||
|
|
||||||
|
~BoostThreadWorker();
|
||||||
|
|
||||||
|
BoostThreadWorker(const BoostThreadWorker &) = delete;
|
||||||
|
BoostThreadWorker(BoostThreadWorker &&) = delete;
|
||||||
|
BoostThreadWorker &operator=(const BoostThreadWorker &) = delete;
|
||||||
|
BoostThreadWorker &operator=(BoostThreadWorker &&) = delete;
|
||||||
|
|
||||||
|
bool push(std::unique_ptr<Job> job) override;
|
||||||
|
|
||||||
|
bool is_idle() const override
|
||||||
|
{
|
||||||
|
// The assumption is that jobs can only be queued from a single main
|
||||||
|
// thread from which this method is also called. And the output
|
||||||
|
// messages are also processed only in this calling thread. In that
|
||||||
|
// case, if the input queue is empty, it will remain so during this
|
||||||
|
// function call. If the worker thread is also not running and the
|
||||||
|
// output queue is already processed, we can safely say that the
|
||||||
|
// worker is dormant.
|
||||||
|
return m_input_queue.empty() && !m_running.load() && m_output_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel() override { m_canceled.store(true); }
|
||||||
|
void cancel_all() override { m_input_queue.clear(); cancel(); }
|
||||||
|
|
||||||
|
ProgressIndicator * get_pri() { return m_progress.get(); }
|
||||||
|
const ProgressIndicator * get_pri() const { return m_progress.get(); }
|
||||||
|
|
||||||
|
void process_events() override;
|
||||||
|
bool wait_for_current_job(unsigned timeout_ms = 0) override;
|
||||||
|
bool wait_for_idle(unsigned timeout_ms = 0) override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // BOOSTTHREADWORKER_HPP
|
48
src/slic3r/GUI/Jobs/BusyCursorJob.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef BUSYCURSORJOB_HPP
|
||||||
|
#define BUSYCURSORJOB_HPP
|
||||||
|
|
||||||
|
#include "Job.hpp"
|
||||||
|
|
||||||
|
#include <wx/utils.h>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
struct CursorSetterRAII
|
||||||
|
{
|
||||||
|
Job::Ctl &ctl;
|
||||||
|
CursorSetterRAII(Job::Ctl &c) : ctl{c}
|
||||||
|
{
|
||||||
|
ctl.call_on_main_thread([] { wxBeginBusyCursor(); });
|
||||||
|
}
|
||||||
|
~CursorSetterRAII()
|
||||||
|
{
|
||||||
|
ctl.call_on_main_thread([] { wxEndBusyCursor(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class JobSubclass>
|
||||||
|
class BusyCursored: public Job {
|
||||||
|
JobSubclass m_job;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<class... Args>
|
||||||
|
BusyCursored(Args &&...args) : m_job{std::forward<Args>(args)...}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void process(Ctl &ctl) override
|
||||||
|
{
|
||||||
|
CursorSetterRAII cursor_setter{ctl};
|
||||||
|
m_job.process(ctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalize(bool canceled, std::exception_ptr &eptr) override
|
||||||
|
{
|
||||||
|
m_job.finalize(canceled, eptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUSYCURSORJOB_HPP
|
@ -3,6 +3,7 @@
|
|||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
|
|
||||||
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
@ -102,8 +103,12 @@ void FillBedJob::prepare()
|
|||||||
p.translation(X) -= p.bed_idx * stride;
|
p.translation(X) -= p.bed_idx * stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FillBedJob::process()
|
void FillBedJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
|
auto statustxt = _u8L("Filling bed");
|
||||||
|
ctl.call_on_main_thread([this] { prepare(); }).wait();
|
||||||
|
ctl.update_status(0, statustxt);
|
||||||
|
|
||||||
if (m_object_idx == -1 || m_selected.empty()) return;
|
if (m_object_idx == -1 || m_selected.empty()) return;
|
||||||
|
|
||||||
const GLCanvas3D::ArrangeSettings &settings =
|
const GLCanvas3D::ArrangeSettings &settings =
|
||||||
@ -114,13 +119,13 @@ void FillBedJob::process()
|
|||||||
params.min_obj_distance = scaled(settings.distance);
|
params.min_obj_distance = scaled(settings.distance);
|
||||||
|
|
||||||
bool do_stop = false;
|
bool do_stop = false;
|
||||||
params.stopcondition = [this, &do_stop]() {
|
params.stopcondition = [&ctl, &do_stop]() {
|
||||||
return was_canceled() || do_stop;
|
return ctl.was_canceled() || do_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
params.progressind = [this](unsigned st) {
|
params.progressind = [this, &ctl, &statustxt](unsigned st) {
|
||||||
if (st > 0)
|
if (st > 0)
|
||||||
update_status(int(m_status_range - st), _(L("Filling bed")));
|
ctl.update_status(int(m_status_range - st) * 100 / status_range(), statustxt);
|
||||||
};
|
};
|
||||||
|
|
||||||
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
|
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
|
||||||
@ -130,15 +135,18 @@ void FillBedJob::process()
|
|||||||
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
|
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
|
||||||
|
|
||||||
// finalize just here.
|
// finalize just here.
|
||||||
update_status(m_status_range, was_canceled() ?
|
ctl.update_status(100, ctl.was_canceled() ?
|
||||||
_(L("Bed filling canceled.")) :
|
_u8L("Bed filling canceled.") :
|
||||||
_(L("Bed filling done.")));
|
_u8L("Bed filling done."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FillBedJob::finalize()
|
FillBedJob::FillBedJob() : m_plater{wxGetApp().plater()} {}
|
||||||
|
|
||||||
|
void FillBedJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
// Ignore the arrange result if aborted.
|
// Ignore the arrange result if aborted.
|
||||||
if (was_canceled()) return;
|
if (canceled || eptr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_object_idx == -1) return;
|
if (m_object_idx == -1) return;
|
||||||
|
|
||||||
@ -167,8 +175,6 @@ void FillBedJob::finalize()
|
|||||||
m_plater->sidebar()
|
m_plater->sidebar()
|
||||||
.obj_list()->increase_object_instances(m_object_idx, size_t(added_cnt));
|
.obj_list()->increase_object_instances(m_object_idx, size_t(added_cnt));
|
||||||
}
|
}
|
||||||
|
|
||||||
Job::finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
@ -7,7 +7,7 @@ namespace Slic3r { namespace GUI {
|
|||||||
|
|
||||||
class Plater;
|
class Plater;
|
||||||
|
|
||||||
class FillBedJob : public PlaterJob
|
class FillBedJob : public Job
|
||||||
{
|
{
|
||||||
int m_object_idx = -1;
|
int m_object_idx = -1;
|
||||||
|
|
||||||
@ -20,23 +20,20 @@ class FillBedJob : public PlaterJob
|
|||||||
Points m_bedpts;
|
Points m_bedpts;
|
||||||
|
|
||||||
int m_status_range = 0;
|
int m_status_range = 0;
|
||||||
|
Plater *m_plater;
|
||||||
protected:
|
|
||||||
|
|
||||||
void prepare() override;
|
|
||||||
void process() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FillBedJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
void prepare();
|
||||||
: PlaterJob{std::move(pri), plater}
|
void process(Ctl &ctl) override;
|
||||||
{}
|
|
||||||
|
|
||||||
int status_range() const override
|
FillBedJob();
|
||||||
|
|
||||||
|
int status_range() const /*override*/
|
||||||
{
|
{
|
||||||
return m_status_range;
|
return m_status_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalize() override;
|
void finalize(bool canceled, std::exception_ptr &e) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
@ -1,158 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#include "Job.hpp"
|
|
||||||
#include <libslic3r/Thread.hpp>
|
|
||||||
#include <boost/log/trivial.hpp>
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
void GUI::Job::run(std::exception_ptr &eptr)
|
|
||||||
{
|
|
||||||
m_running.store(true);
|
|
||||||
try {
|
|
||||||
process();
|
|
||||||
} catch (...) {
|
|
||||||
eptr = std::current_exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_running.store(false);
|
|
||||||
|
|
||||||
// ensure to call the last status to finalize the job
|
|
||||||
update_status(status_range(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI::Job::update_status(int st, const wxString &msg)
|
|
||||||
{
|
|
||||||
auto evt = new wxThreadEvent(wxEVT_THREAD, m_thread_evt_id);
|
|
||||||
evt->SetInt(st);
|
|
||||||
evt->SetString(msg);
|
|
||||||
wxQueueEvent(this, evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI::Job::Job(std::shared_ptr<ProgressIndicator> pri)
|
|
||||||
: m_progress(std::move(pri))
|
|
||||||
{
|
|
||||||
m_thread_evt_id = wxNewId();
|
|
||||||
|
|
||||||
Bind(wxEVT_THREAD, [this](const wxThreadEvent &evt) {
|
|
||||||
if (m_finalizing) return;
|
|
||||||
|
|
||||||
auto msg = evt.GetString();
|
|
||||||
if (!msg.empty() && !m_worker_error)
|
|
||||||
m_progress->set_status_text(msg.ToUTF8().data());
|
|
||||||
|
|
||||||
if (m_finalized) return;
|
|
||||||
|
|
||||||
m_progress->set_progress(evt.GetInt());
|
|
||||||
if (evt.GetInt() == status_range() || m_worker_error) {
|
|
||||||
// set back the original range and cancel callback
|
|
||||||
m_progress->set_range(m_range);
|
|
||||||
// Make sure progress indicators get the last value of their range
|
|
||||||
// to make sure they close, fade out, whathever
|
|
||||||
m_progress->set_progress(m_range);
|
|
||||||
m_progress->set_cancel_callback();
|
|
||||||
wxEndBusyCursor();
|
|
||||||
|
|
||||||
if (m_worker_error) {
|
|
||||||
m_finalized = true;
|
|
||||||
m_progress->set_status_text("");
|
|
||||||
m_progress->set_progress(m_range);
|
|
||||||
on_exception(m_worker_error);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// This is an RAII solution to remember that finalization is
|
|
||||||
// running. The run method calls update_status(status_range(), "")
|
|
||||||
// at the end, which queues up a call to this handler in all cases.
|
|
||||||
// If process also calls update_status with maxed out status arg
|
|
||||||
// it will call this handler twice. It is not a problem unless
|
|
||||||
// yield is called inside the finilize() method, which would
|
|
||||||
// jump out of finalize and call this handler again.
|
|
||||||
struct Finalizing {
|
|
||||||
bool &flag;
|
|
||||||
Finalizing (bool &f): flag(f) { flag = true; }
|
|
||||||
~Finalizing() { flag = false; }
|
|
||||||
} fin(m_finalizing);
|
|
||||||
|
|
||||||
finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// dont do finalization again for the same process
|
|
||||||
m_finalized = true;
|
|
||||||
}
|
|
||||||
}, m_thread_evt_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI::Job::start()
|
|
||||||
{ // Start the job. No effect if the job is already running
|
|
||||||
if (!m_running.load()) {
|
|
||||||
prepare();
|
|
||||||
|
|
||||||
// Save the current status indicatior range and push the new one
|
|
||||||
m_range = m_progress->get_range();
|
|
||||||
m_progress->set_range(status_range());
|
|
||||||
|
|
||||||
// init cancellation flag and set the cancel callback
|
|
||||||
m_canceled.store(false);
|
|
||||||
m_progress->set_cancel_callback(
|
|
||||||
[this]() { m_canceled.store(true); });
|
|
||||||
|
|
||||||
m_finalized = false;
|
|
||||||
m_finalizing = false;
|
|
||||||
|
|
||||||
// Changing cursor to busy
|
|
||||||
wxBeginBusyCursor();
|
|
||||||
|
|
||||||
try { // Execute the job
|
|
||||||
m_worker_error = nullptr;
|
|
||||||
m_thread = create_thread([this] { this->run(m_worker_error); });
|
|
||||||
} catch (std::exception &) {
|
|
||||||
update_status(status_range(),
|
|
||||||
_(L("ERROR: not enough resources to "
|
|
||||||
"execute a new job.")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The state changes will be undone when the process hits the
|
|
||||||
// last status value, in the status update handler (see ctor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUI::Job::join(int timeout_ms)
|
|
||||||
{
|
|
||||||
if (!m_thread.joinable()) return true;
|
|
||||||
|
|
||||||
if (timeout_ms <= 0)
|
|
||||||
m_thread.join();
|
|
||||||
else if (!m_thread.try_join_for(boost::chrono::milliseconds(timeout_ms)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI::ExclusiveJobGroup::start(size_t jid) {
|
|
||||||
assert(jid < m_jobs.size());
|
|
||||||
stop_all();
|
|
||||||
m_jobs[jid]->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI::ExclusiveJobGroup::join_all(int wait_ms)
|
|
||||||
{
|
|
||||||
std::vector<bool> aborted(m_jobs.size(), false);
|
|
||||||
|
|
||||||
for (size_t jid = 0; jid < m_jobs.size(); ++jid)
|
|
||||||
aborted[jid] = m_jobs[jid]->join(wait_ms);
|
|
||||||
|
|
||||||
if (!std::all_of(aborted.begin(), aborted.end(), [](bool t) { return t; }))
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "Could not abort a job!";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUI::ExclusiveJobGroup::is_any_running() const
|
|
||||||
{
|
|
||||||
return std::any_of(m_jobs.begin(), m_jobs.end(),
|
|
||||||
[](const std::unique_ptr<GUI::Job> &j) {
|
|
||||||
return j->is_running();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -3,119 +3,53 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include <slic3r/GUI/I18N.hpp>
|
|
||||||
|
|
||||||
#include "ProgressIndicator.hpp"
|
#include "ProgressIndicator.hpp"
|
||||||
|
|
||||||
#include <wx/event.h>
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
// A class to handle UI jobs like arranging and optimizing rotation.
|
// A class representing a job that is to be run in the background, not blocking
|
||||||
// These are not instant jobs, the user has to be informed about their
|
// the main thread. Running it is up to a Worker object (see Worker interface)
|
||||||
// state in the status progress indicator. On the other hand they are
|
class Job {
|
||||||
// separated from the background slicing process. Ideally, these jobs should
|
public:
|
||||||
// run when the background process is not running.
|
|
||||||
//
|
|
||||||
// TODO: A mechanism would be useful for blocking the plater interactions:
|
|
||||||
// objects would be frozen for the user. In case of arrange, an animation
|
|
||||||
// could be shown, or with the optimize orientations, partial results
|
|
||||||
// could be displayed.
|
|
||||||
class Job : public wxEvtHandler
|
|
||||||
{
|
|
||||||
int m_range = 100;
|
|
||||||
int m_thread_evt_id = wxID_ANY;
|
|
||||||
boost::thread m_thread;
|
|
||||||
std::atomic<bool> m_running{false}, m_canceled{false};
|
|
||||||
bool m_finalized = false, m_finalizing = false;
|
|
||||||
std::shared_ptr<ProgressIndicator> m_progress;
|
|
||||||
std::exception_ptr m_worker_error = nullptr;
|
|
||||||
|
|
||||||
void run(std::exception_ptr &);
|
// A controller interface that informs the job about cancellation and
|
||||||
|
// makes it possible for the job to advertise its status.
|
||||||
protected:
|
class Ctl {
|
||||||
// status range for a particular job
|
public:
|
||||||
virtual int status_range() const { return 100; }
|
virtual ~Ctl() = default;
|
||||||
|
|
||||||
// status update, to be used from the work thread (process() method)
|
// status update, to be used from the work thread (process() method)
|
||||||
void update_status(int st, const wxString &msg = "");
|
virtual void update_status(int st, const std::string &msg = "") = 0;
|
||||||
|
|
||||||
bool was_canceled() const { return m_canceled.load(); }
|
// Returns true if the job was asked to cancel itself.
|
||||||
|
virtual bool was_canceled() const = 0;
|
||||||
|
|
||||||
// Launched just before start(), a job can use it to prepare internals
|
// Execute a functor on the main thread. Note that the exact time of
|
||||||
virtual void prepare() {}
|
// execution is hard to determine. This can be used to make modifications
|
||||||
|
// on the UI, like displaying some intermediate results or modify the
|
||||||
|
// cursor.
|
||||||
|
// This function returns a std::future<void> object which enables the
|
||||||
|
// caller to optionally wait for the main thread to finish the function call.
|
||||||
|
virtual std::future<void> call_on_main_thread(std::function<void()> fn) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// The method where the actual work of the job should be defined.
|
virtual ~Job() = default;
|
||||||
virtual void process() = 0;
|
|
||||||
|
|
||||||
// Launched when the job is finished. It refreshes the 3Dscene by def.
|
// The method where the actual work of the job should be defined. This is
|
||||||
virtual void finalize() { m_finalized = true; }
|
// run on the worker thread.
|
||||||
|
virtual void process(Ctl &ctl) = 0;
|
||||||
|
|
||||||
|
// Launched when the job is finished on the UI thread.
|
||||||
|
// If the job was cancelled, the first parameter will have a true value.
|
||||||
// Exceptions occuring in process() are redirected from the worker thread
|
// Exceptions occuring in process() are redirected from the worker thread
|
||||||
// into the main (UI) thread. This method is called from the main thread and
|
// into the main (UI) thread. This method receives the exception and can
|
||||||
// can be overriden to handle these exceptions.
|
// handle it properly. Assign nullptr to this second argument before
|
||||||
virtual void on_exception(const std::exception_ptr &eptr)
|
// function return to prevent further action. Leaving it with a non-null
|
||||||
{
|
// value will result in rethrowing by the worker.
|
||||||
if (eptr) std::rethrow_exception(eptr);
|
virtual void finalize(bool /*canceled*/, std::exception_ptr &) {}
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Job(std::shared_ptr<ProgressIndicator> pri);
|
|
||||||
|
|
||||||
bool is_finalized() const { return m_finalized; }
|
|
||||||
|
|
||||||
Job(const Job &) = delete;
|
|
||||||
Job(Job &&) = delete;
|
|
||||||
Job &operator=(const Job &) = delete;
|
|
||||||
Job &operator=(Job &&) = delete;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
|
|
||||||
// To wait for the running job and join the threads. False is
|
|
||||||
// returned if the timeout has been reached and the job is still
|
|
||||||
// running. Call cancel() before this fn if you want to explicitly
|
|
||||||
// end the job.
|
|
||||||
bool join(int timeout_ms = 0);
|
|
||||||
|
|
||||||
bool is_running() const { return m_running.load(); }
|
|
||||||
void cancel() { m_canceled.store(true); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Jobs defined inside the group class will be managed so that only one can
|
|
||||||
// run at a time. Also, the background process will be stopped if a job is
|
|
||||||
// started.
|
|
||||||
class ExclusiveJobGroup
|
|
||||||
{
|
|
||||||
static const int ABORT_WAIT_MAX_MS = 10000;
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<GUI::Job>> m_jobs;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void before_start() {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~ExclusiveJobGroup() = default;
|
|
||||||
|
|
||||||
size_t add_job(std::unique_ptr<GUI::Job> &&job)
|
|
||||||
{
|
|
||||||
m_jobs.emplace_back(std::move(job));
|
|
||||||
return m_jobs.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start(size_t jid);
|
|
||||||
|
|
||||||
void cancel_all() { for (auto& j : m_jobs) j->cancel(); }
|
|
||||||
|
|
||||||
void join_all(int wait_ms = 0);
|
|
||||||
|
|
||||||
void stop_all() { cancel_all(); join_all(ABORT_WAIT_MAX_MS); }
|
|
||||||
|
|
||||||
bool is_any_running() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
@ -12,11 +12,15 @@ void NotificationProgressIndicator::set_range(int range)
|
|||||||
|
|
||||||
void NotificationProgressIndicator::set_cancel_callback(CancelFn fn)
|
void NotificationProgressIndicator::set_cancel_callback(CancelFn fn)
|
||||||
{
|
{
|
||||||
m_nm->progress_indicator_set_cancel_callback(std::move(fn));
|
m_cancelfn = std::move(fn);
|
||||||
|
m_nm->progress_indicator_set_cancel_callback(m_cancelfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationProgressIndicator::set_progress(int pr)
|
void NotificationProgressIndicator::set_progress(int pr)
|
||||||
{
|
{
|
||||||
|
if (!pr)
|
||||||
|
set_cancel_callback(m_cancelfn);
|
||||||
|
|
||||||
m_nm->progress_indicator_set_progress(pr);
|
m_nm->progress_indicator_set_progress(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class NotificationManager;
|
|||||||
|
|
||||||
class NotificationProgressIndicator: public ProgressIndicator {
|
class NotificationProgressIndicator: public ProgressIndicator {
|
||||||
NotificationManager *m_nm = nullptr;
|
NotificationManager *m_nm = nullptr;
|
||||||
|
CancelFn m_cancelfn;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit NotificationProgressIndicator(NotificationManager *nm);
|
explicit NotificationProgressIndicator(NotificationManager *nm);
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
#include "PlaterJob.hpp"
|
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
|
||||||
|
|
||||||
void PlaterJob::on_exception(const std::exception_ptr &eptr)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (eptr)
|
|
||||||
std::rethrow_exception(eptr);
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
show_error(m_plater, _(L("An unexpected error occured")) + ": "+ e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef PLATERJOB_HPP
|
|
||||||
#define PLATERJOB_HPP
|
|
||||||
|
|
||||||
#include "Job.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
|
||||||
|
|
||||||
class Plater;
|
|
||||||
|
|
||||||
class PlaterJob : public Job {
|
|
||||||
protected:
|
|
||||||
Plater *m_plater;
|
|
||||||
|
|
||||||
void on_exception(const std::exception_ptr &) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
PlaterJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater):
|
|
||||||
Job{std::move(pri)}, m_plater{plater} {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
|
||||||
|
|
||||||
#endif // PLATERJOB_HPP
|
|
127
src/slic3r/GUI/Jobs/PlaterWorker.hpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#ifndef PLATERWORKER_HPP
|
||||||
|
#define PLATERWORKER_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Worker.hpp"
|
||||||
|
#include "BusyCursorJob.hpp"
|
||||||
|
|
||||||
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
class Plater;
|
||||||
|
|
||||||
|
template<class WorkerSubclass>
|
||||||
|
class PlaterWorker: public Worker {
|
||||||
|
WorkerSubclass m_w;
|
||||||
|
Plater *m_plater;
|
||||||
|
|
||||||
|
class PlaterJob : public Job {
|
||||||
|
std::unique_ptr<Job> m_job;
|
||||||
|
Plater *m_plater;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void process(Ctl &c) override
|
||||||
|
{
|
||||||
|
// Ensure that wxWidgets processing wakes up to handle outgoing
|
||||||
|
// messages in plater's wxIdle handler. Otherwise it might happen
|
||||||
|
// that the message will only be processed when an event like mouse
|
||||||
|
// move comes along which might be too late.
|
||||||
|
struct WakeUpCtl: Ctl {
|
||||||
|
Ctl &ctl;
|
||||||
|
WakeUpCtl(Ctl &c) : ctl{c} {}
|
||||||
|
|
||||||
|
void update_status(int st, const std::string &msg = "") override
|
||||||
|
{
|
||||||
|
wxWakeUpIdle();
|
||||||
|
ctl.update_status(st, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool was_canceled() const override { return ctl.was_canceled(); }
|
||||||
|
|
||||||
|
std::future<void> call_on_main_thread(std::function<void()> fn) override
|
||||||
|
{
|
||||||
|
wxWakeUpIdle();
|
||||||
|
return ctl.call_on_main_thread(std::move(fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
} wctl{c};
|
||||||
|
|
||||||
|
CursorSetterRAII busycursor{wctl};
|
||||||
|
m_job->process(wctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalize(bool canceled, std::exception_ptr &eptr) override
|
||||||
|
{
|
||||||
|
m_job->finalize(canceled, eptr);
|
||||||
|
|
||||||
|
if (eptr) try {
|
||||||
|
std::rethrow_exception(eptr);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
show_error(m_plater, _L("An unexpected error occured: ") + e.what());
|
||||||
|
eptr = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlaterJob(Plater *p, std::unique_ptr<Job> j)
|
||||||
|
: m_job{std::move(j)}, m_plater{p}
|
||||||
|
{
|
||||||
|
// TODO: decide if disabling slice button during UI job is what we
|
||||||
|
// want.
|
||||||
|
// if (m_plater)
|
||||||
|
// m_plater->sidebar().enable_buttons(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~PlaterJob() override
|
||||||
|
{
|
||||||
|
// TODO: decide if disabling slice button during UI job is what we want.
|
||||||
|
|
||||||
|
// Reload scene ensures that the slice button gets properly
|
||||||
|
// enabled or disabled after the job finishes, depending on the
|
||||||
|
// state of slicing. This might be an overkill but works for now.
|
||||||
|
// if (m_plater)
|
||||||
|
// m_plater->canvas3D()->reload_scene(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<class... WorkerArgs>
|
||||||
|
PlaterWorker(Plater *plater, WorkerArgs &&...args)
|
||||||
|
: m_w{std::forward<WorkerArgs>(args)...}, m_plater{plater}
|
||||||
|
{
|
||||||
|
// Ensure that messages from the worker thread to the UI thread are
|
||||||
|
// processed continuously.
|
||||||
|
plater->Bind(wxEVT_IDLE, [this](wxIdleEvent &) {
|
||||||
|
process_events();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always package the job argument into a PlaterJob
|
||||||
|
bool push(std::unique_ptr<Job> job) override
|
||||||
|
{
|
||||||
|
return m_w.push(std::make_unique<PlaterJob>(m_plater, std::move(job)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_idle() const override { return m_w.is_idle(); }
|
||||||
|
void cancel() override { m_w.cancel(); }
|
||||||
|
void cancel_all() override { m_w.cancel_all(); }
|
||||||
|
void process_events() override { m_w.process_events(); }
|
||||||
|
bool wait_for_current_job(unsigned timeout_ms = 0) override
|
||||||
|
{
|
||||||
|
return m_w.wait_for_current_job(timeout_ms);
|
||||||
|
}
|
||||||
|
bool wait_for_idle(unsigned timeout_ms = 0) override
|
||||||
|
{
|
||||||
|
return m_w.wait_for_idle(timeout_ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // PLATERJOB_HPP
|
@ -12,6 +12,8 @@
|
|||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
|
||||||
|
#include <slic3r/GUI/I18N.hpp>
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
void RotoptimizeJob::prepare()
|
void RotoptimizeJob::prepare()
|
||||||
@ -45,20 +47,23 @@ void RotoptimizeJob::prepare()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotoptimizeJob::process()
|
void RotoptimizeJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
int prev_status = 0;
|
int prev_status = 0;
|
||||||
|
auto statustxt = _u8L("Searching for optimal orientation");
|
||||||
|
ctl.update_status(0, statustxt);
|
||||||
|
|
||||||
auto params =
|
auto params =
|
||||||
sla::RotOptimizeParams{}
|
sla::RotOptimizeParams{}
|
||||||
.accuracy(m_accuracy)
|
.accuracy(m_accuracy)
|
||||||
.print_config(&m_default_print_cfg)
|
.print_config(&m_default_print_cfg)
|
||||||
.statucb([this, &prev_status](int s)
|
.statucb([this, &prev_status, &ctl, &statustxt](int s)
|
||||||
{
|
{
|
||||||
if (s > 0 && s < 100)
|
if (s > 0 && s < 100)
|
||||||
update_status(prev_status + s / m_selected_object_ids.size(),
|
ctl.update_status(prev_status + s / m_selected_object_ids.size(),
|
||||||
_(L("Searching for optimal orientation")));
|
statustxt);
|
||||||
|
|
||||||
return !was_canceled();
|
return !ctl.was_canceled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -71,16 +76,20 @@ void RotoptimizeJob::process()
|
|||||||
|
|
||||||
prev_status += 100 / m_selected_object_ids.size();
|
prev_status += 100 / m_selected_object_ids.size();
|
||||||
|
|
||||||
if (was_canceled()) break;
|
if (ctl.was_canceled()) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_status(100, was_canceled() ? _(L("Orientation search canceled.")) :
|
ctl.update_status(100, ctl.was_canceled() ?
|
||||||
_(L("Orientation found.")));
|
_u8L("Orientation search canceled.") :
|
||||||
|
_u8L("Orientation found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotoptimizeJob::finalize()
|
RotoptimizeJob::RotoptimizeJob() : m_plater{wxGetApp().plater()} { prepare(); }
|
||||||
|
|
||||||
|
void RotoptimizeJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
if (was_canceled()) return;
|
if (canceled || eptr)
|
||||||
|
return;
|
||||||
|
|
||||||
for (const ObjRot &objrot : m_selected_object_ids) {
|
for (const ObjRot &objrot : m_selected_object_ids) {
|
||||||
ModelObject *o = m_plater->model().objects[size_t(objrot.idx)];
|
ModelObject *o = m_plater->model().objects[size_t(objrot.idx)];
|
||||||
@ -111,10 +120,8 @@ void RotoptimizeJob::finalize()
|
|||||||
// m_plater->find_new_position(o->instances);
|
// m_plater->find_new_position(o->instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!was_canceled())
|
if (!canceled)
|
||||||
m_plater->update();
|
m_plater->update();
|
||||||
|
|
||||||
Job::finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#ifndef ROTOPTIMIZEJOB_HPP
|
#ifndef ROTOPTIMIZEJOB_HPP
|
||||||
#define ROTOPTIMIZEJOB_HPP
|
#define ROTOPTIMIZEJOB_HPP
|
||||||
|
|
||||||
#include "PlaterJob.hpp"
|
#include "Job.hpp"
|
||||||
|
|
||||||
#include "libslic3r/SLA/Rotfinder.hpp"
|
#include "libslic3r/SLA/Rotfinder.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
namespace GUI {
|
class Plater;
|
||||||
|
|
||||||
class RotoptimizeJob : public PlaterJob
|
class RotoptimizeJob : public Job
|
||||||
{
|
{
|
||||||
using FindFn = std::function<Vec2d(const ModelObject & mo,
|
using FindFn = std::function<Vec2d(const ModelObject & mo,
|
||||||
const sla::RotOptimizeParams ¶ms)>;
|
const sla::RotOptimizeParams ¶ms)>;
|
||||||
@ -44,19 +45,16 @@ class RotoptimizeJob : public PlaterJob
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ObjRot> m_selected_object_ids;
|
std::vector<ObjRot> m_selected_object_ids;
|
||||||
|
Plater *m_plater;
|
||||||
protected:
|
|
||||||
|
|
||||||
void prepare() override;
|
|
||||||
void process() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RotoptimizeJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
void prepare();
|
||||||
: PlaterJob{std::move(pri), plater}
|
void process(Ctl &ctl) override;
|
||||||
{}
|
|
||||||
|
|
||||||
void finalize() override;
|
RotoptimizeJob();
|
||||||
|
|
||||||
|
void finalize(bool canceled, std::exception_ptr &) override;
|
||||||
|
|
||||||
static constexpr size_t get_methods_count() { return std::size(Methods); }
|
static constexpr size_t get_methods_count() { return std::size(Methods); }
|
||||||
|
|
||||||
|
114
src/slic3r/GUI/Jobs/SLAImportDialog.hpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#ifndef SLAIMPORTDIALOG_HPP
|
||||||
|
#define SLAIMPORTDIALOG_HPP
|
||||||
|
|
||||||
|
#include "SLAImportJob.hpp"
|
||||||
|
|
||||||
|
#include <wx/dialog.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/combobox.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/filepicker.h>
|
||||||
|
|
||||||
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
|
||||||
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
|
||||||
|
//#include "libslic3r/Model.hpp"
|
||||||
|
//#include "libslic3r/PresetBundle.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
class SLAImportDialog: public wxDialog, public SLAImportJobView {
|
||||||
|
wxFilePickerCtrl *m_filepicker;
|
||||||
|
wxComboBox *m_import_dropdown, *m_quality_dropdown;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SLAImportDialog(Plater *plater)
|
||||||
|
: wxDialog{plater, wxID_ANY, "Import SLA archive"}
|
||||||
|
{
|
||||||
|
auto szvert = new wxBoxSizer{wxVERTICAL};
|
||||||
|
auto szfilepck = new wxBoxSizer{wxHORIZONTAL};
|
||||||
|
|
||||||
|
m_filepicker = new wxFilePickerCtrl(this, wxID_ANY,
|
||||||
|
from_u8(wxGetApp().app_config->get_last_dir()), _(L("Choose SLA archive:")),
|
||||||
|
"SL1 / SL1S archive files (*.sl1, *.sl1s, *.zip)|*.sl1;*.SL1;*.sl1s;*.SL1S;*.zip;*.ZIP",
|
||||||
|
wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
|
|
||||||
|
szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER);
|
||||||
|
szfilepck->Add(m_filepicker, 1);
|
||||||
|
szvert->Add(szfilepck, 0, wxALL | wxEXPAND, 5);
|
||||||
|
|
||||||
|
auto szchoices = new wxBoxSizer{wxHORIZONTAL};
|
||||||
|
|
||||||
|
static const std::vector<wxString> inp_choices = {
|
||||||
|
_(L("Import model and profile")),
|
||||||
|
_(L("Import profile only")),
|
||||||
|
_(L("Import model only"))
|
||||||
|
};
|
||||||
|
|
||||||
|
m_import_dropdown = new wxComboBox(
|
||||||
|
this, wxID_ANY, inp_choices[0], wxDefaultPosition, wxDefaultSize,
|
||||||
|
inp_choices.size(), inp_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
|
||||||
|
|
||||||
|
szchoices->Add(m_import_dropdown);
|
||||||
|
szchoices->Add(new wxStaticText(this, wxID_ANY, _L("Quality") + ": "), 0, wxALIGN_CENTER | wxALL, 5);
|
||||||
|
|
||||||
|
static const std::vector<wxString> qual_choices = {
|
||||||
|
_(L("Accurate")),
|
||||||
|
_(L("Balanced")),
|
||||||
|
_(L("Quick"))
|
||||||
|
};
|
||||||
|
|
||||||
|
m_quality_dropdown = new wxComboBox(
|
||||||
|
this, wxID_ANY, qual_choices[0], wxDefaultPosition, wxDefaultSize,
|
||||||
|
qual_choices.size(), qual_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
|
||||||
|
szchoices->Add(m_quality_dropdown);
|
||||||
|
|
||||||
|
m_import_dropdown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &) {
|
||||||
|
if (get_selection() == Sel::profileOnly)
|
||||||
|
m_quality_dropdown->Disable();
|
||||||
|
else m_quality_dropdown->Enable();
|
||||||
|
});
|
||||||
|
|
||||||
|
szvert->Add(szchoices, 0, wxALL, 5);
|
||||||
|
szvert->AddStretchSpacer(1);
|
||||||
|
auto szbtn = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
szbtn->Add(new wxButton{this, wxID_CANCEL});
|
||||||
|
szbtn->Add(new wxButton{this, wxID_OK});
|
||||||
|
szvert->Add(szbtn, 0, wxALIGN_RIGHT | wxALL, 5);
|
||||||
|
|
||||||
|
SetSizerAndFit(szvert);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sel get_selection() const override
|
||||||
|
{
|
||||||
|
int sel = m_import_dropdown->GetSelection();
|
||||||
|
return Sel(std::min(int(Sel::modelOnly), std::max(0, sel)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2i get_marchsq_windowsize() const override
|
||||||
|
{
|
||||||
|
enum { Accurate, Balanced, Fast};
|
||||||
|
|
||||||
|
switch(m_quality_dropdown->GetSelection())
|
||||||
|
{
|
||||||
|
case Fast: return {8, 8};
|
||||||
|
case Balanced: return {4, 4};
|
||||||
|
default:
|
||||||
|
case Accurate:
|
||||||
|
return {2, 2};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_path() const override
|
||||||
|
{
|
||||||
|
return m_filepicker->GetPath().ToUTF8().data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // SLAIMPORTDIALOG_HPP
|
@ -3,7 +3,6 @@
|
|||||||
#include "libslic3r/Format/SL1.hpp"
|
#include "libslic3r/Format/SL1.hpp"
|
||||||
|
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
#include "slic3r/GUI/NotificationManager.hpp"
|
#include "slic3r/GUI/NotificationManager.hpp"
|
||||||
@ -11,104 +10,10 @@
|
|||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
|
||||||
#include <wx/dialog.h>
|
|
||||||
#include <wx/stattext.h>
|
|
||||||
#include <wx/combobox.h>
|
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <wx/filepicker.h>
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
enum class Sel { modelAndProfile, profileOnly, modelOnly};
|
|
||||||
|
|
||||||
class ImportDlg: public wxDialog {
|
|
||||||
wxFilePickerCtrl *m_filepicker;
|
|
||||||
wxComboBox *m_import_dropdown, *m_quality_dropdown;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ImportDlg(Plater *plater)
|
|
||||||
: wxDialog{plater, wxID_ANY, "Import SLA archive"}
|
|
||||||
{
|
|
||||||
auto szvert = new wxBoxSizer{wxVERTICAL};
|
|
||||||
auto szfilepck = new wxBoxSizer{wxHORIZONTAL};
|
|
||||||
|
|
||||||
m_filepicker = new wxFilePickerCtrl(this, wxID_ANY,
|
|
||||||
from_u8(wxGetApp().app_config->get_last_dir()), _(L("Choose SLA archive:")),
|
|
||||||
"SL1 / SL1S archive files (*.sl1, *.sl1s, *.zip)|*.sl1;*.SL1;*.sl1s;*.SL1S;*.zip;*.ZIP",
|
|
||||||
wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
|
||||||
|
|
||||||
szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER);
|
|
||||||
szfilepck->Add(m_filepicker, 1);
|
|
||||||
szvert->Add(szfilepck, 0, wxALL | wxEXPAND, 5);
|
|
||||||
|
|
||||||
auto szchoices = new wxBoxSizer{wxHORIZONTAL};
|
|
||||||
|
|
||||||
static const std::vector<wxString> inp_choices = {
|
|
||||||
_(L("Import model and profile")),
|
|
||||||
_(L("Import profile only")),
|
|
||||||
_(L("Import model only"))
|
|
||||||
};
|
|
||||||
|
|
||||||
m_import_dropdown = new wxComboBox(
|
|
||||||
this, wxID_ANY, inp_choices[0], wxDefaultPosition, wxDefaultSize,
|
|
||||||
inp_choices.size(), inp_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
|
|
||||||
|
|
||||||
szchoices->Add(m_import_dropdown);
|
|
||||||
szchoices->Add(new wxStaticText(this, wxID_ANY, _L("Quality") + ": "), 0, wxALIGN_CENTER | wxALL, 5);
|
|
||||||
|
|
||||||
static const std::vector<wxString> qual_choices = {
|
|
||||||
_(L("Accurate")),
|
|
||||||
_(L("Balanced")),
|
|
||||||
_(L("Quick"))
|
|
||||||
};
|
|
||||||
|
|
||||||
m_quality_dropdown = new wxComboBox(
|
|
||||||
this, wxID_ANY, qual_choices[0], wxDefaultPosition, wxDefaultSize,
|
|
||||||
qual_choices.size(), qual_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
|
|
||||||
szchoices->Add(m_quality_dropdown);
|
|
||||||
|
|
||||||
m_import_dropdown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &) {
|
|
||||||
if (get_selection() == Sel::profileOnly)
|
|
||||||
m_quality_dropdown->Disable();
|
|
||||||
else m_quality_dropdown->Enable();
|
|
||||||
});
|
|
||||||
|
|
||||||
szvert->Add(szchoices, 0, wxALL, 5);
|
|
||||||
szvert->AddStretchSpacer(1);
|
|
||||||
auto szbtn = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
szbtn->Add(new wxButton{this, wxID_CANCEL});
|
|
||||||
szbtn->Add(new wxButton{this, wxID_OK});
|
|
||||||
szvert->Add(szbtn, 0, wxALIGN_RIGHT | wxALL, 5);
|
|
||||||
|
|
||||||
SetSizerAndFit(szvert);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sel get_selection() const
|
|
||||||
{
|
|
||||||
int sel = m_import_dropdown->GetSelection();
|
|
||||||
return Sel(std::min(int(Sel::modelOnly), std::max(0, sel)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2i get_marchsq_windowsize() const
|
|
||||||
{
|
|
||||||
enum { Accurate, Balanced, Fast};
|
|
||||||
|
|
||||||
switch(m_quality_dropdown->GetSelection())
|
|
||||||
{
|
|
||||||
case Fast: return {8, 8};
|
|
||||||
case Balanced: return {4, 4};
|
|
||||||
default:
|
|
||||||
case Accurate:
|
|
||||||
return {2, 2};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString get_path() const
|
|
||||||
{
|
|
||||||
return m_filepicker->GetPath();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SLAImportJob::priv {
|
class SLAImportJob::priv {
|
||||||
public:
|
public:
|
||||||
Plater *plater;
|
Plater *plater;
|
||||||
@ -122,23 +27,28 @@ public:
|
|||||||
std::string err;
|
std::string err;
|
||||||
ConfigSubstitutions config_substitutions;
|
ConfigSubstitutions config_substitutions;
|
||||||
|
|
||||||
ImportDlg import_dlg;
|
const SLAImportJobView * import_dlg;
|
||||||
|
|
||||||
priv(Plater *plt) : plater{plt}, import_dlg{plt} {}
|
priv(Plater *plt, const SLAImportJobView *view) : plater{plt}, import_dlg{view} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
SLAImportJob::SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
SLAImportJob::SLAImportJob(const SLAImportJobView *view)
|
||||||
: PlaterJob{std::move(pri), plater}, p{std::make_unique<priv>(plater)}
|
: p{std::make_unique<priv>(wxGetApp().plater(), view)}
|
||||||
{}
|
{
|
||||||
|
prepare();
|
||||||
|
}
|
||||||
|
|
||||||
SLAImportJob::~SLAImportJob() = default;
|
SLAImportJob::~SLAImportJob() = default;
|
||||||
|
|
||||||
void SLAImportJob::process()
|
void SLAImportJob::process(Ctl &ctl)
|
||||||
{
|
{
|
||||||
auto progr = [this](int s) {
|
auto statustxt = _u8L("Importing SLA archive");
|
||||||
|
ctl.update_status(0, statustxt);
|
||||||
|
|
||||||
|
auto progr = [&ctl, &statustxt](int s) {
|
||||||
if (s < 100)
|
if (s < 100)
|
||||||
update_status(int(s), _(L("Importing SLA archive")));
|
ctl.update_status(int(s), statustxt);
|
||||||
return !was_canceled();
|
return !ctl.was_canceled();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (p->path.empty()) return;
|
if (p->path.empty()) return;
|
||||||
@ -161,15 +71,15 @@ void SLAImportJob::process()
|
|||||||
p->err = ex.what();
|
p->err = ex.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_status(100, was_canceled() ? _(L("Importing canceled.")) :
|
ctl.update_status(100, ctl.was_canceled() ? _u8L("Importing canceled.") :
|
||||||
_(L("Importing done.")));
|
_u8L("Importing done."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SLAImportJob::reset()
|
void SLAImportJob::reset()
|
||||||
{
|
{
|
||||||
p->sel = Sel::modelAndProfile;
|
p->sel = Sel::modelAndProfile;
|
||||||
p->mesh = {};
|
p->mesh = {};
|
||||||
p->profile = m_plater->sla_print().full_print_config();
|
p->profile = p->plater->sla_print().full_print_config();
|
||||||
p->win = {2, 2};
|
p->win = {2, 2};
|
||||||
p->path.Clear();
|
p->path.Clear();
|
||||||
}
|
}
|
||||||
@ -178,22 +88,19 @@ void SLAImportJob::prepare()
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
if (p->import_dlg.ShowModal() == wxID_OK) {
|
auto path = p->import_dlg->get_path();
|
||||||
auto path = p->import_dlg.get_path();
|
|
||||||
auto nm = wxFileName(path);
|
auto nm = wxFileName(path);
|
||||||
p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : nm.GetFullPath();
|
p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : nm.GetFullPath();
|
||||||
p->sel = p->import_dlg.get_selection();
|
p->sel = p->import_dlg->get_selection();
|
||||||
p->win = p->import_dlg.get_marchsq_windowsize();
|
p->win = p->import_dlg->get_marchsq_windowsize();
|
||||||
p->config_substitutions.clear();
|
p->config_substitutions.clear();
|
||||||
} else {
|
|
||||||
p->path = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SLAImportJob::finalize()
|
void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||||
{
|
{
|
||||||
// Ignore the arrange result if aborted.
|
// Ignore the arrange result if aborted.
|
||||||
if (was_canceled()) return;
|
if (canceled || eptr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!p->err.empty()) {
|
if (!p->err.empty()) {
|
||||||
show_error(p->plater, p->err);
|
show_error(p->plater, p->err);
|
||||||
@ -204,7 +111,7 @@ void SLAImportJob::finalize()
|
|||||||
std::string name = wxFileName(p->path).GetName().ToUTF8().data();
|
std::string name = wxFileName(p->path).GetName().ToUTF8().data();
|
||||||
|
|
||||||
if (p->profile.empty()) {
|
if (p->profile.empty()) {
|
||||||
m_plater->get_notification_manager()->push_notification(
|
p->plater->get_notification_manager()->push_notification(
|
||||||
NotificationType::CustomNotification,
|
NotificationType::CustomNotification,
|
||||||
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
NotificationManager::NotificationLevel::WarningNotificationLevel,
|
||||||
_L("The imported SLA archive did not contain any presets. "
|
_L("The imported SLA archive did not contain any presets. "
|
||||||
@ -213,7 +120,7 @@ void SLAImportJob::finalize()
|
|||||||
|
|
||||||
if (p->sel != Sel::modelOnly) {
|
if (p->sel != Sel::modelOnly) {
|
||||||
if (p->profile.empty())
|
if (p->profile.empty())
|
||||||
p->profile = m_plater->sla_print().full_print_config();
|
p->profile = p->plater->sla_print().full_print_config();
|
||||||
|
|
||||||
const ModelObjectPtrs& objects = p->plater->model().objects;
|
const ModelObjectPtrs& objects = p->plater->model().objects;
|
||||||
for (auto object : objects)
|
for (auto object : objects)
|
||||||
|
@ -1,22 +1,37 @@
|
|||||||
#ifndef SLAIMPORTJOB_HPP
|
#ifndef SLAIMPORTJOB_HPP
|
||||||
#define SLAIMPORTJOB_HPP
|
#define SLAIMPORTJOB_HPP
|
||||||
|
|
||||||
#include "PlaterJob.hpp"
|
#include "Job.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/Point.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
class SLAImportJob : public PlaterJob {
|
class SLAImportJobView {
|
||||||
|
public:
|
||||||
|
enum Sel { modelAndProfile, profileOnly, modelOnly};
|
||||||
|
|
||||||
|
virtual ~SLAImportJobView() = default;
|
||||||
|
|
||||||
|
virtual Sel get_selection() const = 0;
|
||||||
|
virtual Vec2i get_marchsq_windowsize() const = 0;
|
||||||
|
virtual std::string get_path() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Plater;
|
||||||
|
|
||||||
|
class SLAImportJob : public Job {
|
||||||
class priv;
|
class priv;
|
||||||
|
|
||||||
std::unique_ptr<priv> p;
|
std::unique_ptr<priv> p;
|
||||||
|
using Sel = SLAImportJobView::Sel;
|
||||||
protected:
|
|
||||||
void prepare() override;
|
|
||||||
void process() override;
|
|
||||||
void finalize() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater);
|
void prepare();
|
||||||
|
void process(Ctl &ctl) override;
|
||||||
|
void finalize(bool canceled, std::exception_ptr &) override;
|
||||||
|
|
||||||
|
SLAImportJob(const SLAImportJobView *);
|
||||||
~SLAImportJob();
|
~SLAImportJob();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
123
src/slic3r/GUI/Jobs/ThreadSafeQueue.hpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#ifndef THREADSAFEQUEUE_HPP
|
||||||
|
#define THREADSAFEQUEUE_HPP
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
// Helper structure for overloads of ThreadSafeQueueSPSC::consume_one()
|
||||||
|
// to block if the queue is empty.
|
||||||
|
struct BlockingWait
|
||||||
|
{
|
||||||
|
// Timeout to wait for the arrival of new element into the queue.
|
||||||
|
unsigned timeout_ms = 0;
|
||||||
|
|
||||||
|
// An optional atomic flag to set true if an incoming element gets
|
||||||
|
// consumed. The flag will be atomically set to true when popping the
|
||||||
|
// front of the queue.
|
||||||
|
std::atomic<bool> *pop_flag = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A thread safe queue for one producer and one consumer.
|
||||||
|
template<class T,
|
||||||
|
template<class, class...> class Container = std::deque,
|
||||||
|
class... ContainerArgs>
|
||||||
|
class ThreadSafeQueueSPSC
|
||||||
|
{
|
||||||
|
std::queue<T, Container<T, ContainerArgs...>> m_queue;
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
std::condition_variable m_cond_var;
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Consume one element, block if the queue is empty.
|
||||||
|
template<class Fn> bool consume_one(const BlockingWait &blkw, Fn &&fn)
|
||||||
|
{
|
||||||
|
static_assert(!std::is_reference_v<T>, "");
|
||||||
|
static_assert(std::is_default_constructible_v<T>, "");
|
||||||
|
static_assert(std::is_move_assignable_v<T> || std::is_copy_assignable_v<T>, "");
|
||||||
|
|
||||||
|
T el;
|
||||||
|
{
|
||||||
|
std::unique_lock lk{m_mutex};
|
||||||
|
|
||||||
|
auto pred = [this]{ return !m_queue.empty(); };
|
||||||
|
if (blkw.timeout_ms > 0) {
|
||||||
|
auto timeout = std::chrono::milliseconds(blkw.timeout_ms);
|
||||||
|
if (!m_cond_var.wait_for(lk, timeout, pred))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_cond_var.wait(lk, pred);
|
||||||
|
|
||||||
|
if constexpr (std::is_move_assignable_v<T>)
|
||||||
|
el = std::move(m_queue.front());
|
||||||
|
else
|
||||||
|
el = m_queue.front();
|
||||||
|
|
||||||
|
m_queue.pop();
|
||||||
|
|
||||||
|
if (blkw.pop_flag)
|
||||||
|
// The optional flag is set before the lock us unlocked.
|
||||||
|
blkw.pop_flag->store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn(el);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume one element, return true if consumed, false if queue was empty.
|
||||||
|
template<class Fn> bool consume_one(Fn &&fn)
|
||||||
|
{
|
||||||
|
T el;
|
||||||
|
{
|
||||||
|
std::unique_lock lk{m_mutex};
|
||||||
|
if (!m_queue.empty()) {
|
||||||
|
if constexpr (std::is_move_assignable_v<T>)
|
||||||
|
el = std::move(m_queue.front());
|
||||||
|
else
|
||||||
|
el = m_queue.front();
|
||||||
|
|
||||||
|
m_queue.pop();
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn(el);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push element into the queue.
|
||||||
|
template<class...TArgs> void push(TArgs&&...el)
|
||||||
|
{
|
||||||
|
std::lock_guard lk{m_mutex};
|
||||||
|
m_queue.emplace(std::forward<TArgs>(el)...);
|
||||||
|
m_cond_var.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
std::lock_guard lk{m_mutex};
|
||||||
|
return m_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
std::lock_guard lk{m_mutex};
|
||||||
|
return m_queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::lock_guard lk{m_mutex};
|
||||||
|
while (!m_queue.empty()) m_queue.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // THREADSAFEQUEUE_HPP
|
119
src/slic3r/GUI/Jobs/Worker.hpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#ifndef PRUSALSICER_WORKER_HPP
|
||||||
|
#define PRUSALSICER_WORKER_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Job.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
// An interface of a worker that runs jobs on a dedicated worker thread, one
|
||||||
|
// after the other. It is assumed that every method of this class is called
|
||||||
|
// from the same main thread.
|
||||||
|
class Worker {
|
||||||
|
public:
|
||||||
|
// Queue up a new job after the current one. This call does not block.
|
||||||
|
// Returns false if the job gets discarded.
|
||||||
|
virtual bool push(std::unique_ptr<Job> job) = 0;
|
||||||
|
|
||||||
|
// Returns true if no job is running, the job queue is empty and no job
|
||||||
|
// message is left to be processed. This means that nothing is left to
|
||||||
|
// finalize or take care of in the main thread.
|
||||||
|
virtual bool is_idle() const = 0;
|
||||||
|
|
||||||
|
// Ask the current job gracefully to cancel. This call is not blocking and
|
||||||
|
// the job may or may not cancel eventually, depending on its
|
||||||
|
// implementation. Note that it is not trivial to kill a thread forcefully
|
||||||
|
// and we don't need that.
|
||||||
|
virtual void cancel() = 0;
|
||||||
|
|
||||||
|
// This method will delete the queued jobs and cancel the current one.
|
||||||
|
virtual void cancel_all() = 0;
|
||||||
|
|
||||||
|
// Needs to be called continuously to process events (like status update
|
||||||
|
// or finalizing of jobs) in the main thread. This can be done e.g. in a
|
||||||
|
// wxIdle handler.
|
||||||
|
virtual void process_events() = 0;
|
||||||
|
|
||||||
|
// Wait until the current job finishes. Timeout will only be considered
|
||||||
|
// if not zero. Returns false if timeout is reached but the job has not
|
||||||
|
// finished.
|
||||||
|
virtual bool wait_for_current_job(unsigned timeout_ms = 0) = 0;
|
||||||
|
|
||||||
|
// Wait until the whole job queue finishes. Timeout will only be considered
|
||||||
|
// if not zero. Returns false only if timeout is reached but the worker has
|
||||||
|
// not reached the idle state.
|
||||||
|
virtual bool wait_for_idle(unsigned timeout_ms = 0) = 0;
|
||||||
|
|
||||||
|
// The destructor shall properly close the worker thread.
|
||||||
|
virtual ~Worker() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Fn> constexpr bool IsProcessFn = std::is_invocable_v<Fn, Job::Ctl&>;
|
||||||
|
template<class Fn> constexpr bool IsFinishFn = std::is_invocable_v<Fn, bool, std::exception_ptr&>;
|
||||||
|
|
||||||
|
// Helper function to use the worker with arbitrary functors.
|
||||||
|
template<class ProcessFn, class FinishFn,
|
||||||
|
class = std::enable_if_t<IsProcessFn<ProcessFn>>,
|
||||||
|
class = std::enable_if_t<IsFinishFn<FinishFn>> >
|
||||||
|
bool queue_job(Worker &w, ProcessFn fn, FinishFn finishfn)
|
||||||
|
{
|
||||||
|
struct LambdaJob: Job {
|
||||||
|
ProcessFn fn;
|
||||||
|
FinishFn finishfn;
|
||||||
|
|
||||||
|
LambdaJob(ProcessFn pfn, FinishFn ffn)
|
||||||
|
: fn{std::move(pfn)}, finishfn{std::move(ffn)}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void process(Ctl &ctl) override { fn(ctl); }
|
||||||
|
void finalize(bool canceled, std::exception_ptr &eptr) override
|
||||||
|
{
|
||||||
|
finishfn(canceled, eptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto j = std::make_unique<LambdaJob>(std::move(fn), std::move(finishfn));
|
||||||
|
return w.push(std::move(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class ProcessFn, class = std::enable_if_t<IsProcessFn<ProcessFn>>>
|
||||||
|
bool queue_job(Worker &w, ProcessFn fn)
|
||||||
|
{
|
||||||
|
return queue_job(w, std::move(fn), [](bool, std::exception_ptr &) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool queue_job(Worker &w, std::unique_ptr<Job> j)
|
||||||
|
{
|
||||||
|
return w.push(std::move(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the current job queue with a new job. The signature is the same
|
||||||
|
// as for queue_job(). This cancels all jobs and
|
||||||
|
// will not wait. The new job will begin after the queue cancels properly.
|
||||||
|
// Note that this can be called from the UI thread and will not block it if
|
||||||
|
// the jobs take longer to cancel.
|
||||||
|
template<class...Args> bool replace_job(Worker &w, Args&& ...args)
|
||||||
|
{
|
||||||
|
w.cancel_all();
|
||||||
|
return queue_job(w, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel the current job and wait for it to actually be stopped.
|
||||||
|
inline bool stop_current_job(Worker &w, unsigned timeout_ms = 0)
|
||||||
|
{
|
||||||
|
w.cancel();
|
||||||
|
return w.wait_for_current_job(timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel all pending jobs including current one and wait until the worker
|
||||||
|
// becomes idle.
|
||||||
|
inline bool stop_queue(Worker &w, unsigned timeout_ms = 0)
|
||||||
|
{
|
||||||
|
w.cancel_all();
|
||||||
|
return w.wait_for_idle(timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // WORKER_HPP
|
@ -223,7 +223,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
{ "A", L("Horizontal slider - Move active thumb Left") },
|
{ "A", L("Horizontal slider - Move active thumb Left") },
|
||||||
{ "D", L("Horizontal slider - Move active thumb Right") },
|
{ "D", L("Horizontal slider - Move active thumb Right") },
|
||||||
{ "X", L("On/Off one layer mode of the vertical slider") },
|
{ "X", L("On/Off one layer mode of the vertical slider") },
|
||||||
{ "L", L("Show/Hide Legend and Estimated printing time") },
|
{ "L", L("Show/Hide legend") },
|
||||||
{ "C", L("Show/Hide G-code window") },
|
{ "C", L("Show/Hide G-code window") },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "GUI_ObjectList.hpp"
|
#include "GUI_ObjectList.hpp"
|
||||||
#include "GalleryDialog.hpp"
|
#include "GalleryDialog.hpp"
|
||||||
#include "NotificationManager.hpp"
|
#include "NotificationManager.hpp"
|
||||||
|
#include "Preferences.hpp"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
@ -272,6 +273,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||||||
if (m_plater != nullptr) {
|
if (m_plater != nullptr) {
|
||||||
m_plater->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get("show_collapse_button") == "1");
|
m_plater->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get("show_collapse_button") == "1");
|
||||||
m_plater->show_action_buttons(true);
|
m_plater->show_action_buttons(true);
|
||||||
|
|
||||||
|
preferences_dialog = new PreferencesDialog(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +574,7 @@ void MainFrame::shutdown()
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
if (m_plater != nullptr) {
|
if (m_plater != nullptr) {
|
||||||
m_plater->stop_jobs();
|
m_plater->get_ui_job_worker().cancel_all();
|
||||||
|
|
||||||
// Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC,
|
// Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC,
|
||||||
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
|
// when closing the application using Command+Q, a mouse event is triggered after this lambda is completed,
|
||||||
@ -1208,7 +1211,7 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
|
|
||||||
append_menu_item(import_menu, wxID_ANY, _L("Import SL1 / SL1S Archive") + dots, _L("Load an SL1 / Sl1S archive"),
|
append_menu_item(import_menu, wxID_ANY, _L("Import SL1 / SL1S Archive") + dots, _L("Load an SL1 / Sl1S archive"),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr,
|
[this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr,
|
||||||
[this](){return m_plater != nullptr && !m_plater->is_any_job_running(); }, this);
|
[this](){return m_plater != nullptr && m_plater->get_ui_job_worker().is_idle(); }, this);
|
||||||
|
|
||||||
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"),
|
||||||
@ -1427,6 +1430,11 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + sep + "E", _L("Show object/instance labels in 3D scene"),
|
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels") + sep + "E", _L("Show object/instance labels in 3D scene"),
|
||||||
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this,
|
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this,
|
||||||
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
|
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
append_menu_check_item(viewMenu, wxID_ANY, _L("Show Legen&d") + sep + "L", _L("Show legend in preview"),
|
||||||
|
[this](wxCommandEvent&) { m_plater->show_legend(!m_plater->is_legend_shown()); }, this,
|
||||||
|
[this]() { return m_plater->is_preview_shown(); }, [this]() { return m_plater->is_legend_shown(); }, this);
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse Sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"),
|
append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse Sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"),
|
||||||
[this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this,
|
[this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this,
|
||||||
[]() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this);
|
[]() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this);
|
||||||
@ -1544,6 +1552,12 @@ void MainFrame::init_menubar_as_gcodeviewer()
|
|||||||
if (m_plater != nullptr) {
|
if (m_plater != nullptr) {
|
||||||
viewMenu = new wxMenu();
|
viewMenu = new wxMenu();
|
||||||
add_common_view_menu_items(viewMenu, this, std::bind(&MainFrame::can_change_view, this));
|
add_common_view_menu_items(viewMenu, this, std::bind(&MainFrame::can_change_view, this));
|
||||||
|
#if ENABLE_PREVIEW_LAYOUT
|
||||||
|
viewMenu->AppendSeparator();
|
||||||
|
append_menu_check_item(viewMenu, wxID_ANY, _L("Show legen&d") + sep + "L", _L("Show legend"),
|
||||||
|
[this](wxCommandEvent&) { m_plater->show_legend(!m_plater->is_legend_shown()); }, this,
|
||||||
|
[this]() { return m_plater->is_preview_shown(); }, [this]() { return m_plater->is_legend_shown(); }, this);
|
||||||
|
#endif // ENABLE_PREVIEW_LAYOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
// helpmenu
|
// helpmenu
|
||||||
|