Merge remote-tracking branch 'origin/master' into ys_printable_property
|
@ -3,39 +3,23 @@
|
|||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="edit_x5F_layers_x5F_all">
|
||||
<path fill="#808080" d="M15,2.5H1C0.72,2.5,0.5,2.28,0.5,2S0.72,1.5,1,1.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,2.5,15,2.5z"/>
|
||||
<path fill="#808080" d="M15,4.5H1C0.72,4.5,0.5,4.28,0.5,4S0.72,3.5,1,3.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,4.5,15,4.5z"/>
|
||||
<path fill="#808080" d="M15,12.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,12.5,15,12.5z"/>
|
||||
<path fill="#808080" d="M15,14.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,14.5,15,14.5z"/>
|
||||
<g>
|
||||
<path fill="#808080" d="M5.86,10.36c-0.01,0.04-0.13-0.14-0.2-0.22l-0.2-0.02C5.16,10.1,4.85,9.89,4.73,9.6L4.69,9.5H1
|
||||
c-0.28,0-0.5,0.22-0.5,0.5s0.22,0.5,0.5,0.5h4.87L5.86,10.36z"/>
|
||||
<path fill="#808080" d="M15,9.5h-3.69l-0.04,0.1c-0.12,0.29-0.42,0.5-0.73,0.53l-0.18,0.01c0.04,0.01-0.13,0.13-0.21,0.2
|
||||
l-0.02,0.16H15c0.28,0,0.5-0.22,0.5-0.5S15.28,9.5,15,9.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.7,8.29l0.11-0.13c-0.03,0.02,0-0.19,0.01-0.3L4.7,7.71C4.65,7.65,4.61,7.58,4.58,7.5H1
|
||||
C0.72,7.5,0.5,7.72,0.5,8S0.72,8.5,1,8.5h3.58C4.61,8.42,4.65,8.35,4.7,8.29z"/>
|
||||
<path fill="#808080" d="M15,7.5h-3.58c-0.03,0.08-0.08,0.15-0.13,0.21l-0.11,0.13l-0.01,0.02c0.01,0.12,0.04,0.32,0.06,0.38
|
||||
l0.06,0.05c0.05,0.06,0.1,0.13,0.13,0.21H15c0.28,0,0.5-0.22,0.5-0.5S15.28,7.5,15,7.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.74,6.4c0.12-0.29,0.42-0.5,0.73-0.52l0.17-0.01C5.6,5.86,5.77,5.73,5.85,5.66L5.87,5.5H1
|
||||
C0.72,5.5,0.5,5.72,0.5,6S0.72,6.5,1,6.5h3.69L4.74,6.4z"/>
|
||||
<path fill="#808080" d="M15,5.5h-4.87l0.01,0.14c0-0.03,0.13,0.13,0.2,0.21l0.2,0.02c0.31,0.02,0.61,0.24,0.73,0.53l0.04,0.1H15
|
||||
c0.28,0,0.5-0.22,0.5-0.5S15.28,5.5,15,5.5z"/>
|
||||
</g>
|
||||
<path fill="#ED6B21" d="M10.67,7.89c-0.01-0.12,0.05-0.29,0.13-0.38l0.11-0.13c0.08-0.09,0.11-0.26,0.06-0.37L10.8,6.59
|
||||
c-0.05-0.11-0.18-0.21-0.3-0.22l-0.17-0.01c-0.12-0.01-0.28-0.09-0.36-0.18C9.89,6.1,9.65,5.79,9.64,5.67L9.63,5.5
|
||||
C9.62,5.38,9.52,5.24,9.41,5.2L8.99,5.02C8.88,4.98,8.71,5,8.62,5.08L8.49,5.2C8.4,5.28,8.22,5.33,8.11,5.33
|
||||
C7.99,5.32,7.6,5.27,7.51,5.2L7.38,5.08C7.29,5,7.13,4.98,7.01,5.02L6.59,5.2C6.48,5.24,6.38,5.38,6.37,5.5L6.36,5.67
|
||||
C6.35,5.79,6.27,5.95,6.19,6.03S5.79,6.35,5.67,6.36L5.5,6.37C5.38,6.38,5.24,6.48,5.2,6.59L5.02,7.01C4.98,7.12,5,7.29,5.08,7.38
|
||||
L5.2,7.51C5.28,7.6,5.33,7.78,5.33,7.89C5.32,8.01,5.27,8.4,5.2,8.49L5.08,8.62C5,8.71,4.98,8.87,5.02,8.99L5.2,9.41
|
||||
c0.05,0.11,0.18,0.21,0.3,0.22l0.17,0.01c0.12,0.01,0.28,0.09,0.36,0.18c0.08,0.09,0.32,0.39,0.33,0.51l0.01,0.17
|
||||
c0.01,0.12,0.11,0.26,0.22,0.3l0.42,0.17c0.11,0.05,0.28,0.02,0.37-0.06l0.13-0.11c0.09-0.08,0.26-0.14,0.38-0.13
|
||||
c0.12,0.01,0.5,0.05,0.59,0.13l0.13,0.11c0.09,0.08,0.26,0.11,0.37,0.06l0.42-0.17c0.11-0.05,0.21-0.18,0.22-0.3l0.01-0.17
|
||||
c0.01-0.12,0.09-0.28,0.18-0.36c0.09-0.08,0.39-0.32,0.51-0.33l0.17-0.01c0.12-0.01,0.26-0.11,0.3-0.22l0.17-0.42
|
||||
c0.05-0.11,0.02-0.28-0.06-0.37L10.8,8.49C10.72,8.4,10.68,8.01,10.67,7.89z M8,9.8c-0.99,0-1.8-0.8-1.8-1.8S7.01,6.2,8,6.2
|
||||
S9.8,7.01,9.8,8S8.99,9.8,8,9.8z"/>
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="6" y2="2"/>
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="6" x2="6" y2="6"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="10" x2="14" y2="10"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/>
|
||||
<path fill="#ED6B21" d="M14.62,4.37c-0.01-0.14,0.06-0.34,0.15-0.44l0.13-0.15c0.09-0.11,0.12-0.3,0.07-0.43l-0.2-0.49
|
||||
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.33-0.1-0.42-0.21c-0.09-0.1-0.37-0.46-0.38-0.6l-0.01-0.2
|
||||
c-0.01-0.14-0.12-0.3-0.25-0.35l-0.49-0.2C12.52,0.97,12.33,1,12.22,1.1l-0.15,0.13c-0.11,0.09-0.31,0.16-0.44,0.15
|
||||
c-0.14-0.01-0.59-0.06-0.69-0.15L10.78,1.1c-0.11-0.09-0.3-0.12-0.43-0.07l-0.49,0.2C9.73,1.28,9.61,1.44,9.6,1.58l-0.01,0.2
|
||||
C9.58,1.92,9.49,2.11,9.38,2.2c-0.1,0.09-0.46,0.37-0.6,0.38L8.58,2.6c-0.14,0.01-0.3,0.12-0.35,0.25l-0.2,0.49
|
||||
C7.97,3.48,8,3.67,8.1,3.78l0.13,0.15c0.09,0.11,0.16,0.31,0.15,0.44C8.37,4.52,8.32,4.96,8.23,5.07L8.1,5.22
|
||||
C8,5.33,7.97,5.52,8.03,5.65l0.2,0.49C8.28,6.27,8.44,6.39,8.58,6.4l0.2,0.01c0.14,0.01,0.33,0.1,0.42,0.21
|
||||
c0.09,0.1,0.37,0.46,0.38,0.6l0.01,0.2c0.01,0.14,0.12,0.3,0.25,0.35l0.49,0.2C10.48,8.03,10.67,8,10.78,7.9l0.15-0.13
|
||||
c0.11-0.09,0.31-0.16,0.44-0.15c0.14,0.01,0.59,0.06,0.69,0.15l0.15,0.13c0.11,0.09,0.3,0.12,0.43,0.07l0.49-0.2
|
||||
c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.33,0.21-0.42s0.46-0.37,0.6-0.38l0.2-0.01c0.14-0.01,0.3-0.12,0.35-0.25
|
||||
l0.2-0.49C15.03,5.52,15,5.33,14.9,5.22l-0.13-0.15C14.68,4.96,14.63,4.51,14.62,4.37z M11.5,6.6c-1.16,0-2.1-0.94-2.1-2.1
|
||||
s0.94-2.1,2.1-2.1s2.1,0.94,2.1,2.1S12.66,6.6,11.5,6.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -2,68 +2,13 @@
|
|||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="edit_x5F_layers_x5F_some">
|
||||
<g>
|
||||
<path fill="#808080" d="M15,2.5H1C0.72,2.5,0.5,2.28,0.5,2S0.72,1.5,1,1.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,2.5,15,2.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,4.5h-2.5C12.22,4.5,12,4.28,12,4s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,4.5,15,4.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M9.5,4.5h-3C6.22,4.5,6,4.28,6,4s0.22-0.5,0.5-0.5h3C9.78,3.5,10,3.72,10,4S9.78,4.5,9.5,4.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,4.5H1C0.72,4.5,0.5,4.28,0.5,4S0.72,3.5,1,3.5h2.5C3.78,3.5,4,3.72,4,4S3.78,4.5,3.5,4.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,8.5h-2.5C12.22,8.5,12,8.28,12,8s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,8.5,15,8.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,8.5H1C0.72,8.5,0.5,8.28,0.5,8S0.72,7.5,1,7.5h2.5C3.78,7.5,4,7.72,4,8S3.78,8.5,3.5,8.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,12.5h-2.5c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5H15c0.28,0,0.5,0.22,0.5,0.5S15.28,12.5,15,12.5
|
||||
z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M9.5,12.5h-3C6.22,12.5,6,12.28,6,12s0.22-0.5,0.5-0.5h3c0.28,0,0.5,0.22,0.5,0.5S9.78,12.5,9.5,12.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M3.5,12.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h2.5C3.78,11.5,4,11.72,4,12S3.78,12.5,3.5,12.5z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,14.5H1c-0.28,0-0.5-0.22-0.5-0.5s0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5S15.28,14.5,15,14.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M15,9.5h-3.69l-0.04,0.1c-0.12,0.29-0.42,0.5-0.73,0.53l-0.18,0.01c0.04,0.01-0.13,0.13-0.21,0.2
|
||||
l-0.02,0.16H15c0.28,0,0.5-0.22,0.5-0.5S15.28,9.5,15,9.5z"/>
|
||||
<path fill="#808080" d="M5.86,10.36c-0.01,0.04-0.13-0.14-0.2-0.22l-0.2-0.02C5.16,10.1,4.85,9.89,4.73,9.6L4.69,9.5H1
|
||||
c-0.28,0-0.5,0.22-0.5,0.5s0.22,0.5,0.5,0.5h4.87L5.86,10.36z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#808080" d="M4.74,6.4c0.12-0.29,0.42-0.5,0.73-0.52l0.17-0.01C5.6,5.86,5.77,5.73,5.85,5.66L5.87,5.5H1
|
||||
C0.72,5.5,0.5,5.72,0.5,6S0.72,6.5,1,6.5h3.69L4.74,6.4z"/>
|
||||
<path fill="#808080" d="M15,5.5h-4.87l0.01,0.14c0-0.03,0.13,0.13,0.2,0.21l0.2,0.02c0.31,0.02,0.61,0.24,0.73,0.53l0.04,0.1H15
|
||||
c0.28,0,0.5-0.22,0.5-0.5S15.28,5.5,15,5.5z"/>
|
||||
</g>
|
||||
<path fill="#ED6B21" d="M10.67,7.89c-0.01-0.12,0.05-0.29,0.13-0.38l0.11-0.13c0.08-0.09,0.11-0.26,0.06-0.37L10.8,6.59
|
||||
c-0.05-0.11-0.18-0.21-0.3-0.22l-0.17-0.01c-0.12-0.01-0.28-0.09-0.36-0.18C9.89,6.1,9.65,5.79,9.64,5.67L9.63,5.5
|
||||
C9.62,5.38,9.52,5.24,9.41,5.2L8.99,5.02C8.88,4.98,8.71,5,8.62,5.08L8.49,5.2C8.4,5.28,8.22,5.33,8.11,5.33
|
||||
C7.99,5.32,7.6,5.27,7.51,5.2L7.38,5.08C7.29,5,7.13,4.98,7.01,5.02L6.59,5.2C6.48,5.24,6.38,5.38,6.37,5.5L6.36,5.67
|
||||
C6.35,5.79,6.27,5.95,6.19,6.03S5.79,6.35,5.67,6.36L5.5,6.37C5.38,6.38,5.24,6.48,5.2,6.59L5.02,7.01C4.98,7.12,5,7.29,5.08,7.38
|
||||
L5.2,7.51C5.28,7.6,5.33,7.78,5.33,7.89C5.32,8.01,5.27,8.4,5.2,8.49L5.08,8.62C5,8.71,4.98,8.87,5.02,8.99L5.2,9.41
|
||||
c0.05,0.11,0.18,0.21,0.3,0.22l0.17,0.01c0.12,0.01,0.28,0.09,0.36,0.18c0.08,0.09,0.32,0.39,0.33,0.51l0.01,0.17
|
||||
c0.01,0.12,0.11,0.26,0.22,0.3l0.42,0.17c0.11,0.05,0.28,0.02,0.37-0.06l0.13-0.11c0.09-0.08,0.26-0.14,0.38-0.13
|
||||
c0.12,0.01,0.5,0.05,0.59,0.13l0.13,0.11c0.09,0.08,0.26,0.11,0.37,0.06l0.42-0.17c0.11-0.05,0.21-0.18,0.22-0.3l0.01-0.17
|
||||
c0.01-0.12,0.09-0.28,0.18-0.36c0.09-0.08,0.39-0.32,0.51-0.33l0.17-0.01c0.12-0.01,0.26-0.11,0.3-0.22l0.17-0.42
|
||||
c0.05-0.11,0.02-0.28-0.06-0.37L10.8,8.49C10.72,8.4,10.68,8.01,10.67,7.89z M8,9.8c-0.99,0-1.8-0.8-1.8-1.8S7.01,6.2,8,6.2
|
||||
S9.8,7.01,9.8,8S8.99,9.8,8,9.8z"/>
|
||||
<g id="edit_x5F_layers_x5F_some_1_">
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="11" x2="14" y2="11"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/>
|
||||
<path fill="#ED6B21" d="M7.68,8.87c0.18,0.18,0.47,0.18,0.64,0L11.19,6c0.18-0.18,0.12-0.32-0.13-0.32H9.62
|
||||
c-0.25,0-0.45-0.2-0.45-0.45V1.45C9.17,1.2,8.97,1,8.71,1H7.29C7.03,1,6.83,1.2,6.83,1.45v3.77c0,0.25-0.2,0.45-0.45,0.45H4.95
|
||||
C4.7,5.68,4.64,5.82,4.81,6L7.68,8.87z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 931 B |
10
resources/icons/lock_closed_f.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_closed">
|
||||
<path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="9" d="M4,8V4c0,0,0-2,2-2c1,0,3,0,4,0c2,0,2,2,2,2v4"/>
|
||||
<path fill="#808080" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 728 B |
11
resources/icons/lock_open_f.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_open">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2
|
||||
c1,0,3,0,4,0c2,0,2,2,2,2v1"/>
|
||||
<path fill="#ED6B21" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 753 B |
|
@ -4,19 +4,19 @@
|
|||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="mirror_x5F_off">
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l4,0c0.55,0,1,0.45,1,1v8
|
||||
c0,0.55-0.45,1-1,1h-4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M10,3.01l3,0c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L2,3C1.45,3,1,3.45,1,4v8
|
||||
c0,0.55,0.45,1,1,1h4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M6,3.01L3,3C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -2,21 +2,21 @@
|
|||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="mirror_x5F_off_1_">
|
||||
<g id="mirror_x5F_on">
|
||||
<g>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l4,0c0.55,0,1,0.45,1,1v8
|
||||
c0,0.55-0.45,1-1,1h-4"/>
|
||||
<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l3,0
|
||||
c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L2,3C1.45,3,1,3.45,1,4v8
|
||||
c0,0.55,0.45,1,1,1h4"/>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L3,3
|
||||
C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/>
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/>
|
||||
<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -1,4 +1,9 @@
|
|||
min_slic3r_version = 2.1.0-alpha0
|
||||
1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX
|
||||
min_slic3r_version = 1.42.0-alpha6
|
||||
0.8.3 FW version and SL1 materials update
|
||||
0.8.2 FFF and SL1 settings update
|
||||
0.8.1 Output settings and SLA materials update
|
||||
0.8.0 Updated for the PrusaSlicer 2.0.0 final release
|
||||
0.8.0-rc2 Updated firmware versions for MK2.5/S and MK3/S
|
||||
0.8.0-rc1 Updated SLA profiles
|
||||
|
@ -18,6 +23,8 @@ min_slic3r_version = 1.42.0-alpha
|
|||
0.4.0-alpha3 Update of SLA profiles
|
||||
0.4.0-alpha2 First SLA profiles
|
||||
min_slic3r_version = 1.41.3-alpha
|
||||
0.4.8 MK2.5/3/S FW update
|
||||
0.4.7 MK2/S/MMU FW update
|
||||
0.4.6 Updated firmware versions for MK2.5/S and MK3/S
|
||||
0.4.5 Enabled remaining time support for MK2/S/MMU1
|
||||
0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
|
@ -26,6 +33,8 @@ min_slic3r_version = 1.41.3-alpha
|
|||
0.4.1 New MK2.5S and MK3S FW versions
|
||||
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
min_slic3r_version = 1.41.1
|
||||
0.3.8 MK2.5/3/S FW update
|
||||
0.3.7 MK2/S/MMU FW update
|
||||
0.3.6 Updated firmware versions for MK2.5 and MK3
|
||||
0.3.5 New MK2.5 and MK3 FW versions
|
||||
0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
|
@ -60,6 +69,8 @@ min_slic3r_version = 1.41.0-alpha
|
|||
0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
|
||||
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
|
||||
min_slic3r_version = 1.40.0
|
||||
0.1.16 MK2.5/3/S FW update
|
||||
0.1.15 MK2/S/MMU FW update
|
||||
0.1.14 Updated firmware versions for MK2.5 and MK3
|
||||
0.1.13 New MK2.5 and MK3 FW versions
|
||||
0.1.12 New MK2.5 and MK3 FW versions
|
||||
|
|
|
@ -102,7 +102,7 @@ protected:
|
|||
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||
return from - save_from;
|
||||
#else
|
||||
return save_max - max;
|
||||
return int(save_max - max);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -211,25 +211,35 @@ std::vector<std::string> ConfigOptionDef::cli_args(const std::string &key) const
|
|||
|
||||
ConfigOption* ConfigOptionDef::create_empty_option() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case coFloat: return new ConfigOptionFloat();
|
||||
case coFloats: return new ConfigOptionFloats();
|
||||
case coInt: return new ConfigOptionInt();
|
||||
case coInts: return new ConfigOptionInts();
|
||||
case coString: return new ConfigOptionString();
|
||||
case coStrings: return new ConfigOptionStrings();
|
||||
case coPercent: return new ConfigOptionPercent();
|
||||
case coPercents: return new ConfigOptionPercents();
|
||||
case coFloatOrPercent: return new ConfigOptionFloatOrPercent();
|
||||
case coPoint: return new ConfigOptionPoint();
|
||||
case coPoints: return new ConfigOptionPoints();
|
||||
case coPoint3: return new ConfigOptionPoint3();
|
||||
// case coPoint3s: return new ConfigOptionPoint3s();
|
||||
case coBool: return new ConfigOptionBool();
|
||||
case coBools: return new ConfigOptionBools();
|
||||
case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map);
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label);
|
||||
}
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloats: return new ConfigOptionFloatsNullable();
|
||||
case coInts: return new ConfigOptionIntsNullable();
|
||||
case coPercents: return new ConfigOptionPercentsNullable();
|
||||
case coBools: return new ConfigOptionBoolsNullable();
|
||||
default: throw std::runtime_error(std::string("Unknown option type for nullable option ") + this->label);
|
||||
}
|
||||
} else {
|
||||
switch (this->type) {
|
||||
case coFloat: return new ConfigOptionFloat();
|
||||
case coFloats: return new ConfigOptionFloats();
|
||||
case coInt: return new ConfigOptionInt();
|
||||
case coInts: return new ConfigOptionInts();
|
||||
case coString: return new ConfigOptionString();
|
||||
case coStrings: return new ConfigOptionStrings();
|
||||
case coPercent: return new ConfigOptionPercent();
|
||||
case coPercents: return new ConfigOptionPercents();
|
||||
case coFloatOrPercent: return new ConfigOptionFloatOrPercent();
|
||||
case coPoint: return new ConfigOptionPoint();
|
||||
case coPoints: return new ConfigOptionPoints();
|
||||
case coPoint3: return new ConfigOptionPoint3();
|
||||
// case coPoint3s: return new ConfigOptionPoint3s();
|
||||
case coBool: return new ConfigOptionBool();
|
||||
case coBools: return new ConfigOptionBools();
|
||||
case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map);
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConfigOption* ConfigOptionDef::create_default_option() const
|
||||
|
@ -254,6 +264,13 @@ ConfigOptionDef* ConfigDef::add(const t_config_option_key &opt_key, ConfigOption
|
|||
return opt;
|
||||
}
|
||||
|
||||
ConfigOptionDef* ConfigDef::add_nullable(const t_config_option_key &opt_key, ConfigOptionType type)
|
||||
{
|
||||
ConfigOptionDef *def = this->add(opt_key, type);
|
||||
def->nullable = true;
|
||||
return def;
|
||||
}
|
||||
|
||||
std::string ConfigOptionDef::nocli = "~~~noCLI";
|
||||
|
||||
std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const
|
||||
|
@ -642,6 +659,17 @@ void ConfigBase::save(const std::string &file) const
|
|||
c.close();
|
||||
}
|
||||
|
||||
// Set all the nullable values to nils.
|
||||
void ConfigBase::null_nullables()
|
||||
{
|
||||
for (const std::string &opt_key : this->keys()) {
|
||||
ConfigOption *opt = this->optptr(opt_key, false);
|
||||
assert(opt != nullptr);
|
||||
if (opt->nullable())
|
||||
opt->deserialize("nil");
|
||||
}
|
||||
}
|
||||
|
||||
bool DynamicConfig::operator==(const DynamicConfig &rhs) const
|
||||
{
|
||||
auto it1 = this->options.begin();
|
||||
|
@ -655,6 +683,19 @@ bool DynamicConfig::operator==(const DynamicConfig &rhs) const
|
|||
return it1 == it1_end && it2 == it2_end;
|
||||
}
|
||||
|
||||
// Remove options with all nil values, those are optional and it does not help to hold them.
|
||||
size_t DynamicConfig::remove_nil_options()
|
||||
{
|
||||
size_t cnt_removed = 0;
|
||||
for (auto it = options.begin(); it != options.end();)
|
||||
if (it->second->is_nil()) {
|
||||
it = options.erase(it);
|
||||
++ cnt_removed;
|
||||
} else
|
||||
++ it;
|
||||
return cnt_removed;
|
||||
}
|
||||
|
||||
ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create)
|
||||
{
|
||||
auto it = options.find(opt_key);
|
||||
|
@ -838,18 +879,22 @@ CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<Slic3r::Vec2d>)
|
|||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionVector<unsigned char>)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloat)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionIntsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionString)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionStrings)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercent)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercents)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPercentsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionFloatOrPercent)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoints)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionPoint3)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBool)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBools)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionBoolsNullable)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigOptionEnumGeneric)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::ConfigBase)
|
||||
CEREAL_REGISTER_TYPE(Slic3r::DynamicConfig)
|
||||
|
@ -868,17 +913,21 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::Con
|
|||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVectorBase, Slic3r::ConfigOptionVector<unsigned char>)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<double>, Slic3r::ConfigOptionFloat)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<double>, Slic3r::ConfigOptionFloats)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<double>, Slic3r::ConfigOptionFloatsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<int>, Slic3r::ConfigOptionInt)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<int>, Slic3r::ConfigOptionInts)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<int>, Slic3r::ConfigOptionIntsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<std::string>, Slic3r::ConfigOptionString)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<std::string>, Slic3r::ConfigOptionStrings)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloat, Slic3r::ConfigOptionPercent)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloats, Slic3r::ConfigOptionPercents)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionFloats, Slic3r::ConfigOptionPercentsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionPercent, Slic3r::ConfigOptionFloatOrPercent)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<Slic3r::Vec2d>, Slic3r::ConfigOptionPoint)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<Slic3r::Vec2d>, Slic3r::ConfigOptionPoints)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<Slic3r::Vec3d>, Slic3r::ConfigOptionPoint3)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionSingle<bool>, Slic3r::ConfigOptionBool)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBools)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionVector<unsigned char>, Slic3r::ConfigOptionBoolsNullable)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigOptionInt, Slic3r::ConfigOptionEnumGeneric)
|
||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ConfigBase, Slic3r::DynamicConfig)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clonable_ptr.hpp"
|
||||
#include "Point.hpp"
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
|
@ -124,6 +125,23 @@ public:
|
|||
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
|
||||
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
|
||||
bool is_vector() const { return ! this->is_scalar(); }
|
||||
// If this option is nullable, then it may have its value or values set to nil.
|
||||
virtual bool nullable() const { return false; }
|
||||
// A scalar is nil, or all values of a vector are nil.
|
||||
virtual bool is_nil() const { return false; }
|
||||
// Is this option overridden by another option?
|
||||
// An option overrides another option if it is not nil and not equal.
|
||||
virtual bool overriden_by(const ConfigOption *rhs) const {
|
||||
assert(! this->nullable() && ! rhs->nullable());
|
||||
return *this != *rhs;
|
||||
}
|
||||
// Apply an override option, possibly a nullable one.
|
||||
virtual bool apply_override(const ConfigOption *rhs) {
|
||||
if (*this == *rhs)
|
||||
return false;
|
||||
*this = *rhs;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ConfigOption* ConfigOptionPtr;
|
||||
|
@ -183,6 +201,8 @@ public:
|
|||
virtual size_t size() const = 0;
|
||||
// Is this vector empty?
|
||||
virtual bool empty() const = 0;
|
||||
// Is the value nil? That should only be possible if this->nullable().
|
||||
virtual bool is_nil(size_t idx) const = 0;
|
||||
|
||||
protected:
|
||||
// Used to verify type compatibility when assigning to / from a scalar ConfigOption.
|
||||
|
@ -302,6 +322,62 @@ public:
|
|||
bool operator==(const std::vector<T> &rhs) const { return this->values == rhs; }
|
||||
bool operator!=(const std::vector<T> &rhs) const { return this->values != rhs; }
|
||||
|
||||
// Is this option overridden by another option?
|
||||
// An option overrides another option if it is not nil and not equal.
|
||||
bool overriden_by(const ConfigOption *rhs) const override {
|
||||
if (this->nullable())
|
||||
throw std::runtime_error("Cannot override a nullable ConfigOption.");
|
||||
if (rhs->type() != this->type())
|
||||
throw std::runtime_error("ConfigOptionVector.overriden_by() applied to different types.");
|
||||
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
|
||||
if (! rhs->nullable())
|
||||
// Overridding a non-nullable object with another non-nullable object.
|
||||
return this->values != rhs_vec->values;
|
||||
size_t i = 0;
|
||||
size_t cnt = std::min(this->size(), rhs_vec->size());
|
||||
for (; i < cnt; ++ i)
|
||||
if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i])
|
||||
return true;
|
||||
for (; i < rhs_vec->size(); ++ i)
|
||||
if (! rhs_vec->is_nil(i))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// Apply an override option, possibly a nullable one.
|
||||
bool apply_override(const ConfigOption *rhs) override {
|
||||
if (this->nullable())
|
||||
throw std::runtime_error("Cannot override a nullable ConfigOption.");
|
||||
if (rhs->type() != this->type())
|
||||
throw std::runtime_error("ConfigOptionVector.apply_override() applied to different types.");
|
||||
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
|
||||
if (! rhs->nullable()) {
|
||||
// Overridding a non-nullable object with another non-nullable object.
|
||||
if (this->values != rhs_vec->values) {
|
||||
this->values = rhs_vec->values;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
size_t i = 0;
|
||||
size_t cnt = std::min(this->size(), rhs_vec->size());
|
||||
bool modified = false;
|
||||
for (; i < cnt; ++ i)
|
||||
if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i]) {
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
for (; i < rhs_vec->size(); ++ i)
|
||||
if (! rhs_vec->is_nil(i)) {
|
||||
if (this->values.empty())
|
||||
this->values.resize(i + 1);
|
||||
else
|
||||
this->values.resize(i + 1, this->values.front());
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive & ar) { ar(this->values); }
|
||||
|
@ -345,26 +421,41 @@ private:
|
|||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionFloats : public ConfigOptionVector<double>
|
||||
template<bool NULLABLE>
|
||||
class ConfigOptionFloatsTempl : public ConfigOptionVector<double>
|
||||
{
|
||||
public:
|
||||
ConfigOptionFloats() : ConfigOptionVector<double>() {}
|
||||
explicit ConfigOptionFloats(size_t n, double value) : ConfigOptionVector<double>(n, value) {}
|
||||
explicit ConfigOptionFloats(std::initializer_list<double> il) : ConfigOptionVector<double>(std::move(il)) {}
|
||||
explicit ConfigOptionFloats(const std::vector<double> &vec) : ConfigOptionVector<double>(vec) {}
|
||||
explicit ConfigOptionFloats(std::vector<double> &&vec) : ConfigOptionVector<double>(std::move(vec)) {}
|
||||
ConfigOptionFloatsTempl() : ConfigOptionVector<double>() {}
|
||||
explicit ConfigOptionFloatsTempl(size_t n, double value) : ConfigOptionVector<double>(n, value) {}
|
||||
explicit ConfigOptionFloatsTempl(std::initializer_list<double> il) : ConfigOptionVector<double>(std::move(il)) {}
|
||||
explicit ConfigOptionFloatsTempl(const std::vector<double> &vec) : ConfigOptionVector<double>(vec) {}
|
||||
explicit ConfigOptionFloatsTempl(std::vector<double> &&vec) : ConfigOptionVector<double>(std::move(vec)) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coFloats; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionFloats(*this); }
|
||||
bool operator==(const ConfigOptionFloats &rhs) const { return this->values == rhs.values; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionFloatsTempl(*this); }
|
||||
bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
|
||||
bool operator==(const ConfigOption &rhs) const override {
|
||||
if (rhs.type() != this->type())
|
||||
throw std::runtime_error("ConfigOptionFloatsTempl: Comparing incompatible types");
|
||||
assert(dynamic_cast<const ConfigOptionVector<double>*>(&rhs));
|
||||
return vectors_equal(this->values, static_cast<const ConfigOptionVector<double>*>(&rhs)->values);
|
||||
}
|
||||
// Could a special "nil" value be stored inside the vector, indicating undefined value?
|
||||
bool nullable() const override { return NULLABLE; }
|
||||
// Special "nil" value to be stored into the vector if this->supports_nil().
|
||||
static double nil_value() { return std::numeric_limits<double>::quiet_NaN(); }
|
||||
// A scalar is nil, or all values of a vector are nil.
|
||||
bool is_nil() const override { for (auto v : this->values) if (! std::isnan(v)) return false; return true; }
|
||||
bool is_nil(size_t idx) const override { return std::isnan(this->values[idx]); }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
for (std::vector<double>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
if (it - this->values.begin() != 0) ss << ",";
|
||||
ss << *it;
|
||||
for (const double &v : this->values) {
|
||||
if (&v != &this->values.front())
|
||||
ss << ",";
|
||||
serialize_single_value(ss, v);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
@ -373,14 +464,14 @@ public:
|
|||
{
|
||||
std::vector<std::string> vv;
|
||||
vv.reserve(this->values.size());
|
||||
for (std::vector<double>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
for (const double v : this->values) {
|
||||
std::ostringstream ss;
|
||||
ss << *it;
|
||||
serialize_single_value(ss, v);
|
||||
vv.push_back(ss.str());
|
||||
}
|
||||
return vv;
|
||||
}
|
||||
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) override
|
||||
{
|
||||
if (! append)
|
||||
|
@ -388,25 +479,61 @@ public:
|
|||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
std::istringstream iss(item_str);
|
||||
double value;
|
||||
iss >> value;
|
||||
this->values.push_back(value);
|
||||
boost::trim(item_str);
|
||||
if (item_str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->values.push_back(nil_value());
|
||||
else
|
||||
std::runtime_error("Deserializing nil into a non-nullable object");
|
||||
} else {
|
||||
std::istringstream iss(item_str);
|
||||
double value;
|
||||
iss >> value;
|
||||
this->values.push_back(value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ConfigOptionFloats& operator=(const ConfigOption *opt)
|
||||
ConfigOptionFloatsTempl& operator=(const ConfigOption *opt)
|
||||
{
|
||||
this->set(opt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void serialize_single_value(std::ostringstream &ss, const double v) const {
|
||||
if (std::isfinite(v))
|
||||
ss << v;
|
||||
else if (std::isnan(v)) {
|
||||
if (NULLABLE)
|
||||
ss << "nil";
|
||||
else
|
||||
std::runtime_error("Serializing NaN");
|
||||
} else
|
||||
std::runtime_error("Serializing invalid number");
|
||||
}
|
||||
static bool vectors_equal(const std::vector<double> &v1, const std::vector<double> &v2) {
|
||||
if (NULLABLE) {
|
||||
if (v1.size() != v2.size())
|
||||
return false;
|
||||
for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2)
|
||||
if (! ((std::isnan(*it1) && std::isnan(*it2)) || *it1 == *it2))
|
||||
return false;
|
||||
return true;
|
||||
} else
|
||||
// Not supporting nullable values, the default vector compare is cheaper.
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<double>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionFloats = ConfigOptionFloatsTempl<false>;
|
||||
using ConfigOptionFloatsNullable = ConfigOptionFloatsTempl<true>;
|
||||
|
||||
class ConfigOptionInt : public ConfigOptionSingle<int>
|
||||
{
|
||||
public:
|
||||
|
@ -447,35 +574,45 @@ private:
|
|||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<int>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionInts : public ConfigOptionVector<int>
|
||||
template<bool NULLABLE>
|
||||
class ConfigOptionIntsTempl : public ConfigOptionVector<int>
|
||||
{
|
||||
public:
|
||||
ConfigOptionInts() : ConfigOptionVector<int>() {}
|
||||
explicit ConfigOptionInts(size_t n, int value) : ConfigOptionVector<int>(n, value) {}
|
||||
explicit ConfigOptionInts(std::initializer_list<int> il) : ConfigOptionVector<int>(std::move(il)) {}
|
||||
ConfigOptionIntsTempl() : ConfigOptionVector<int>() {}
|
||||
explicit ConfigOptionIntsTempl(size_t n, int value) : ConfigOptionVector<int>(n, value) {}
|
||||
explicit ConfigOptionIntsTempl(std::initializer_list<int> il) : ConfigOptionVector<int>(std::move(il)) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coInts; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionInts(*this); }
|
||||
ConfigOptionInts& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionInts &rhs) const { return this->values == rhs.values; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionIntsTempl(*this); }
|
||||
ConfigOptionIntsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionIntsTempl &rhs) const { return this->values == rhs.values; }
|
||||
// Could a special "nil" value be stored inside the vector, indicating undefined value?
|
||||
bool nullable() const override { return NULLABLE; }
|
||||
// Special "nil" value to be stored into the vector if this->supports_nil().
|
||||
static int nil_value() { return std::numeric_limits<int>::max(); }
|
||||
// A scalar is nil, or all values of a vector are nil.
|
||||
bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
|
||||
bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
|
||||
|
||||
std::string serialize() const override {
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
for (std::vector<int>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
if (it - this->values.begin() != 0) ss << ",";
|
||||
ss << *it;
|
||||
for (const int &v : this->values) {
|
||||
if (&v != &this->values.front())
|
||||
ss << ",";
|
||||
serialize_single_value(ss, v);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<std::string> vserialize() const override
|
||||
std::vector<std::string> vserialize() const override
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
vv.reserve(this->values.size());
|
||||
for (std::vector<int>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
for (const int v : this->values) {
|
||||
std::ostringstream ss;
|
||||
ss << *it;
|
||||
serialize_single_value(ss, v);
|
||||
vv.push_back(ss.str());
|
||||
}
|
||||
return vv;
|
||||
|
@ -488,19 +625,40 @@ public:
|
|||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
std::istringstream iss(item_str);
|
||||
int value;
|
||||
iss >> value;
|
||||
this->values.push_back(value);
|
||||
boost::trim(item_str);
|
||||
if (item_str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->values.push_back(nil_value());
|
||||
else
|
||||
std::runtime_error("Deserializing nil into a non-nullable object");
|
||||
} else {
|
||||
std::istringstream iss(item_str);
|
||||
int value;
|
||||
iss >> value;
|
||||
this->values.push_back(value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void serialize_single_value(std::ostringstream &ss, const int v) const {
|
||||
if (v == nil_value()) {
|
||||
if (NULLABLE)
|
||||
ss << "nil";
|
||||
else
|
||||
std::runtime_error("Serializing NaN");
|
||||
} else
|
||||
ss << v;
|
||||
}
|
||||
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<int>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionInts = ConfigOptionIntsTempl<false>;
|
||||
using ConfigOptionIntsNullable = ConfigOptionIntsTempl<true>;
|
||||
|
||||
class ConfigOptionString : public ConfigOptionSingle<std::string>
|
||||
{
|
||||
public:
|
||||
|
@ -544,6 +702,7 @@ public:
|
|||
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
|
||||
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
|
||||
bool is_nil(size_t idx) const override { return false; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
|
@ -603,64 +762,61 @@ private:
|
|||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloat>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionPercents : public ConfigOptionFloats
|
||||
template<bool NULLABLE>
|
||||
class ConfigOptionPercentsTempl : public ConfigOptionFloatsTempl<NULLABLE>
|
||||
{
|
||||
public:
|
||||
ConfigOptionPercents() : ConfigOptionFloats() {}
|
||||
explicit ConfigOptionPercents(size_t n, double value) : ConfigOptionFloats(n, value) {}
|
||||
explicit ConfigOptionPercents(std::initializer_list<double> il) : ConfigOptionFloats(std::move(il)) {}
|
||||
ConfigOptionPercentsTempl() : ConfigOptionFloatsTempl<NULLABLE>() {}
|
||||
explicit ConfigOptionPercentsTempl(size_t n, double value) : ConfigOptionFloatsTempl<NULLABLE>(n, value) {}
|
||||
explicit ConfigOptionPercentsTempl(std::initializer_list<double> il) : ConfigOptionFloatsTempl<NULLABLE>(std::move(il)) {}
|
||||
explicit ConfigOptionPercentsTempl(const std::vector<double>& vec) : ConfigOptionFloatsTempl<NULLABLE>(vec) {}
|
||||
explicit ConfigOptionPercentsTempl(std::vector<double>&& vec) : ConfigOptionFloatsTempl<NULLABLE>(std::move(vec)) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coPercents; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPercents(*this); }
|
||||
ConfigOptionPercents& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionPercents &rhs) const { return this->values == rhs.values; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPercentsTempl(*this); }
|
||||
ConfigOptionPercentsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionPercentsTempl &rhs) const { return this->values == rhs.values; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
for (const auto &v : this->values) {
|
||||
if (&v != &this->values.front()) ss << ",";
|
||||
ss << v << "%";
|
||||
for (const double &v : this->values) {
|
||||
if (&v != &this->values.front())
|
||||
ss << ",";
|
||||
this->serialize_single_value(ss, v);
|
||||
if (! std::isnan(v))
|
||||
ss << "%";
|
||||
}
|
||||
std::string str = ss.str();
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> vserialize() const override
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
vv.reserve(this->values.size());
|
||||
for (const auto v : this->values) {
|
||||
for (const double v : this->values) {
|
||||
std::ostringstream ss;
|
||||
ss << v;
|
||||
std::string sout = ss.str() + "%";
|
||||
vv.push_back(sout);
|
||||
this->serialize_single_value(ss, v);
|
||||
if (! std::isnan(v))
|
||||
ss << "%";
|
||||
vv.push_back(ss.str());
|
||||
}
|
||||
return vv;
|
||||
}
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) override
|
||||
{
|
||||
if (! append)
|
||||
this->values.clear();
|
||||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
std::istringstream iss(item_str);
|
||||
double value;
|
||||
// don't try to parse the trailing % since it's optional
|
||||
iss >> value;
|
||||
this->values.push_back(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// The float's deserialize function shall ignore the trailing optional %.
|
||||
// bool deserialize(const std::string &str, bool append = false) override;
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloats>(this)); }
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloatsTempl<NULLABLE>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionPercents = ConfigOptionPercentsTempl<false>;
|
||||
using ConfigOptionPercentsNullable = ConfigOptionPercentsTempl<true>;
|
||||
|
||||
class ConfigOptionFloatOrPercent : public ConfigOptionPercent
|
||||
{
|
||||
public:
|
||||
|
@ -761,6 +917,7 @@ public:
|
|||
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
|
||||
ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
|
||||
bool is_nil(size_t idx) const override { return false; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
|
@ -887,18 +1044,29 @@ private:
|
|||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<bool>>(this)); }
|
||||
};
|
||||
|
||||
class ConfigOptionBools : public ConfigOptionVector<unsigned char>
|
||||
template<bool NULLABLE>
|
||||
class ConfigOptionBoolsTempl : public ConfigOptionVector<unsigned char>
|
||||
{
|
||||
public:
|
||||
ConfigOptionBools() : ConfigOptionVector<unsigned char>() {}
|
||||
explicit ConfigOptionBools(size_t n, bool value) : ConfigOptionVector<unsigned char>(n, (unsigned char)value) {}
|
||||
explicit ConfigOptionBools(std::initializer_list<bool> il) { values.reserve(il.size()); for (bool b : il) values.emplace_back((unsigned char)b); }
|
||||
ConfigOptionBoolsTempl() : ConfigOptionVector<unsigned char>() {}
|
||||
explicit ConfigOptionBoolsTempl(size_t n, bool value) : ConfigOptionVector<unsigned char>(n, (unsigned char)value) {}
|
||||
explicit ConfigOptionBoolsTempl(std::initializer_list<bool> il) { values.reserve(il.size()); for (bool b : il) values.emplace_back((unsigned char)b); }
|
||||
explicit ConfigOptionBoolsTempl(std::initializer_list<unsigned char> il) { values.reserve(il.size()); for (unsigned char b : il) values.emplace_back(b); }
|
||||
explicit ConfigOptionBoolsTempl(const std::vector<unsigned char>& vec) : ConfigOptionVector<unsigned char>(vec) {}
|
||||
explicit ConfigOptionBoolsTempl(std::vector<unsigned char>&& vec) : ConfigOptionVector<unsigned char>(std::move(vec)) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coBools; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionBools(*this); }
|
||||
ConfigOptionBools& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionBools &rhs) const { return this->values == rhs.values; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionBoolsTempl(*this); }
|
||||
ConfigOptionBoolsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionBoolsTempl &rhs) const { return this->values == rhs.values; }
|
||||
// Could a special "nil" value be stored inside the vector, indicating undefined value?
|
||||
bool nullable() const override { return NULLABLE; }
|
||||
// Special "nil" value to be stored into the vector if this->supports_nil().
|
||||
static unsigned char nil_value() { return std::numeric_limits<unsigned char>::max(); }
|
||||
// A scalar is nil, or all values of a vector are nil.
|
||||
bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
|
||||
bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
|
||||
|
||||
bool& get_at(size_t i) {
|
||||
assert(! this->values.empty());
|
||||
|
@ -911,19 +1079,20 @@ public:
|
|||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
for (std::vector<unsigned char>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
if (it - this->values.begin() != 0) ss << ",";
|
||||
ss << (*it ? "1" : "0");
|
||||
}
|
||||
for (const unsigned char &v : this->values) {
|
||||
if (&v != &this->values.front())
|
||||
ss << ",";
|
||||
this->serialize_single_value(ss, v);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<std::string> vserialize() const override
|
||||
{
|
||||
std::vector<std::string> vv;
|
||||
for (std::vector<unsigned char>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
|
||||
std::ostringstream ss;
|
||||
ss << (*it ? "1" : "0");
|
||||
for (const unsigned char v : this->values) {
|
||||
std::ostringstream ss;
|
||||
this->serialize_single_value(ss, v);
|
||||
vv.push_back(ss.str());
|
||||
}
|
||||
return vv;
|
||||
|
@ -936,16 +1105,37 @@ public:
|
|||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
this->values.push_back(item_str.compare("1") == 0);
|
||||
boost::trim(item_str);
|
||||
if (item_str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->values.push_back(nil_value());
|
||||
else
|
||||
std::runtime_error("Deserializing nil into a non-nullable object");
|
||||
} else
|
||||
this->values.push_back(item_str.compare("1") == 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void serialize_single_value(std::ostringstream &ss, const unsigned char v) const {
|
||||
if (v == nil_value()) {
|
||||
if (NULLABLE)
|
||||
ss << "nil";
|
||||
else
|
||||
std::runtime_error("Serializing NaN");
|
||||
} else
|
||||
ss << (v ? "1" : "0");
|
||||
}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<unsigned char>>(this)); }
|
||||
};
|
||||
|
||||
using ConfigOptionBools = ConfigOptionBoolsTempl<false>;
|
||||
using ConfigOptionBoolsNullable = ConfigOptionBoolsTempl<true>;
|
||||
|
||||
// Map from an enum integer value to an enum name.
|
||||
typedef std::vector<std::string> t_config_enum_names;
|
||||
// Map from an enum name to an enum integer value.
|
||||
|
@ -1096,6 +1286,8 @@ public:
|
|||
t_config_option_key opt_key;
|
||||
// What type? bool, int, string etc.
|
||||
ConfigOptionType type = coNone;
|
||||
// If a type is nullable, then it accepts a "nil" value (scalar) or "nil" values (vector).
|
||||
bool nullable = false;
|
||||
// Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
|
||||
Slic3r::clonable_ptr<const ConfigOption> default_value;
|
||||
void set_default_value(const ConfigOption* ptr) { this->default_value = Slic3r::clonable_ptr<const ConfigOption>(ptr); }
|
||||
|
@ -1107,45 +1299,65 @@ public:
|
|||
ConfigOption* create_default_option() const;
|
||||
|
||||
template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
|
||||
switch (this->type) {
|
||||
case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; }
|
||||
case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); return opt; }
|
||||
case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; }
|
||||
case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); return opt; }
|
||||
case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; }
|
||||
case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); return opt; }
|
||||
case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; }
|
||||
case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; }
|
||||
case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; }
|
||||
case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; }
|
||||
case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; }
|
||||
case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; }
|
||||
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
|
||||
case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; }
|
||||
case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; }
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloats: { auto opt = new ConfigOptionFloatsNullable(); archive(*opt); return opt; }
|
||||
case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; }
|
||||
case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); return opt; }
|
||||
case coBools: { auto opt = new ConfigOptionBoolsNullable(); archive(*opt); return opt; }
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown nullable option type for option ") + this->opt_key);
|
||||
}
|
||||
} else {
|
||||
switch (this->type) {
|
||||
case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; }
|
||||
case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); return opt; }
|
||||
case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; }
|
||||
case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); return opt; }
|
||||
case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; }
|
||||
case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); return opt; }
|
||||
case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; }
|
||||
case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; }
|
||||
case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; }
|
||||
case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; }
|
||||
case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; }
|
||||
case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; }
|
||||
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
|
||||
case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; }
|
||||
case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; }
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive> ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const {
|
||||
switch (this->type) {
|
||||
case coFloat: archive(*static_cast<const ConfigOptionFloat*>(opt)); break;
|
||||
case coFloats: archive(*static_cast<const ConfigOptionFloats*>(opt)); break;
|
||||
case coInt: archive(*static_cast<const ConfigOptionInt*>(opt)); break;
|
||||
case coInts: archive(*static_cast<const ConfigOptionInts*>(opt)); break;
|
||||
case coString: archive(*static_cast<const ConfigOptionString*>(opt)); break;
|
||||
case coStrings: archive(*static_cast<const ConfigOptionStrings*>(opt)); break;
|
||||
case coPercent: archive(*static_cast<const ConfigOptionPercent*>(opt)); break;
|
||||
case coPercents: archive(*static_cast<const ConfigOptionPercents*>(opt)); break;
|
||||
case coFloatOrPercent: archive(*static_cast<const ConfigOptionFloatOrPercent*>(opt)); break;
|
||||
case coPoint: archive(*static_cast<const ConfigOptionPoint*>(opt)); break;
|
||||
case coPoints: archive(*static_cast<const ConfigOptionPoints*>(opt)); break;
|
||||
case coPoint3: archive(*static_cast<const ConfigOptionPoint3*>(opt)); break;
|
||||
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
|
||||
case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
|
||||
case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
if (this->nullable) {
|
||||
switch (this->type) {
|
||||
case coFloats: archive(*static_cast<const ConfigOptionFloatsNullable*>(opt)); break;
|
||||
case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break;
|
||||
case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(opt));break;
|
||||
case coBools: archive(*static_cast<const ConfigOptionBoolsNullable*>(opt)); break;
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown nullable option type for option ") + this->opt_key);
|
||||
}
|
||||
} else {
|
||||
switch (this->type) {
|
||||
case coFloat: archive(*static_cast<const ConfigOptionFloat*>(opt)); break;
|
||||
case coFloats: archive(*static_cast<const ConfigOptionFloats*>(opt)); break;
|
||||
case coInt: archive(*static_cast<const ConfigOptionInt*>(opt)); break;
|
||||
case coInts: archive(*static_cast<const ConfigOptionInts*>(opt)); break;
|
||||
case coString: archive(*static_cast<const ConfigOptionString*>(opt)); break;
|
||||
case coStrings: archive(*static_cast<const ConfigOptionStrings*>(opt)); break;
|
||||
case coPercent: archive(*static_cast<const ConfigOptionPercent*>(opt)); break;
|
||||
case coPercents: archive(*static_cast<const ConfigOptionPercents*>(opt)); break;
|
||||
case coFloatOrPercent: archive(*static_cast<const ConfigOptionFloatOrPercent*>(opt)); break;
|
||||
case coPoint: archive(*static_cast<const ConfigOptionPoint*>(opt)); break;
|
||||
case coPoints: archive(*static_cast<const ConfigOptionPoints*>(opt)); break;
|
||||
case coPoint3: archive(*static_cast<const ConfigOptionPoint3*>(opt)); break;
|
||||
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
|
||||
case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
|
||||
case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
|
||||
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
|
||||
}
|
||||
}
|
||||
// Make the compiler happy, shut up the warnings.
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1263,6 +1475,7 @@ public:
|
|||
|
||||
protected:
|
||||
ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type);
|
||||
ConfigOptionDef* add_nullable(const t_config_option_key &opt_key, ConfigOptionType type);
|
||||
};
|
||||
|
||||
// An abstract configuration store.
|
||||
|
@ -1347,6 +1560,9 @@ public:
|
|||
void load(const boost::property_tree::ptree &tree);
|
||||
void save(const std::string &file) const;
|
||||
|
||||
// Set all the nullable values to nils.
|
||||
void null_nullables();
|
||||
|
||||
private:
|
||||
// Set a configuration value from a string.
|
||||
bool set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &str, bool append);
|
||||
|
@ -1444,9 +1660,12 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
// Remove options with all nil values, those are optional and it does not help to hold them.
|
||||
size_t remove_nil_options();
|
||||
|
||||
// Allow DynamicConfig to be instantiated on ints own without a definition.
|
||||
// If the definition is not defined, the method requiring the definition will throw NoDefinitionException.
|
||||
const ConfigDef* def() const override { return nullptr; };
|
||||
const ConfigDef* def() const override { return nullptr; }
|
||||
template<class T> T* opt(const t_config_option_key &opt_key, bool create = false)
|
||||
{ return dynamic_cast<T*>(this->option(opt_key, create)); }
|
||||
template<class T> const T* opt(const t_config_option_key &opt_key) const
|
||||
|
|
|
@ -1829,25 +1829,12 @@ void GCode::apply_print_config(const PrintConfig &print_config)
|
|||
m_config.apply(print_config);
|
||||
}
|
||||
|
||||
void GCode::append_full_config(const Print& print, std::string& str)
|
||||
void GCode::append_full_config(const Print &print, std::string &str)
|
||||
{
|
||||
const StaticPrintConfig *configs[] = { static_cast<const GCodeConfig*>(&print.config()), &print.default_object_config(), &print.default_region_config() };
|
||||
for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) {
|
||||
const StaticPrintConfig *cfg = configs[i];
|
||||
for (const std::string &key : cfg->keys())
|
||||
if (key != "compatible_printers")
|
||||
str += "; " + key + " = " + cfg->opt_serialize(key) + "\n";
|
||||
}
|
||||
const DynamicConfig &full_config = print.placeholder_parser().config();
|
||||
for (const char *key : {
|
||||
"print_settings_id", "filament_settings_id", "sla_print_settings_id", "sla_material_settings_id", "printer_settings_id",
|
||||
"printer_model", "printer_variant",
|
||||
"default_print_profile", "default_filament_profile", "default_sla_print_profile", "default_sla_material_profile",
|
||||
"compatible_prints_condition_cummulative", "compatible_printers_condition_cummulative", "inherits_cummulative" }) {
|
||||
const ConfigOption *opt = full_config.option(key);
|
||||
if (opt != nullptr)
|
||||
str += std::string("; ") + key + " = " + opt->serialize() + "\n";
|
||||
}
|
||||
const DynamicPrintConfig &cfg = print.full_print_config();
|
||||
for (const std::string &key : cfg.keys())
|
||||
if (key != "compatible_prints" && key != "compatible_printers" && ! cfg.option(key)->is_nil())
|
||||
str += "; " + key + " = " + cfg.opt_serialize(key) + "\n";
|
||||
}
|
||||
|
||||
void GCode::set_extruders(const std::vector<unsigned int> &extruder_ids)
|
||||
|
|
|
@ -134,7 +134,7 @@ public:
|
|||
m_filpar[idx].cooling_final_speed = cooling_final_speed;
|
||||
}
|
||||
|
||||
m_filpar[idx].filament_area = (M_PI/4.f) * pow(filament_diameter, 2); // all extruders are assumed to have the same filament diameter at this point
|
||||
m_filpar[idx].filament_area = float((M_PI/4.f) * pow(filament_diameter, 2)); // all extruders are assumed to have the same filament diameter at this point
|
||||
m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
|
||||
|
||||
if (max_volumetric_speed != 0.f)
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
PlaceholderParser::PlaceholderParser()
|
||||
PlaceholderParser::PlaceholderParser(const DynamicConfig *external_config) : m_external_config(external_config)
|
||||
{
|
||||
this->set("version", std::string(SLIC3R_VERSION));
|
||||
this->apply_env_variables();
|
||||
|
@ -94,14 +94,6 @@ void PlaceholderParser::update_timestamp(DynamicConfig &config)
|
|||
config.set_key_value("second", new ConfigOptionInt(timeinfo->tm_sec));
|
||||
}
|
||||
|
||||
// Ignore this key by the placeholder parser.
|
||||
static inline bool placeholder_parser_ignore(const ConfigDef *def, const std::string &opt_key)
|
||||
{
|
||||
const ConfigOptionDef *opt_def = def->get(opt_key);
|
||||
assert(opt_def != nullptr);
|
||||
return (opt_def->multiline && boost::ends_with(opt_key, "_gcode")) || opt_key == "post_process";
|
||||
}
|
||||
|
||||
static inline bool opts_equal(const DynamicConfig &config_old, const DynamicConfig &config_new, const std::string &opt_key)
|
||||
{
|
||||
const ConfigOption *opt_old = config_old.option(opt_key);
|
||||
|
@ -119,7 +111,7 @@ std::vector<std::string> PlaceholderParser::config_diff(const DynamicPrintConfig
|
|||
const ConfigDef *def = rhs.def();
|
||||
std::vector<std::string> diff_keys;
|
||||
for (const t_config_option_key &opt_key : rhs.keys())
|
||||
if (! placeholder_parser_ignore(def, opt_key) && ! opts_equal(m_config, rhs, opt_key))
|
||||
if (! opts_equal(m_config, rhs, opt_key))
|
||||
diff_keys.emplace_back(opt_key);
|
||||
return diff_keys;
|
||||
}
|
||||
|
@ -135,8 +127,6 @@ bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs)
|
|||
const ConfigDef *def = rhs.def();
|
||||
bool modified = false;
|
||||
for (const t_config_option_key &opt_key : rhs.keys()) {
|
||||
if (placeholder_parser_ignore(def, opt_key))
|
||||
continue;
|
||||
if (! opts_equal(m_config, rhs, opt_key)) {
|
||||
// Store a copy of the config option.
|
||||
// Convert FloatOrPercent values to floats first.
|
||||
|
@ -155,7 +145,6 @@ bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs)
|
|||
void PlaceholderParser::apply_only(const DynamicPrintConfig &rhs, const std::vector<std::string> &keys)
|
||||
{
|
||||
for (const t_config_option_key &opt_key : keys) {
|
||||
assert(! placeholder_parser_ignore(rhs.def(), opt_key));
|
||||
// Store a copy of the config option.
|
||||
// Convert FloatOrPercent values to floats first.
|
||||
//FIXME there are some ratio_over chains, which end with empty ratio_with.
|
||||
|
@ -167,6 +156,11 @@ void PlaceholderParser::apply_only(const DynamicPrintConfig &rhs, const std::vec
|
|||
}
|
||||
}
|
||||
|
||||
void PlaceholderParser::apply_config(DynamicPrintConfig &&rhs)
|
||||
{
|
||||
m_config += std::move(rhs);
|
||||
}
|
||||
|
||||
void PlaceholderParser::apply_env_variables()
|
||||
{
|
||||
for (char** env = environ; *env; ++ env) {
|
||||
|
@ -608,6 +602,7 @@ namespace client
|
|||
}
|
||||
|
||||
struct MyContext {
|
||||
const DynamicConfig *external_config = nullptr;
|
||||
const DynamicConfig *config = nullptr;
|
||||
const DynamicConfig *config_override = nullptr;
|
||||
size_t current_extruder_id = 0;
|
||||
|
@ -628,6 +623,8 @@ namespace client
|
|||
opt = config_override->option(opt_key);
|
||||
if (opt == nullptr)
|
||||
opt = config->option(opt_key);
|
||||
if (opt == nullptr && external_config != nullptr)
|
||||
opt = external_config->option(opt_key);
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
@ -1255,6 +1252,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
|
|||
std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) const
|
||||
{
|
||||
client::MyContext context;
|
||||
context.external_config = this->external_config();
|
||||
context.config = &this->config();
|
||||
context.config_override = config_override;
|
||||
context.current_extruder_id = current_extruder_id;
|
||||
|
@ -1266,8 +1264,8 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu
|
|||
bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override)
|
||||
{
|
||||
client::MyContext context;
|
||||
context.config = &config;
|
||||
context.config_override = config_override;
|
||||
context.config = &config;
|
||||
context.config_override = config_override;
|
||||
// Let the macro processor parse just a boolean expression, not the full macro language.
|
||||
context.just_boolean_expression = true;
|
||||
return process_macro(templ, context) == "true";
|
||||
|
|
|
@ -12,13 +12,14 @@ namespace Slic3r {
|
|||
class PlaceholderParser
|
||||
{
|
||||
public:
|
||||
PlaceholderParser();
|
||||
PlaceholderParser(const DynamicConfig *external_config = nullptr);
|
||||
|
||||
// Return a list of keys, which should be changed in m_config from rhs.
|
||||
// This contains keys, which are found in rhs, but not in m_config.
|
||||
std::vector<std::string> config_diff(const DynamicPrintConfig &rhs);
|
||||
// Return true if modified.
|
||||
bool apply_config(const DynamicPrintConfig &config);
|
||||
void apply_config(DynamicPrintConfig &&config);
|
||||
// To be called on the values returned by PlaceholderParser::config_diff().
|
||||
// The keys should already be valid.
|
||||
void apply_only(const DynamicPrintConfig &config, const std::vector<std::string> &keys);
|
||||
|
@ -35,6 +36,8 @@ public:
|
|||
DynamicConfig& config_writable() { return m_config; }
|
||||
const DynamicConfig& config() const { return m_config; }
|
||||
const ConfigOption* option(const std::string &key) const { return m_config.option(key); }
|
||||
// External config is not owned by PlaceholderParser. It has a lowest priority when looking up an option.
|
||||
const DynamicConfig* external_config() const { return m_external_config; }
|
||||
|
||||
// Fill in the template using a macro processing language.
|
||||
// Throws std::runtime_error on syntax or runtime error.
|
||||
|
@ -50,7 +53,9 @@ public:
|
|||
void update_timestamp() { update_timestamp(m_config); }
|
||||
|
||||
private:
|
||||
DynamicConfig m_config;
|
||||
// config has a higher priority than external_config when looking up a symbol.
|
||||
DynamicConfig m_config;
|
||||
const DynamicConfig *m_external_config;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -485,25 +485,82 @@ bool layer_height_ranges_equal(const t_layer_config_ranges &lr1, const t_layer_c
|
|||
return true;
|
||||
}
|
||||
|
||||
Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &config_in)
|
||||
// Collect diffs of configuration values at various containers,
|
||||
// resolve the filament rectract overrides of extruder retract values.
|
||||
void Print::config_diffs(
|
||||
const DynamicPrintConfig &new_full_config,
|
||||
t_config_option_keys &print_diff, t_config_option_keys &object_diff, t_config_option_keys ®ion_diff,
|
||||
t_config_option_keys &full_config_diff,
|
||||
DynamicPrintConfig &placeholder_parser_overrides,
|
||||
DynamicPrintConfig &filament_overrides) const
|
||||
{
|
||||
// Collect changes to print config, account for overrides of extruder retract values by filament presets.
|
||||
{
|
||||
const std::vector<std::string> &extruder_retract_keys = print_config_def.extruder_retract_keys();
|
||||
const std::string filament_prefix = "filament_";
|
||||
for (const t_config_option_key &opt_key : m_config.keys()) {
|
||||
const ConfigOption *opt_old = m_config.option(opt_key);
|
||||
assert(opt_old != nullptr);
|
||||
const ConfigOption *opt_new = new_full_config.option(opt_key);
|
||||
// assert(opt_new != nullptr);
|
||||
if (opt_new == nullptr)
|
||||
//FIXME This may happen when executing some test cases.
|
||||
continue;
|
||||
const ConfigOption *opt_new_filament = std::binary_search(extruder_retract_keys.begin(), extruder_retract_keys.end(), opt_key) ? new_full_config.option(filament_prefix + opt_key) : nullptr;
|
||||
if (opt_new_filament != nullptr && ! opt_new_filament->is_nil()) {
|
||||
// An extruder retract override is available at some of the filament presets.
|
||||
if (*opt_old != *opt_new || opt_new->overriden_by(opt_new_filament)) {
|
||||
auto opt_copy = opt_new->clone();
|
||||
opt_copy->apply_override(opt_new_filament);
|
||||
if (*opt_old == *opt_copy)
|
||||
delete opt_copy;
|
||||
else {
|
||||
filament_overrides.set_key_value(opt_key, opt_copy);
|
||||
print_diff.emplace_back(opt_key);
|
||||
}
|
||||
}
|
||||
} else if (*opt_new != *opt_old)
|
||||
print_diff.emplace_back(opt_key);
|
||||
}
|
||||
}
|
||||
// Collect changes to object and region configs.
|
||||
object_diff = m_default_object_config.diff(new_full_config);
|
||||
region_diff = m_default_region_config.diff(new_full_config);
|
||||
// Prepare for storing of the full print config into new_full_config to be exported into the G-code and to be used by the PlaceholderParser.
|
||||
// As the PlaceholderParser does not interpret the FloatOrPercent values itself, these values are stored into the PlaceholderParser converted to floats.
|
||||
for (const t_config_option_key &opt_key : new_full_config.keys()) {
|
||||
const ConfigOption *opt_old = m_full_print_config.option(opt_key);
|
||||
const ConfigOption *opt_new = new_full_config.option(opt_key);
|
||||
if (opt_old == nullptr || *opt_new != *opt_old)
|
||||
full_config_diff.emplace_back(opt_key);
|
||||
if (opt_new->type() == coFloatOrPercent) {
|
||||
// The m_placeholder_parser is never modified by the background processing, GCode.cpp/hpp makes a copy.
|
||||
const ConfigOption *opt_old_pp = this->placeholder_parser().config().option(opt_key);
|
||||
double new_value = new_full_config.get_abs_value(opt_key);
|
||||
if (opt_old_pp == nullptr || static_cast<const ConfigOptionFloat*>(opt_old_pp)->value != new_value)
|
||||
placeholder_parser_overrides.set_key_value(opt_key, new ConfigOptionFloat(new_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_config)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
check_model_ids_validity(model);
|
||||
#endif /* _DEBUG */
|
||||
|
||||
// Make a copy of the config, normalize it.
|
||||
DynamicPrintConfig config(config_in);
|
||||
config.option("print_settings_id", true);
|
||||
config.option("filament_settings_id", true);
|
||||
config.option("printer_settings_id", true);
|
||||
config.normalize();
|
||||
// Collect changes to print config.
|
||||
t_config_option_keys print_diff = m_config.diff(config);
|
||||
t_config_option_keys object_diff = m_default_object_config.diff(config);
|
||||
t_config_option_keys region_diff = m_default_region_config.diff(config);
|
||||
t_config_option_keys placeholder_parser_diff = this->placeholder_parser().config_diff(config);
|
||||
// Normalize the config.
|
||||
new_full_config.option("print_settings_id", true);
|
||||
new_full_config.option("filament_settings_id", true);
|
||||
new_full_config.option("printer_settings_id", true);
|
||||
new_full_config.normalize();
|
||||
|
||||
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
|
||||
// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
|
||||
t_config_option_keys print_diff, object_diff, region_diff, full_config_diff;
|
||||
DynamicPrintConfig placeholder_parser_overrides, filament_overrides;
|
||||
this->config_diffs(new_full_config, print_diff, object_diff, region_diff, full_config_diff, placeholder_parser_overrides, filament_overrides);
|
||||
|
||||
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
|
||||
unsigned int apply_status = APPLY_STATUS_UNCHANGED;
|
||||
auto update_apply_status = [&apply_status](bool invalidated)
|
||||
{ apply_status = std::max<unsigned int>(apply_status, invalidated ? APPLY_STATUS_INVALIDATED : APPLY_STATUS_CHANGED); };
|
||||
|
@ -516,24 +573,25 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||
// The following call may stop the background processing.
|
||||
if (! print_diff.empty())
|
||||
update_apply_status(this->invalidate_state_by_config_options(print_diff));
|
||||
|
||||
// Apply variables to placeholder parser. The placeholder parser is used by G-code export,
|
||||
// which should be stopped if print_diff is not empty.
|
||||
if (! placeholder_parser_diff.empty()) {
|
||||
if (! full_config_diff.empty() || ! placeholder_parser_overrides.empty()) {
|
||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_only(config, placeholder_parser_diff);
|
||||
m_placeholder_parser.apply_config(std::move(placeholder_parser_overrides));
|
||||
// Set the profile aliases for the PrintBase::output_filename()
|
||||
pp.set("print_preset", config.option("print_settings_id")->clone());
|
||||
pp.set("filament_preset", config.option("filament_settings_id")->clone());
|
||||
pp.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
|
||||
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
|
||||
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
m_config.apply_only(new_full_config, print_diff, true);
|
||||
m_config.apply(filament_overrides);
|
||||
// Handle changes to object config defaults
|
||||
m_default_object_config.apply_only(new_full_config, object_diff, true);
|
||||
// Handle changes to regions config defaults
|
||||
m_default_region_config.apply_only(new_full_config, region_diff, true);
|
||||
m_full_print_config = std::move(new_full_config);
|
||||
}
|
||||
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
m_config.apply_only(config, print_diff, true);
|
||||
// Handle changes to object config defaults
|
||||
m_default_object_config.apply_only(config, object_diff, true);
|
||||
// Handle changes to regions config defaults
|
||||
m_default_region_config.apply_only(config, region_diff, true);
|
||||
|
||||
class LayerRanges
|
||||
{
|
||||
|
@ -545,9 +603,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||
m_ranges.reserve(in.size());
|
||||
// Input ranges are sorted lexicographically. First range trims the other ranges.
|
||||
coordf_t last_z = 0;
|
||||
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range : in) {
|
||||
// for (auto &range : in) {
|
||||
if (range.first.second > last_z) {
|
||||
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range : in)
|
||||
if (range.first.second > last_z) {
|
||||
coordf_t min_z = std::max(range.first.first, 0.);
|
||||
if (min_z > last_z + EPSILON) {
|
||||
m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr);
|
||||
|
@ -559,7 +616,6 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||
last_z = range.first.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_ranges.empty())
|
||||
m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr);
|
||||
else if (m_ranges.back().second == nullptr)
|
||||
|
@ -1707,9 +1763,9 @@ void Print::_make_wipe_tower()
|
|||
(float)m_config.filament_cooling_initial_speed.get_at(i),
|
||||
(float)m_config.filament_cooling_final_speed.get_at(i),
|
||||
m_config.filament_ramming_parameters.get_at(i),
|
||||
m_config.filament_max_volumetric_speed.get_at(i),
|
||||
m_config.nozzle_diameter.get_at(i),
|
||||
m_config.filament_diameter.get_at(i));
|
||||
(float)m_config.filament_max_volumetric_speed.get_at(i),
|
||||
(float)m_config.nozzle_diameter.get_at(i),
|
||||
(float)m_config.filament_diameter.get_at(i));
|
||||
|
||||
m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
|
||||
wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
|
||||
|
@ -1791,47 +1847,7 @@ std::string Print::output_filename(const std::string &filename_base) const
|
|||
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
|
||||
return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
|
||||
}
|
||||
/*
|
||||
// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes
|
||||
// and removing spaces.
|
||||
static std::string short_time(const std::string &time)
|
||||
{
|
||||
// Parse the dhms time format.
|
||||
int days = 0;
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
int seconds = 0;
|
||||
if (time.find('d') != std::string::npos)
|
||||
::sscanf(time.c_str(), "%dd %dh %dm %ds", &days, &hours, &minutes, &seconds);
|
||||
else if (time.find('h') != std::string::npos)
|
||||
::sscanf(time.c_str(), "%dh %dm %ds", &hours, &minutes, &seconds);
|
||||
else if (time.find('m') != std::string::npos)
|
||||
::sscanf(time.c_str(), "%dm %ds", &minutes, &seconds);
|
||||
else if (time.find('s') != std::string::npos)
|
||||
::sscanf(time.c_str(), "%ds", &seconds);
|
||||
// Round to full minutes.
|
||||
if (days + hours + minutes > 0 && seconds >= 30) {
|
||||
if (++ minutes == 60) {
|
||||
minutes = 0;
|
||||
if (++ hours == 24) {
|
||||
hours = 0;
|
||||
++ days;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Format the dhm time.
|
||||
char buffer[64];
|
||||
if (days > 0)
|
||||
::sprintf(buffer, "%dd%dh%dm", days, hours, minutes);
|
||||
else if (hours > 0)
|
||||
::sprintf(buffer, "%dh%dm", hours, minutes);
|
||||
else if (minutes > 0)
|
||||
::sprintf(buffer, "%dm", minutes);
|
||||
else
|
||||
::sprintf(buffer, "%ds", seconds);
|
||||
return buffer;
|
||||
}
|
||||
*/
|
||||
|
||||
DynamicConfig PrintStatistics::config() const
|
||||
{
|
||||
DynamicConfig config;
|
||||
|
|
|
@ -296,7 +296,7 @@ public:
|
|||
void clear() override;
|
||||
bool empty() const override { return m_objects.empty(); }
|
||||
|
||||
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
||||
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
||||
|
||||
void process() override;
|
||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||
|
@ -368,6 +368,13 @@ protected:
|
|||
bool invalidate_step(PrintStep step);
|
||||
|
||||
private:
|
||||
void config_diffs(
|
||||
const DynamicPrintConfig &new_full_config,
|
||||
t_config_option_keys &print_diff, t_config_option_keys &object_diff, t_config_option_keys ®ion_diff,
|
||||
t_config_option_keys &full_config_diff,
|
||||
DynamicPrintConfig &placeholder_parser_overrides,
|
||||
DynamicPrintConfig &filament_overrides) const;
|
||||
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
|
||||
void _make_skirt();
|
||||
|
|
|
@ -217,7 +217,7 @@ protected:
|
|||
class PrintBase
|
||||
{
|
||||
public:
|
||||
PrintBase() { this->restart(); }
|
||||
PrintBase() : m_placeholder_parser(&m_full_print_config) { this->restart(); }
|
||||
inline virtual ~PrintBase() {}
|
||||
|
||||
virtual PrinterTechnology technology() const noexcept = 0;
|
||||
|
@ -240,7 +240,7 @@ public:
|
|||
// Some data was changed, which in turn invalidated already calculated steps.
|
||||
APPLY_STATUS_INVALIDATED,
|
||||
};
|
||||
virtual ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) = 0;
|
||||
virtual ApplyStatus apply(const Model &model, DynamicPrintConfig config) = 0;
|
||||
const Model& model() const { return m_model; }
|
||||
|
||||
struct TaskParams {
|
||||
|
@ -316,7 +316,7 @@ public:
|
|||
virtual bool finished() const = 0;
|
||||
|
||||
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
|
||||
PlaceholderParser& placeholder_parser() { return m_placeholder_parser; }
|
||||
const DynamicPrintConfig& full_print_config() const { return m_full_print_config; }
|
||||
|
||||
virtual std::string output_filename(const std::string &filename_base = std::string()) const = 0;
|
||||
// If the filename_base is set, it is used as the input for the template processing. In that case the path is expected to be the directory (may be empty).
|
||||
|
@ -341,6 +341,8 @@ protected:
|
|||
void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const;
|
||||
|
||||
Model m_model;
|
||||
DynamicPrintConfig m_full_print_config;
|
||||
PlaceholderParser m_placeholder_parser;
|
||||
|
||||
private:
|
||||
tbb::atomic<CancelStatus> m_cancel_status;
|
||||
|
@ -354,8 +356,6 @@ private:
|
|||
// The mutex will be used to guard the worker thread against entering a stage
|
||||
// while the data influencing the stage is modified.
|
||||
mutable tbb::mutex m_state_mutex;
|
||||
|
||||
PlaceholderParser m_placeholder_parser;
|
||||
};
|
||||
|
||||
template<typename PrintStepEnum, const size_t COUNT>
|
||||
|
|
|
@ -29,6 +29,7 @@ PrintConfigDef::PrintConfigDef()
|
|||
this->init_common_params();
|
||||
assign_printer_technology_to_unknown(this->options, ptAny);
|
||||
this->init_fff_params();
|
||||
this->init_extruder_retract_keys();
|
||||
assign_printer_technology_to_unknown(this->options, ptFFF);
|
||||
this->init_sla_params();
|
||||
assign_printer_technology_to_unknown(this->options, ptSLA);
|
||||
|
@ -2238,6 +2239,48 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
// Declare retract values for filament profile, overriding the printer's extruder profile.
|
||||
for (const char *opt_key : {
|
||||
// floats
|
||||
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel",
|
||||
// bools
|
||||
"retract_layer_change", "wipe",
|
||||
// percents
|
||||
"retract_before_wipe"}) {
|
||||
auto it_opt = options.find(opt_key);
|
||||
assert(it_opt != options.end());
|
||||
def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type);
|
||||
def->label = it_opt->second.label;
|
||||
def->full_label = it_opt->second.full_label;
|
||||
def->tooltip = it_opt->second.tooltip;
|
||||
def->sidetext = it_opt->second.sidetext;
|
||||
def->mode = it_opt->second.mode;
|
||||
switch (def->type) {
|
||||
case coFloats : def->set_default_value(new ConfigOptionFloatsNullable (static_cast<const ConfigOptionFloats* >(it_opt->second.default_value.get())->values)); break;
|
||||
case coPercents : def->set_default_value(new ConfigOptionPercentsNullable(static_cast<const ConfigOptionPercents*>(it_opt->second.default_value.get())->values)); break;
|
||||
case coBools : def->set_default_value(new ConfigOptionBoolsNullable (static_cast<const ConfigOptionBools* >(it_opt->second.default_value.get())->values)); break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintConfigDef::init_extruder_retract_keys()
|
||||
{
|
||||
m_extruder_retract_keys = {
|
||||
"deretract_speed",
|
||||
"retract_before_travel",
|
||||
"retract_before_wipe",
|
||||
"retract_layer_change",
|
||||
"retract_length",
|
||||
"retract_lift",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
"retract_restart_extra",
|
||||
"retract_speed",
|
||||
"wipe"
|
||||
};
|
||||
assert(std::is_sorted(m_extruder_retract_keys.begin(), m_extruder_retract_keys.end()));
|
||||
}
|
||||
|
||||
void PrintConfigDef::init_sla_params()
|
||||
|
@ -2997,7 +3040,7 @@ std::string FullPrintConfig::validate()
|
|||
}
|
||||
case coFloats:
|
||||
case coPercents:
|
||||
for (double v : static_cast<const ConfigOptionFloats*>(opt)->values)
|
||||
for (double v : static_cast<const ConfigOptionVector<double>*>(opt)->values)
|
||||
if (v < optdef->min || v > optdef->max) {
|
||||
out_of_range = true;
|
||||
break;
|
||||
|
@ -3010,7 +3053,7 @@ std::string FullPrintConfig::validate()
|
|||
break;
|
||||
}
|
||||
case coInts:
|
||||
for (int v : static_cast<const ConfigOptionInts*>(opt)->values)
|
||||
for (int v : static_cast<const ConfigOptionVector<int>*>(opt)->values)
|
||||
if (v < optdef->min || v > optdef->max) {
|
||||
out_of_range = true;
|
||||
break;
|
||||
|
|
|
@ -185,10 +185,18 @@ public:
|
|||
|
||||
static void handle_legacy(t_config_option_key &opt_key, std::string &value);
|
||||
|
||||
// Options defining the extruder retract properties. These keys are sorted lexicographically.
|
||||
// The extruder retract keys could be overidden by the same values defined at the Filament level
|
||||
// (then the key is further prefixed with the "filament_" prefix).
|
||||
const std::vector<std::string>& extruder_retract_keys() const { return m_extruder_retract_keys; }
|
||||
|
||||
private:
|
||||
void init_common_params();
|
||||
void init_fff_params();
|
||||
void init_extruder_retract_keys();
|
||||
void init_sla_params();
|
||||
|
||||
std::vector<std::string> m_extruder_retract_keys;
|
||||
};
|
||||
|
||||
// The one and only global definition of SLic3r configuration options.
|
||||
|
|
|
@ -145,14 +145,13 @@ static std::vector<SLAPrintObject::Instance> sla_instances(const ModelObject &mo
|
|||
return instances;
|
||||
}
|
||||
|
||||
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConfig &config_in)
|
||||
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig config)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
check_model_ids_validity(model);
|
||||
#endif /* _DEBUG */
|
||||
|
||||
// Make a copy of the config, normalize it.
|
||||
DynamicPrintConfig config(config_in);
|
||||
// Normalize the config.
|
||||
config.option("sla_print_settings_id", true);
|
||||
config.option("sla_material_settings_id", true);
|
||||
config.option("printer_settings_id", true);
|
||||
|
@ -162,7 +161,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
t_config_option_keys printer_diff = m_printer_config.diff(config);
|
||||
t_config_option_keys material_diff = m_material_config.diff(config);
|
||||
t_config_option_keys object_diff = m_default_object_config.diff(config);
|
||||
t_config_option_keys placeholder_parser_diff = this->placeholder_parser().config_diff(config);
|
||||
t_config_option_keys placeholder_parser_diff = m_placeholder_parser.config_diff(config);
|
||||
|
||||
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
|
||||
unsigned int apply_status = APPLY_STATUS_UNCHANGED;
|
||||
|
@ -187,12 +186,11 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
// only to generate the output file name.
|
||||
if (! placeholder_parser_diff.empty()) {
|
||||
// update_apply_status(this->invalidate_step(slapsRasterize));
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_config(config);
|
||||
m_placeholder_parser.apply_config(config);
|
||||
// Set the profile aliases for the PrintBase::output_filename()
|
||||
pp.set("print_preset", config.option("sla_print_settings_id")->clone());
|
||||
pp.set("material_preset", config.option("sla_material_settings_id")->clone());
|
||||
pp.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||
m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone());
|
||||
m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone());
|
||||
m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||
}
|
||||
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
|
@ -459,6 +457,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
check_model_ids_equal(m_model, model);
|
||||
#endif /* _DEBUG */
|
||||
|
||||
m_full_print_config = std::move(config);
|
||||
return static_cast<ApplyStatus>(apply_status);
|
||||
}
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ public:
|
|||
|
||||
void clear() override;
|
||||
bool empty() const override { return m_objects.empty(); }
|
||||
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
||||
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
||||
void set_task(const TaskParams ¶ms) override;
|
||||
void process() override;
|
||||
void finalize() override;
|
||||
|
|
|
@ -106,6 +106,9 @@ void CopyrightsDialog::fill_entries()
|
|||
"2001-2016 Expat maintainers" , "http://www.libexpat.org/" },
|
||||
{ "AVRDUDE" , "2018 Free Software Foundation, Inc." , "http://savannah.nongnu.org/projects/avrdude" },
|
||||
{ "Shinyprofiler" , "2007-2010 Aidin Abedi" , "http://code.google.com/p/shinyprofiler/" },
|
||||
{ "Real-Time DXT1/DXT5 C compression library"
|
||||
, "Based on original by fabian \"ryg\" giesen v1.04. "
|
||||
"Custom version, modified by Yann Collet" , "https://github.com/Cyan4973/RygsDXTc" },
|
||||
{ "Icons for STL and GCODE files."
|
||||
, "Akira Yasuda" , "http://3dp0.com/icons-for-stl-and-gcode/" }
|
||||
};
|
||||
|
|
|
@ -136,6 +136,8 @@ bool Field::is_matched(const std::string& string, const std::string& pattern)
|
|||
return std::regex_match(string, regex_pattern);
|
||||
}
|
||||
|
||||
static wxString na_value() { return _(L("N/A")); }
|
||||
|
||||
void Field::get_value_by_opt_type(wxString& str)
|
||||
{
|
||||
switch (m_opt.type) {
|
||||
|
@ -165,7 +167,9 @@ void Field::get_value_by_opt_type(wxString& str)
|
|||
val = 0.0;
|
||||
else
|
||||
{
|
||||
if (!str.ToCDouble(&val))
|
||||
if (m_opt.nullable && str == na_value())
|
||||
val = ConfigOptionFloatsNullable::nil_value();
|
||||
else if (!str.ToCDouble(&val))
|
||||
{
|
||||
show_error(m_parent, _(L("Invalid numeric input.")));
|
||||
set_value(double_to_string(val), true);
|
||||
|
@ -256,6 +260,7 @@ void TextCtrl::BUILD() {
|
|||
m_opt.default_value->getFloat() :
|
||||
m_opt.get_default_value<ConfigOptionPercents>()->get_at(m_opt_idx);
|
||||
text_value = double_to_string(val);
|
||||
m_last_meaningful_value = text_value;
|
||||
break;
|
||||
}
|
||||
case coString:
|
||||
|
@ -325,24 +330,7 @@ void TextCtrl::BUILD() {
|
|||
}
|
||||
propagate_value();
|
||||
}), temp->GetId());
|
||||
/*
|
||||
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
if (bChangedValueEvent)
|
||||
#endif //__WXGTK__
|
||||
if(is_defined_input_value())
|
||||
on_change_field();
|
||||
}), temp->GetId());
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// to correct value updating on GTK we should:
|
||||
// call on_change_field() on wxEVT_KEY_UP instead of wxEVT_TEXT
|
||||
// and prevent value updating on wxEVT_KEY_DOWN
|
||||
temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this);
|
||||
temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this);
|
||||
#endif //__WXGTK__
|
||||
*/
|
||||
// select all text using Ctrl+A
|
||||
temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event)
|
||||
{
|
||||
|
@ -355,14 +343,70 @@ void TextCtrl::BUILD() {
|
|||
window = dynamic_cast<wxWindow*>(temp);
|
||||
}
|
||||
|
||||
bool TextCtrl::value_was_changed()
|
||||
{
|
||||
if (m_value.empty())
|
||||
return true;
|
||||
|
||||
boost::any val = m_value;
|
||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||
// update m_value!
|
||||
get_value_by_opt_type(ret_str);
|
||||
|
||||
switch (m_opt.type) {
|
||||
case coInt:
|
||||
return boost::any_cast<int>(m_value) != boost::any_cast<int>(val);
|
||||
case coPercent:
|
||||
case coPercents:
|
||||
case coFloats:
|
||||
case coFloat: {
|
||||
if (m_opt.nullable && std::isnan(boost::any_cast<double>(m_value)) &&
|
||||
std::isnan(boost::any_cast<double>(val)))
|
||||
return false;
|
||||
return boost::any_cast<double>(m_value) != boost::any_cast<double>(val);
|
||||
}
|
||||
case coString:
|
||||
case coStrings:
|
||||
case coFloatOrPercent:
|
||||
return boost::any_cast<std::string>(m_value) != boost::any_cast<std::string>(val);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void TextCtrl::propagate_value()
|
||||
{
|
||||
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
|
||||
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type) && value_was_changed())
|
||||
on_change_field();
|
||||
else
|
||||
on_kill_focus();
|
||||
}
|
||||
|
||||
void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) {
|
||||
m_disable_change_event = !change_event;
|
||||
if (m_opt.nullable) {
|
||||
const bool m_is_na_val = boost::any_cast<wxString>(value) == na_value();
|
||||
if (!m_is_na_val)
|
||||
m_last_meaningful_value = value;
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast<wxString>(value));
|
||||
}
|
||||
else
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value));
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
|
||||
void TextCtrl::set_last_meaningful_value()
|
||||
{
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(m_last_meaningful_value));
|
||||
propagate_value();
|
||||
}
|
||||
|
||||
void TextCtrl::set_na_value()
|
||||
{
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(na_value());
|
||||
propagate_value();
|
||||
}
|
||||
|
||||
boost::any& TextCtrl::get_value()
|
||||
{
|
||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||
|
@ -409,6 +453,8 @@ void CheckBox::BUILD() {
|
|||
m_opt.get_default_value<ConfigOptionBools>()->get_at(m_opt_idx) :
|
||||
false;
|
||||
|
||||
m_last_meaningful_value = static_cast<unsigned char>(check_value);
|
||||
|
||||
// Set Label as a string of at least one space simbol to correct system scaling of a CheckBox
|
||||
auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size);
|
||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
|
@ -416,7 +462,10 @@ void CheckBox::BUILD() {
|
|||
temp->SetValue(check_value);
|
||||
if (m_opt.readonly) temp->Disable();
|
||||
|
||||
temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
|
||||
temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) {
|
||||
m_is_na_val = false;
|
||||
on_change_field();
|
||||
}), temp->GetId());
|
||||
|
||||
temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false"));
|
||||
|
||||
|
@ -424,6 +473,38 @@ void CheckBox::BUILD() {
|
|||
window = dynamic_cast<wxWindow*>(temp);
|
||||
}
|
||||
|
||||
void CheckBox::set_value(const boost::any& value, bool change_event)
|
||||
{
|
||||
m_disable_change_event = !change_event;
|
||||
if (m_opt.nullable) {
|
||||
m_is_na_val = boost::any_cast<unsigned char>(value) == ConfigOptionBoolsNullable::nil_value();
|
||||
if (!m_is_na_val)
|
||||
m_last_meaningful_value = value;
|
||||
dynamic_cast<wxCheckBox*>(window)->SetValue(m_is_na_val ? false : boost::any_cast<unsigned char>(value) != 0);
|
||||
}
|
||||
else
|
||||
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value));
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
|
||||
void CheckBox::set_last_meaningful_value()
|
||||
{
|
||||
if (m_opt.nullable) {
|
||||
m_is_na_val = false;
|
||||
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<unsigned char>(m_last_meaningful_value) != 0);
|
||||
on_change_field();
|
||||
}
|
||||
}
|
||||
|
||||
void CheckBox::set_na_value()
|
||||
{
|
||||
if (m_opt.nullable) {
|
||||
m_is_na_val = true;
|
||||
dynamic_cast<wxCheckBox*>(window)->SetValue(false);
|
||||
on_change_field();
|
||||
}
|
||||
}
|
||||
|
||||
boost::any& CheckBox::get_value()
|
||||
{
|
||||
// boost::any m_value;
|
||||
|
@ -431,7 +512,7 @@ boost::any& CheckBox::get_value()
|
|||
if (m_opt.type == coBool)
|
||||
m_value = static_cast<bool>(value);
|
||||
else
|
||||
m_value = static_cast<unsigned char>(value);
|
||||
m_value = m_is_na_val ? ConfigOptionBoolsNullable::nil_value() : static_cast<unsigned char>(value);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,8 @@ public:
|
|||
/// subclasses should overload with a specific version
|
||||
/// Postcondition: Method does not fire the on_change event.
|
||||
virtual void set_value(const boost::any& value, bool change_event) = 0;
|
||||
virtual void set_last_meaningful_value() {}
|
||||
virtual void set_na_value() {}
|
||||
|
||||
/// Gets a boost::any representing this control.
|
||||
/// subclasses should overload with a specific version
|
||||
|
@ -247,6 +249,8 @@ protected:
|
|||
|
||||
// current value
|
||||
boost::any m_value;
|
||||
// last maeningful value
|
||||
boost::any m_last_meaningful_value;
|
||||
|
||||
int m_em_unit;
|
||||
|
||||
|
@ -277,6 +281,7 @@ public:
|
|||
~TextCtrl() {}
|
||||
|
||||
void BUILD();
|
||||
bool value_was_changed();
|
||||
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||
void propagate_value();
|
||||
wxWindow* window {nullptr};
|
||||
|
@ -286,11 +291,9 @@ public:
|
|||
dynamic_cast<wxTextCtrl*>(window)->SetValue(wxString(value));
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
virtual void set_value(const boost::any& value, bool change_event = false) {
|
||||
m_disable_change_event = !change_event;
|
||||
dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value));
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
virtual void set_value(const boost::any& value, bool change_event = false) override;
|
||||
virtual void set_last_meaningful_value() override;
|
||||
virtual void set_na_value() override;
|
||||
|
||||
boost::any& get_value() override;
|
||||
|
||||
|
@ -303,6 +306,7 @@ public:
|
|||
|
||||
class CheckBox : public Field {
|
||||
using Field::Field;
|
||||
bool m_is_na_val {false};
|
||||
public:
|
||||
CheckBox(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
||||
CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
||||
|
@ -316,11 +320,9 @@ public:
|
|||
dynamic_cast<wxCheckBox*>(window)->SetValue(value);
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
void set_value(const boost::any& value, bool change_event = false) {
|
||||
m_disable_change_event = !change_event;
|
||||
dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value));
|
||||
m_disable_change_event = false;
|
||||
}
|
||||
void set_value(const boost::any& value, bool change_event = false) override;
|
||||
void set_last_meaningful_value() override;
|
||||
void set_na_value() override;
|
||||
boost::any& get_value() override;
|
||||
|
||||
void msw_rescale() override;
|
||||
|
|
|
@ -27,10 +27,13 @@ namespace GUI {
|
|||
|
||||
void GLTexture::Compressor::reset()
|
||||
{
|
||||
// force compression completion, if any
|
||||
m_abort_compressing = true;
|
||||
// wait for compression completion, if any
|
||||
while (m_is_compressing) {}
|
||||
if (m_is_compressing)
|
||||
{
|
||||
// force compression completion, if any
|
||||
m_abort_compressing = true;
|
||||
// wait for compression completion, if any
|
||||
while (m_is_compressing) {}
|
||||
}
|
||||
|
||||
m_levels.clear();
|
||||
}
|
||||
|
@ -42,8 +45,6 @@ void GLTexture::Compressor::add_level(unsigned int w, unsigned int h, const std:
|
|||
|
||||
void GLTexture::Compressor::start_compressing()
|
||||
{
|
||||
m_is_compressing = true;
|
||||
m_abort_compressing = false;
|
||||
std::thread t(&GLTexture::Compressor::compress, this);
|
||||
t.detach();
|
||||
}
|
||||
|
@ -97,6 +98,9 @@ void GLTexture::Compressor::compress()
|
|||
{
|
||||
// reference: https://github.com/Cyan4973/RygsDXTc
|
||||
|
||||
m_is_compressing = true;
|
||||
m_abort_compressing = false;
|
||||
|
||||
for (Level& level : m_levels)
|
||||
{
|
||||
if (m_abort_compressing)
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace GUI {
|
|||
|
||||
public:
|
||||
explicit Compressor(GLTexture& texture) : m_texture(texture), m_is_compressing(false), m_abort_compressing(false) {}
|
||||
~Compressor() { reset(); }
|
||||
|
||||
void reset();
|
||||
|
||||
|
|
|
@ -148,6 +148,13 @@ void config_wizard(int reason)
|
|||
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/)
|
||||
{
|
||||
try{
|
||||
|
||||
if (config.def()->get(opt_key)->type == coBools && config.def()->get(opt_key)->nullable) {
|
||||
ConfigOptionBoolsNullable* vec_new = new ConfigOptionBoolsNullable{ boost::any_cast<unsigned char>(value) };
|
||||
config.option<ConfigOptionBoolsNullable>(opt_key)->set_at(vec_new, opt_index, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (config.def()->get(opt_key)->type) {
|
||||
case coFloatOrPercent:{
|
||||
std::string str = boost::any_cast<std::string>(value);
|
||||
|
|
|
@ -2843,7 +2843,7 @@ void ObjectList::update_selections_on_canvas()
|
|||
else
|
||||
{
|
||||
mode = Selection::Instance;
|
||||
single_selection = false;
|
||||
single_selection &= (obj_idx != selection.get_object_idx());
|
||||
std::vector<unsigned int> idxs = selection.get_volume_idxs_from_object(obj_idx);
|
||||
volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
|
||||
}
|
||||
|
|
|
@ -210,6 +210,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width);
|
||||
auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
|
||||
btn->SetToolTip(wxString::Format(_(L("Toggle %c axis mirroring")), (int)label));
|
||||
btn->SetBitmapDisabled_(m_mirror_bitmap_hidden);
|
||||
|
||||
m_mirror_buttons[axis_idx].first = btn;
|
||||
m_mirror_buttons[axis_idx].second = mbShown;
|
||||
|
@ -286,6 +287,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn, wxBU_EXACTFIT);
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Reset scale")));
|
||||
change_scale_value(0, 100.);
|
||||
change_scale_value(1, 100.);
|
||||
change_scale_value(2, 100.);
|
||||
|
@ -323,7 +325,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
|
||||
selection.synchronize_unselected_volumes();
|
||||
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||
canvas->do_rotate(L("Set Rotation"));
|
||||
canvas->do_rotate(L("Reset Rotation"));
|
||||
|
||||
UpdateAndShow(true);
|
||||
});
|
||||
|
@ -350,6 +352,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
const Geometry::Transformation& instance_trafo = volume->get_instance_transformation();
|
||||
Vec3d diff = m_cache.position - instance_trafo.get_matrix(true).inverse() * Vec3d(0., 0., get_volume_min_z(volume));
|
||||
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Drop to bed")));
|
||||
change_position_value(0, diff.x());
|
||||
change_position_value(1, diff.y());
|
||||
change_position_value(2, diff.z());
|
||||
|
@ -646,13 +649,13 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
|||
wxGetApp().CallAfter([this, new_states]{
|
||||
for (int i=0; i<3; ++i) {
|
||||
if (new_states[i] != m_mirror_buttons[i].second) {
|
||||
const wxBitmap* bmp;
|
||||
const ScalableBitmap* bmp;
|
||||
switch (new_states[i]) {
|
||||
case mbHidden : bmp = &m_mirror_bitmap_hidden.bmp(); m_mirror_buttons[i].first->Enable(false); break;
|
||||
case mbShown : bmp = &m_mirror_bitmap_off.bmp(); m_mirror_buttons[i].first->Enable(true); break;
|
||||
case mbActive : bmp = &m_mirror_bitmap_on.bmp(); m_mirror_buttons[i].first->Enable(true); break;
|
||||
case mbHidden : bmp = &m_mirror_bitmap_hidden; m_mirror_buttons[i].first->Enable(false); break;
|
||||
case mbShown : bmp = &m_mirror_bitmap_off; m_mirror_buttons[i].first->Enable(true); break;
|
||||
case mbActive : bmp = &m_mirror_bitmap_on; m_mirror_buttons[i].first->Enable(true); break;
|
||||
}
|
||||
m_mirror_buttons[i].first->SetBitmap(*bmp);
|
||||
m_mirror_buttons[i].first->SetBitmap_(*bmp);
|
||||
m_mirror_buttons[i].second = new_states[i];
|
||||
}
|
||||
}
|
||||
|
@ -925,6 +928,9 @@ void ObjectManipulation::msw_rescale()
|
|||
m_reset_rotation_button->msw_rescale();
|
||||
m_drop_to_bed_button->msw_rescale();
|
||||
|
||||
for (int id = 0; id < 3; ++id)
|
||||
m_mirror_buttons[id].first->msw_rescale();
|
||||
|
||||
get_og()->msw_rescale();
|
||||
}
|
||||
|
||||
|
|
|
@ -900,6 +900,10 @@ RENDER_AGAIN:
|
|||
ImGui::SameLine(diameter_slider_left);
|
||||
ImGui::PushItemWidth(window_width - diameter_slider_left);
|
||||
|
||||
// Following is a nasty way to:
|
||||
// - save the initial value of the slider before one starts messing with it
|
||||
// - keep updating the head radius during sliding so it is continuosly refreshed in 3D scene
|
||||
// - take correct undo/redo snapshot after the user is done with moving the slider
|
||||
float initial_value = m_new_point_head_diameter;
|
||||
ImGui::SliderFloat("", &m_new_point_head_diameter, 0.1f, diameter_upper_cap, "%.1f");
|
||||
if (ImGui::IsItemClicked()) {
|
||||
|
@ -960,20 +964,35 @@ RENDER_AGAIN:
|
|||
float density = static_cast<const ConfigOptionInt*>(opts[0])->value;
|
||||
float minimal_point_distance = static_cast<const ConfigOptionFloat*>(opts[1])->value;
|
||||
|
||||
bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
|
||||
if (value_changed)
|
||||
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
|
||||
ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm");
|
||||
bool slider_clicked = ImGui::IsItemClicked(); // someone clicked the slider
|
||||
bool slider_edited = ImGui::IsItemEdited(); // someone is dragging the slider
|
||||
bool slider_released = ImGui::IsItemDeactivatedAfterEdit(); // someone has just released the slider
|
||||
|
||||
m_imgui->text(m_desc.at("points_density"));
|
||||
ImGui::SameLine(settings_sliders_left);
|
||||
|
||||
if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) {
|
||||
value_changed = true;
|
||||
ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%");
|
||||
slider_clicked |= ImGui::IsItemClicked();
|
||||
slider_edited |= ImGui::IsItemEdited();
|
||||
slider_released |= ImGui::IsItemDeactivatedAfterEdit();
|
||||
|
||||
if (slider_clicked) { // stash the values of the settings so we know what to revert to after undo
|
||||
m_minimal_point_distance_stash = minimal_point_distance;
|
||||
m_density_stash = density;
|
||||
}
|
||||
if (slider_edited) {
|
||||
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
|
||||
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
|
||||
}
|
||||
|
||||
if (value_changed) // Update side panel
|
||||
if (slider_released) {
|
||||
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = m_minimal_point_distance_stash;
|
||||
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)m_density_stash;
|
||||
wxGetApp().plater()->take_snapshot(_(L("Support parameter change")));
|
||||
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
|
||||
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
|
||||
wxGetApp().obj_list()->update_and_show_object_settings_item();
|
||||
}
|
||||
|
||||
bool generate = m_imgui->button(m_desc.at("auto_generate"));
|
||||
|
||||
|
|
|
@ -107,7 +107,8 @@ private:
|
|||
float m_new_point_head_diameter; // Size of a new point.
|
||||
CacheEntry m_point_before_drag; // undo/redo - so we know what state was edited
|
||||
float m_old_point_head_diameter = 0.; // the same
|
||||
float m_minimal_point_distance = 20.f;
|
||||
float m_minimal_point_distance_stash = 0.f; // and again
|
||||
float m_density_stash = 0.f; // and again
|
||||
mutable std::vector<CacheEntry> m_editing_cache; // a support point and whether it is currently selected
|
||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||
|
||||
|
|
|
@ -108,11 +108,15 @@ public:
|
|||
ar(m_current);
|
||||
|
||||
GLGizmoBase* curr = get_current();
|
||||
if (curr != nullptr)
|
||||
{
|
||||
curr->set_state(GLGizmoBase::On);
|
||||
curr->load(ar);
|
||||
}
|
||||
for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) {
|
||||
GLGizmoBase* gizmo = it->second;
|
||||
if (gizmo != nullptr) {
|
||||
gizmo->set_hover_id(-1);
|
||||
gizmo->set_state((it->second == curr) ? GLGizmoBase::On : GLGizmoBase::Off);
|
||||
if (gizmo == curr)
|
||||
gizmo->load(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Archive>
|
||||
|
|
|
@ -411,6 +411,7 @@ void MainFrame::init_menubar()
|
|||
}, wxID_FILE1, wxID_FILE9);
|
||||
|
||||
std::vector<std::string> recent_projects = wxGetApp().app_config->get_recent_projects();
|
||||
std::reverse(recent_projects.begin(), recent_projects.end());
|
||||
for (const std::string& project : recent_projects)
|
||||
{
|
||||
m_recent_projects.AddFileToHistory(from_u8(project));
|
||||
|
|
|
@ -202,7 +202,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
|||
// so we need a horizontal sizer to arrange these things
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
|
||||
sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT, 7);
|
||||
sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7);
|
||||
sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
|
||||
}
|
||||
}
|
||||
|
@ -372,30 +372,10 @@ void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const b
|
|||
|
||||
auto option = m_options.at(opt_id).opt;
|
||||
|
||||
// get value
|
||||
//! auto field_value = get_value(opt_id);
|
||||
if (option.gui_flags.compare("serialized")==0) {
|
||||
if (opt_index != -1) {
|
||||
// die "Can't set serialized option indexed value" ;
|
||||
}
|
||||
change_opt_value(*m_config, opt_key, value);
|
||||
}
|
||||
else {
|
||||
if (opt_index == -1) {
|
||||
// change_opt_value(*m_config, opt_key, field_value);
|
||||
//!? why field_value?? in this case changed value will be lose! No?
|
||||
change_opt_value(*m_config, opt_key, value);
|
||||
}
|
||||
else {
|
||||
change_opt_value(*m_config, opt_key, value, opt_index);
|
||||
// auto value = m_config->get($opt_key);
|
||||
// $value->[$opt_index] = $field_value;
|
||||
// $self->config->set($opt_key, $value);
|
||||
}
|
||||
}
|
||||
change_opt_value(*m_config, opt_key, value, opt_index == -1 ? 0 : opt_index);
|
||||
}
|
||||
|
||||
OptionsGroup::on_change_OG(opt_id, value); //!? Why doing this
|
||||
OptionsGroup::on_change_OG(opt_id, value);
|
||||
}
|
||||
|
||||
void ConfigOptionsGroup::back_to_initial_value(const std::string& opt_key)
|
||||
|
@ -578,6 +558,34 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
boost::any ret;
|
||||
wxString text_value = wxString("");
|
||||
const ConfigOptionDef* opt = config.def()->get(opt_key);
|
||||
|
||||
if (opt->nullable)
|
||||
{
|
||||
switch (opt->type)
|
||||
{
|
||||
case coPercents:
|
||||
case coFloats: {
|
||||
if (config.option(opt_key)->is_nil())
|
||||
ret = _(L("N/A"));
|
||||
else {
|
||||
double val = opt->type == coFloats ?
|
||||
config.option<ConfigOptionFloatsNullable>(opt_key)->get_at(idx) :
|
||||
config.option<ConfigOptionPercentsNullable>(opt_key)->get_at(idx);
|
||||
ret = double_to_string(val); }
|
||||
}
|
||||
break;
|
||||
case coBools:
|
||||
ret = config.option<ConfigOptionBoolsNullable>(opt_key)->values[idx];
|
||||
break;
|
||||
case coInts:
|
||||
ret = config.option<ConfigOptionIntsNullable>(opt_key)->get_at(idx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case coFloatOrPercent:{
|
||||
const auto &value = *config.option<ConfigOptionFloatOrPercent>(opt_key);
|
||||
|
|
|
@ -252,6 +252,9 @@ public:
|
|||
Option option = get_option(title, idx);
|
||||
return OptionsGroup::create_single_option_line(option);
|
||||
}
|
||||
Line create_single_option_line(const Option& option) const {
|
||||
return OptionsGroup::create_single_option_line(option);
|
||||
}
|
||||
void append_single_option_line(const Option& option) {
|
||||
OptionsGroup::append_single_option_line(option);
|
||||
}
|
||||
|
|
|
@ -4406,6 +4406,12 @@ void Plater::reslice()
|
|||
{
|
||||
// Stop arrange and (or) optimize rotation tasks.
|
||||
this->stop_jobs();
|
||||
|
||||
if (printer_technology() == ptSLA) {
|
||||
for (auto& object : model().objects)
|
||||
if (object->sla_points_status == sla::PointsStatus::NoPoints)
|
||||
object->sla_points_status = sla::PointsStatus::Generating;
|
||||
}
|
||||
|
||||
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
|
||||
// bitmask of UpdateBackgroundProcessReturnState
|
||||
|
|
|
@ -400,6 +400,10 @@ const std::vector<std::string>& Preset::filament_options()
|
|||
"temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed",
|
||||
"max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed",
|
||||
"start_filament_gcode", "end_filament_gcode",
|
||||
// Retract overrides
|
||||
"filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel",
|
||||
"filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe",
|
||||
// Profile compatibility
|
||||
"compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits"
|
||||
};
|
||||
return s_opts;
|
||||
|
|
|
@ -72,6 +72,8 @@ PresetBundle::PresetBundle() :
|
|||
this->filaments.default_preset().config.option<ConfigOptionStrings>("filament_settings_id", true)->values = { "" };
|
||||
this->filaments.default_preset().compatible_printers_condition();
|
||||
this->filaments.default_preset().inherits();
|
||||
// Set all the nullable values to nils.
|
||||
this->filaments.default_preset().config.null_nullables();
|
||||
|
||||
this->sla_materials.default_preset().config.optptr("sla_material_settings_id", true);
|
||||
this->sla_materials.default_preset().compatible_printers_condition();
|
||||
|
|
|
@ -1497,6 +1497,105 @@ void TabPrint::OnActivate()
|
|||
Tab::OnActivate();
|
||||
}
|
||||
|
||||
void TabFilament::add_filament_overrides_page()
|
||||
{
|
||||
PageShp page = add_options_page(_(L("Filament Overrides")), "wrench");
|
||||
ConfigOptionsGroupShp optgroup = page->new_optgroup(_(L("Retraction")));
|
||||
|
||||
auto append_single_option_line = [optgroup, this](const std::string& opt_key, int opt_index)
|
||||
{
|
||||
Line line {"",""};
|
||||
if (opt_key == "filament_retract_lift_above" || opt_key == "filament_retract_lift_below") {
|
||||
Option opt = optgroup->get_option(opt_key);
|
||||
opt.opt.label = opt.opt.full_label;
|
||||
line = optgroup->create_single_option_line(opt);
|
||||
}
|
||||
else
|
||||
line = optgroup->create_single_option_line(optgroup->get_option(opt_key));
|
||||
|
||||
line.near_label_widget = [this, optgroup, opt_key, opt_index](wxWindow* parent) {
|
||||
wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, "");
|
||||
|
||||
check_box->Bind(wxEVT_CHECKBOX, [this, optgroup, opt_key, opt_index](wxCommandEvent& evt) {
|
||||
const bool is_checked = evt.IsChecked();
|
||||
Field* field = optgroup->get_fieldc(opt_key, opt_index);
|
||||
if (field != nullptr) {
|
||||
field->toggle(is_checked);
|
||||
if (is_checked)
|
||||
field->set_last_meaningful_value();
|
||||
else
|
||||
field->set_na_value();
|
||||
}
|
||||
}, check_box->GetId());
|
||||
|
||||
m_overrides_options[opt_key] = check_box;
|
||||
return check_box;
|
||||
};
|
||||
|
||||
optgroup->append_line(line);
|
||||
};
|
||||
|
||||
const int extruder_idx = 0; // #ys_FIXME
|
||||
|
||||
for (const std::string opt_key : { "filament_retract_length",
|
||||
"filament_retract_lift",
|
||||
"filament_retract_lift_above",
|
||||
"filament_retract_lift_below",
|
||||
"filament_retract_speed",
|
||||
"filament_deretract_speed",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_before_travel",
|
||||
"filament_retract_layer_change",
|
||||
"filament_wipe",
|
||||
"filament_retract_before_wipe"
|
||||
})
|
||||
append_single_option_line(opt_key, extruder_idx);
|
||||
}
|
||||
|
||||
void TabFilament::update_filament_overrides_page()
|
||||
{
|
||||
const auto page_it = std::find_if(m_pages.begin(), m_pages.end(), [](const PageShp page) {return page->title() == _(L("Filament Overrides")); });
|
||||
if (page_it == m_pages.end())
|
||||
return;
|
||||
PageShp page = *page_it;
|
||||
|
||||
const auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) {return og->title == _(L("Retraction")); });
|
||||
if (og_it == page->m_optgroups.end())
|
||||
return;
|
||||
ConfigOptionsGroupShp optgroup = *og_it;
|
||||
|
||||
std::vector<std::string> opt_keys = { "filament_retract_length",
|
||||
"filament_retract_lift",
|
||||
"filament_retract_lift_above",
|
||||
"filament_retract_lift_below",
|
||||
"filament_retract_speed",
|
||||
"filament_deretract_speed",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_before_travel",
|
||||
"filament_retract_layer_change",
|
||||
"filament_wipe",
|
||||
"filament_retract_before_wipe"
|
||||
};
|
||||
|
||||
const int extruder_idx = 0; // #ys_FIXME
|
||||
|
||||
const bool have_retract_length = m_config->option("filament_retract_length")->is_nil() ||
|
||||
m_config->opt_float("filament_retract_length", extruder_idx) > 0;
|
||||
|
||||
for (const std::string& opt_key : opt_keys)
|
||||
{
|
||||
bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length;
|
||||
m_overrides_options[opt_key]->Enable(is_checked);
|
||||
|
||||
is_checked &= !m_config->option(opt_key)->is_nil();
|
||||
m_overrides_options[opt_key]->SetValue(is_checked);
|
||||
|
||||
Field* field = optgroup->get_fieldc(opt_key, extruder_idx);
|
||||
if (field != nullptr)
|
||||
field->toggle(is_checked);
|
||||
}
|
||||
}
|
||||
|
||||
void TabFilament::build()
|
||||
{
|
||||
m_presets = &m_preset_bundle->filaments;
|
||||
|
@ -1594,10 +1693,14 @@ void TabFilament::build()
|
|||
};
|
||||
optgroup->append_line(line);
|
||||
|
||||
|
||||
add_filament_overrides_page();
|
||||
|
||||
|
||||
const int gcode_field_height = 15; // 150
|
||||
const int notes_field_height = 25; // 250
|
||||
|
||||
page = add_options_page(_(L("Custom G-code")), "cog");
|
||||
page = add_options_page(_(L("Custom G-code")), "cog");
|
||||
optgroup = page->new_optgroup(_(L("Start G-code")), 0);
|
||||
Option option = optgroup->get_option("start_filament_gcode");
|
||||
option.opt.full_width = true;
|
||||
|
@ -1661,7 +1764,7 @@ void TabFilament::update()
|
|||
return; // ys_FIXME
|
||||
|
||||
m_update_cnt++;
|
||||
// Freeze();
|
||||
|
||||
wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
|
||||
m_cooling_description_line->SetText(text);
|
||||
text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
|
||||
|
@ -1676,7 +1779,9 @@ void TabFilament::update()
|
|||
|
||||
for (auto el : { "min_fan_speed", "disable_fan_first_layers" })
|
||||
get_field(el)->toggle(fan_always_on);
|
||||
// Thaw();
|
||||
|
||||
update_filament_overrides_page();
|
||||
|
||||
m_update_cnt--;
|
||||
|
||||
if (m_update_cnt == 0)
|
||||
|
|
|
@ -337,6 +337,11 @@ class TabFilament : public Tab
|
|||
{
|
||||
ogStaticText* m_volumetric_speed_description_line;
|
||||
ogStaticText* m_cooling_description_line;
|
||||
|
||||
void add_filament_overrides_page();
|
||||
void update_filament_overrides_page();
|
||||
|
||||
std::map<std::string, wxCheckBox*> m_overrides_options;
|
||||
public:
|
||||
TabFilament(wxNotebook* parent) :
|
||||
// Tab(parent, _(L("Filament Settings")), L("filament")) {}
|
||||
|
|
|
@ -513,6 +513,15 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
|||
init_container();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool ObjectDataViewModelNode::valid()
|
||||
{
|
||||
// Verify that the object was not deleted yet.
|
||||
assert(m_idx >= -1);
|
||||
return m_idx >= -1;
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
|
||||
void ObjectDataViewModelNode::set_action_icon()
|
||||
{
|
||||
m_action_icon_name = m_type & itObject ? "advanced_plus" :
|
||||
|
@ -1457,6 +1466,7 @@ wxDataViewItem ObjectDataViewModel::GetParent(const wxDataViewItem &item) const
|
|||
return wxDataViewItem(0);
|
||||
|
||||
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
|
||||
assert(node != nullptr && node->valid());
|
||||
|
||||
// objects nodes has no parent too
|
||||
if (node->m_type == itObject)
|
||||
|
@ -2783,21 +2793,20 @@ LockButton::LockButton( wxWindow *parent,
|
|||
const wxSize& size /*= wxDefaultSize*/):
|
||||
wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER)
|
||||
{
|
||||
m_bmp_lock_on = ScalableBitmap(this, "one_layer_lock_on.png");
|
||||
m_bmp_lock_off = ScalableBitmap(this, "one_layer_lock_off.png");
|
||||
m_bmp_unlock_on = ScalableBitmap(this, "one_layer_unlock_on.png");
|
||||
m_bmp_unlock_off = ScalableBitmap(this, "one_layer_unlock_off.png");
|
||||
m_bmp_lock_closed = ScalableBitmap(this, "lock_closed");
|
||||
m_bmp_lock_closed_f = ScalableBitmap(this, "lock_closed_f");
|
||||
m_bmp_lock_open = ScalableBitmap(this, "lock_open");
|
||||
m_bmp_lock_open_f = ScalableBitmap(this, "lock_open_f");
|
||||
|
||||
#ifdef __WXMSW__
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif // __WXMSW__
|
||||
SetBitmap(m_bmp_unlock_on.bmp());
|
||||
SetBitmapDisabled(m_bmp_lock_on.bmp());
|
||||
SetBitmap(m_bmp_lock_open.bmp());
|
||||
SetBitmapDisabled(m_bmp_lock_open.bmp());
|
||||
SetBitmapHover(m_bmp_lock_closed_f.bmp());
|
||||
|
||||
//button events
|
||||
Bind(wxEVT_BUTTON, &LockButton::OnButton, this);
|
||||
Bind(wxEVT_ENTER_WINDOW, &LockButton::OnEnterBtn, this);
|
||||
Bind(wxEVT_LEAVE_WINDOW, &LockButton::OnLeaveBtn, this);
|
||||
Bind(wxEVT_BUTTON, &LockButton::OnButton, this);
|
||||
}
|
||||
|
||||
void LockButton::OnButton(wxCommandEvent& event)
|
||||
|
@ -2806,7 +2815,7 @@ void LockButton::OnButton(wxCommandEvent& event)
|
|||
return;
|
||||
|
||||
m_is_pushed = !m_is_pushed;
|
||||
enter_button(true);
|
||||
update_button_bitmaps();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
@ -2814,23 +2823,21 @@ void LockButton::OnButton(wxCommandEvent& event)
|
|||
void LockButton::SetLock(bool lock)
|
||||
{
|
||||
m_is_pushed = lock;
|
||||
enter_button(true);
|
||||
update_button_bitmaps();
|
||||
}
|
||||
|
||||
void LockButton::msw_rescale()
|
||||
{
|
||||
m_bmp_lock_on .msw_rescale();
|
||||
m_bmp_lock_off .msw_rescale();
|
||||
m_bmp_unlock_on .msw_rescale();
|
||||
m_bmp_unlock_off.msw_rescale();
|
||||
m_bmp_lock_closed.msw_rescale();
|
||||
m_bmp_lock_closed_f.msw_rescale();
|
||||
m_bmp_lock_open.msw_rescale();
|
||||
m_bmp_lock_open_f.msw_rescale();
|
||||
}
|
||||
|
||||
void LockButton::enter_button(const bool enter)
|
||||
void LockButton::update_button_bitmaps()
|
||||
{
|
||||
const wxBitmap& icon = m_is_pushed ?
|
||||
enter ? m_bmp_lock_off.bmp() : m_bmp_lock_on.bmp() :
|
||||
enter ? m_bmp_unlock_off.bmp() : m_bmp_unlock_on.bmp();
|
||||
SetBitmap(icon);
|
||||
SetBitmap(m_is_pushed ? m_bmp_lock_closed.bmp() : m_bmp_lock_open.bmp());
|
||||
SetBitmapHover(m_is_pushed ? m_bmp_lock_closed_f.bmp() : m_bmp_lock_open_f.bmp());
|
||||
|
||||
Refresh();
|
||||
Update();
|
||||
|
@ -2999,6 +3006,13 @@ ScalableButton::ScalableButton( wxWindow * parent,
|
|||
#endif // __WXMSW__
|
||||
|
||||
SetBitmap(create_scaled_bitmap(parent, icon_name));
|
||||
|
||||
if (size != wxDefaultSize)
|
||||
{
|
||||
const int em = em_unit(parent);
|
||||
m_width = size.x/em;
|
||||
m_height= size.y/em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3025,11 +3039,24 @@ void ScalableButton::SetBitmap_(const ScalableBitmap& bmp)
|
|||
m_current_icon_name = bmp.name();
|
||||
}
|
||||
|
||||
void ScalableButton::SetBitmapDisabled_(const ScalableBitmap& bmp)
|
||||
{
|
||||
SetBitmapDisabled(bmp.bmp());
|
||||
m_disabled_icon_name = bmp.name();
|
||||
}
|
||||
|
||||
void ScalableButton::msw_rescale()
|
||||
{
|
||||
const wxBitmap bmp = create_scaled_bitmap(m_parent, m_current_icon_name);
|
||||
SetBitmap(create_scaled_bitmap(m_parent, m_current_icon_name));
|
||||
if (!m_disabled_icon_name.empty())
|
||||
SetBitmapDisabled(create_scaled_bitmap(m_parent, m_disabled_icon_name));
|
||||
|
||||
SetBitmap(bmp);
|
||||
if (m_width > 0 || m_height>0)
|
||||
{
|
||||
const int em = em_unit(m_parent);
|
||||
wxSize size(m_width * em, m_height * em);
|
||||
SetMinSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ DECLARE_VARIANT_OBJECT(DataViewBitmapText)
|
|||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
|
||||
// ObjectDataViewModelNode: a node inside ObjectDataViewModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
enum ItemType {
|
||||
|
@ -259,6 +259,10 @@ public:
|
|||
ObjectDataViewModelNode *child = m_children[i];
|
||||
delete child;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// Indicate that the object was deleted.
|
||||
m_idx = -2;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
|
||||
void init_container();
|
||||
|
@ -269,6 +273,7 @@ public:
|
|||
|
||||
ObjectDataViewModelNode* GetParent()
|
||||
{
|
||||
assert(m_parent == nullptr || m_parent->valid());
|
||||
return m_parent;
|
||||
}
|
||||
MyObjectTreeModelNodePtrArray& GetChildren()
|
||||
|
@ -357,6 +362,11 @@ public:
|
|||
bool update_settings_digest(const std::vector<std::string>& categories);
|
||||
int volume_type() const { return int(m_volume_type); }
|
||||
void msw_rescale();
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool valid();
|
||||
#endif /* NDEBUG */
|
||||
|
||||
private:
|
||||
friend class ObjectDataViewModel;
|
||||
};
|
||||
|
@ -859,8 +869,6 @@ public:
|
|||
~LockButton() {}
|
||||
|
||||
void OnButton(wxCommandEvent& event);
|
||||
void OnEnterBtn(wxMouseEvent& event) { enter_button(true); event.Skip(); }
|
||||
void OnLeaveBtn(wxMouseEvent& event) { enter_button(false); event.Skip(); }
|
||||
|
||||
bool IsLocked() const { return m_is_pushed; }
|
||||
void SetLock(bool lock);
|
||||
|
@ -872,16 +880,16 @@ public:
|
|||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
void enter_button(const bool enter);
|
||||
void update_button_bitmaps();
|
||||
|
||||
private:
|
||||
bool m_is_pushed = false;
|
||||
bool m_disabled = false;
|
||||
|
||||
ScalableBitmap m_bmp_lock_on;
|
||||
ScalableBitmap m_bmp_lock_off;
|
||||
ScalableBitmap m_bmp_unlock_on;
|
||||
ScalableBitmap m_bmp_unlock_off;
|
||||
ScalableBitmap m_bmp_lock_closed;
|
||||
ScalableBitmap m_bmp_lock_closed_f;
|
||||
ScalableBitmap m_bmp_lock_open;
|
||||
ScalableBitmap m_bmp_lock_open_f;
|
||||
};
|
||||
|
||||
|
||||
|
@ -912,12 +920,16 @@ public:
|
|||
~ScalableButton() {}
|
||||
|
||||
void SetBitmap_(const ScalableBitmap& bmp);
|
||||
void SetBitmapDisabled_(const ScalableBitmap &bmp);
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
private:
|
||||
wxWindow* m_parent;
|
||||
std::string m_current_icon_name = "";
|
||||
std::string m_disabled_icon_name = "";
|
||||
int m_width {-1}; // should be multiplied to em_unit
|
||||
int m_height{-1}; // should be multiplied to em_unit
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
set(SLIC3R_APP_NAME "PrusaSlicer")
|
||||
set(SLIC3R_APP_KEY "PrusaSlicer")
|
||||
set(SLIC3R_VERSION "2.0.0")
|
||||
set(SLIC3R_VERSION "2.1.0-alpha0")
|
||||
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
|
||||
set(SLIC3R_RC_VERSION "2,0,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.0.0.0")
|
||||
set(SLIC3R_RC_VERSION "2,1,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.1.0.0")
|
||||
|
|
|
@ -75,7 +75,7 @@ _constant()
|
|||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = const_cast<GCodeConfig*>(static_cast<const GCodeConfig*>(&THIS->config())); %};
|
||||
Ref<PlaceholderParser> placeholder_parser()
|
||||
%code%{ RETVAL = &THIS->placeholder_parser(); %};
|
||||
%code%{ RETVAL = const_cast<PlaceholderParser*>(&THIS->placeholder_parser()); %};
|
||||
Ref<ExtrusionEntityCollection> skirt()
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->skirt()); %};
|
||||
Ref<ExtrusionEntityCollection> brim()
|
||||
|
|