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

This commit is contained in:
YuSanka 2019-08-01 15:15:18 +02:00
commit 885da35544
45 changed files with 1533 additions and 619 deletions

View file

@ -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

View file

@ -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

View 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

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="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

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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
}

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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";

View file

@ -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;
};
}

View file

@ -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 &region_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;

View file

@ -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 &region_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();

View file

@ -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>

View file

@ -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;

View file

@ -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.

View file

@ -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);
}

View file

@ -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 &params) override;
void process() override;
void finalize() override;

View file

@ -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/" }
};

View file

@ -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;
}

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -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);

View file

@ -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());
}

View file

@ -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();
}

View file

@ -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"));

View file

@ -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

View file

@ -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>

View file

@ -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));

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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)

View file

@ -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")) {}

View file

@ -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);
}
}

View file

@ -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
};

View file

@ -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")

View file

@ -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()