Merge some BS1.7 changes:

Boolean operation feature
This commit is contained in:
SoftFever 2023-08-08 22:13:52 +08:00
parent 9e73dfeb5d
commit da05ae02da
73 changed files with 2496 additions and 481 deletions

View file

@ -0,0 +1,4 @@
<svg width="162" height="162" viewBox="0 0 162 162" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="81" cy="81" r="81" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M161.375 70.875C161.789 74.1919 162 77.5713 162 81H151.875V70.875H161.375ZM156.113 50.625C157.438 53.8989 158.555 57.2793 159.449 60.75H151.875V50.625H156.113ZM151.875 41.7559V50.625H141.75V40.5H151.164C151.406 40.9165 151.641 41.335 151.875 41.7559ZM101.25 2.55176C104.719 3.44482 108.102 4.56299 111.375 5.88818V10.125H101.25V2.55176ZM60.75 2.55176C64.0469 1.70264 67.4297 1.05615 70.875 0.626465V10.125H60.75V2.55176ZM0.625 70.875C1.05469 67.4282 1.70312 64.0483 2.55078 60.75H10.125V70.875H0.625ZM0.625 91.125C0.210938 87.8081 0 84.4287 0 81H10.125V91.125H0.625ZM5.88672 111.375C4.5625 108.101 3.44531 104.721 2.55078 101.25H10.125V111.375H5.88672ZM10.125 120.244V111.375H20.25V121.5H10.8359C10.5938 121.083 10.3594 120.665 10.125 120.244ZM60.75 159.448C57.2812 158.555 53.8984 157.437 50.625 156.112V151.875H60.75V159.448ZM101.25 159.448C97.9531 160.297 94.5703 160.944 91.125 161.374V151.875H101.25V159.448ZM161.375 91.125C160.945 94.5718 160.297 97.9517 159.449 101.25H151.875V91.125H161.375ZM141.75 91.125V81H151.875V91.125H141.75ZM141.75 101.25V91.125H131.625V81H141.75V70.875H151.875V60.75H141.75V50.625H131.625V40.5H141.75V30.375H144.234C143.43 29.3711 142.602 28.3862 141.75 27.4224V30.375H131.625V20.25H134.578C133.613 19.3989 132.629 18.5708 131.625 17.7661V20.25H121.5V10.8364C121.082 10.5957 120.668 10.3584 120.246 10.125H111.375V20.25H101.25V10.125H91.125V0.626465C87.8086 0.212891 84.4297 0 81 0V10.125H70.875V20.25H60.75V10.125H50.625V5.88818C47.5703 7.12402 44.6094 8.54053 41.7539 10.125H50.625V20.25H40.5V10.8364C36.9453 12.8926 33.5625 15.2114 30.375 17.7661V20.25H27.4219C24.8828 22.4893 22.4883 24.8853 20.25 27.4224V30.375H17.7656C15.2109 33.5615 12.8906 36.9453 10.8359 40.5H20.25V50.625H10.125V41.7559C8.53906 44.6108 7.12109 47.5718 5.88672 50.625H10.125V60.75H20.25V70.875H10.125V81H20.25V91.125H10.125V101.25H20.25V111.375H30.375V121.5H20.25V131.625H17.7656C18.5703 132.629 19.3984 133.614 20.25 134.578V131.625H30.375V141.75H27.4219C28.3867 142.601 29.3711 143.429 30.375 144.234V141.75H40.5V151.164C40.918 151.404 41.332 151.642 41.7539 151.875H50.625V141.75H60.75V151.875H70.875V161.374C74.1914 161.787 77.5703 162 81 162V151.875H91.125V141.75H101.25V151.875H111.375V156.112C114.43 154.876 117.391 153.459 120.246 151.875H111.375V141.75H121.5V151.164C125.055 149.107 128.438 146.789 131.625 144.234V141.75H134.578C137.117 139.511 139.512 137.115 141.75 134.578V131.625H144.234C146.789 128.438 149.109 125.055 151.164 121.5H141.75V111.375H151.875V120.244C153.461 117.389 154.879 114.428 156.113 111.375H151.875V101.25H141.75ZM131.625 101.25H141.75V111.375H131.625V101.25ZM121.5 101.25H131.625V91.125H121.5V81H131.625V70.875H141.75V60.75H131.625V50.625H121.5V40.5H131.625V30.375H121.5V20.25H111.375V30.375H101.25V20.25H91.125V10.125H81V20.25H70.875V30.375H60.75V20.25H50.625V30.375H40.5V20.25H30.375V30.375H20.25V40.5H30.375V50.625H20.25V60.75H30.375V70.875H20.25V81H30.375V91.125H20.25V101.25H30.375V111.375H40.5V121.5H30.375V131.625H40.5V141.75H50.625V131.625H60.75V141.75H70.875V151.875H81V141.75H91.125V131.625H101.25V141.75H111.375V131.625H121.5V141.75H131.625V131.625H141.75V121.5H131.625V111.375H121.5V101.25ZM111.375 101.25H121.5V91.125H111.375V81H121.5V70.875H131.625V60.75H121.5V50.625H111.375V40.5H121.5V30.375H111.375V40.5H101.25V30.375H91.125V20.25H81V30.375H70.875V40.5H60.75V30.375H50.625V40.5H40.5V30.375H30.375V40.5H40.5V50.625H30.375V60.75H40.5V70.875H30.375V81H40.5V91.125H30.375V101.25H40.5V111.375H50.625V121.5H40.5V131.625H50.625V121.5H60.75V131.625H70.875V141.75H81V131.625H91.125V121.5H101.25V131.625H111.375V121.5H121.5V131.625H131.625V121.5H121.5V111.375H111.375V101.25ZM101.25 101.25H111.375V91.125H101.25V81H111.375V70.875H121.5V60.75H111.375V50.625H101.25V40.5H91.125V30.375H81V40.5H70.875V50.625H60.75V40.5H50.625V50.625H40.5V60.75H50.625V70.875H40.5V81H50.625V91.125H40.5V101.25H50.625V111.375H60.75V121.5H70.875V131.625H81V121.5H91.125V111.375H101.25V121.5H111.375V111.375H101.25V101.25ZM91.125 101.25H101.25V91.125H91.125V81H101.25V70.875H111.375V60.75H101.25V50.625H91.125V40.5H81V50.625H70.875V60.75H60.75V50.625H50.625V60.75H60.75V70.875H50.625V81H60.75V91.125H50.625V101.25H60.75V111.375H70.875V121.5H81V111.375H91.125V101.25ZM81 101.25H91.125V91.125H81V81H91.125V70.875H101.25V60.75H91.125V50.625H81V60.75H70.875V70.875H60.75V81H70.875V91.125H60.75V101.25H70.875V111.375H81V101.25ZM81 101.25H70.875V91.125H81V101.25ZM81 70.875H91.125V60.75H81V70.875ZM81 70.875H70.875V81H81V70.875Z" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,3 @@
<svg width="11" height="8" viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.25391 3.68839L4.3354 6.76988C4.44084 6.87532 4.6118 6.87532 4.71724 6.76988L10.1868 1.30029" stroke="white" stroke-width="1.08" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 266 B

View file

@ -0,0 +1,3 @@
<svg width="11" height="8" viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.25391 3.68839L4.3354 6.76988C4.44084 6.87532 4.6118 6.87532 4.71724 6.76988L10.1868 1.30029" stroke="#262E30" stroke-width="1.08" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 268 B

View file

@ -0,0 +1,8 @@
<svg width="95" height="92" xmlns="http://www.w3.org/2000/svg" data-name="图层 1">
<g>
<title>Layer 1</title>
<path fill-rule="evenodd" fill="#20e86a" d="m90.53,44.88c-0.4,-11.48 -5.07,-22.4 -13.09,-30.55c-8.4,-8.54 -19.79,-13.33 -31.66,-13.33s-23.27,4.79 -31.67,13.33c-5.02,5.11 -8.72,11.3 -10.89,18.04l3.9,0.32c2.02,-5.82 5.3,-11.18 9.67,-15.63c7.68,-7.81 18.11,-12.19 28.97,-12.19s21.29,4.39 28.97,12.19c7.31,7.43 11.57,17.37 11.97,27.82l-3.51,0l5.4,7.12l5.4,-7.12l-3.47,0l0.01,0z" class="cls-1" id="path2"/>
<path fill-rule="evenodd" fill="#20e86a" d="m87.87,59.31c-2.02,5.82 -5.3,11.18 -9.67,15.63c-7.68,7.81 -18.11,12.19 -28.97,12.19s-21.29,-4.39 -28.97,-12.19c-7.31,-7.43 -11.57,-17.37 -11.97,-27.82l3.51,0l-5.4,-7.12l-5.4,7.12l3.47,0c0.4,11.48 5.07,22.4 13.09,30.55c8.4,8.53 19.79,13.33 31.66,13.33s23.26,-4.79 31.66,-13.33c5.02,-5.11 8.72,-11.3 10.89,-18.04l-3.9,-0.32z" class="cls-1" id="path1"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 929 B

View file

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.7212 3.81468L7.23212 1.3256C7.10398 1.19746 6.89622 1.19746 6.76808 1.3256L4.27899 3.81468C4.21746 3.87622 4.18289 3.95968 4.18289 4.0467C4.18289 4.22792 4.32979 4.37483 4.51101 4.37483L6.34377 4.37424L6.34385 8.96858L6.34826 9.04511C6.38617 9.37149 6.66355 9.62483 7.0001 9.62483C7.36253 9.62483 7.65635 9.33102 7.65635 8.96858L7.65627 4.37424L9.48918 4.37483C9.57621 4.37483 9.65967 4.34026 9.7212 4.27872C9.84934 4.15058 9.84934 3.94283 9.7212 3.81468ZM12.869 7.61875C12.869 7.27693 12.5919 6.99983 12.2501 6.99983C11.8924 6.99983 11.5914 7.26785 11.5501 7.62317L11.5306 7.76392C11.1667 9.9373 9.27683 11.5936 7.0001 11.5936C4.75084 11.5936 2.87915 9.97704 2.48345 7.84238L2.47787 7.81098L2.45226 7.62633C2.41148 7.26938 2.10937 6.99983 1.7501 6.99983L1.69071 7.00269C1.35085 7.03549 1.10193 7.33758 1.13474 7.67744L1.15 7.81514L1.18603 8.04498C1.67947 10.8084 4.09481 12.9061 7.0001 12.9061C9.97945 12.9061 12.4436 10.7001 12.8481 7.83235L12.8661 7.67925L12.869 7.61875Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,17 @@
<svg width="234" height="17" viewBox="0 0 234 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M169.731 3.76779H28.1206V4.78227H169.731V3.76779Z" fill="#B3B3B3"/>
<path d="M30.8688 1.82988L19.082 9.38452L19.3511 9.81281L31.1378 2.25817L30.8688 1.82988Z" fill="#B3B3B3"/>
<path d="M31.1343 2.24611V15.4343H31.6364V2.24611H31.1343Z" fill="#B3B3B3"/>
<path d="M206.39 8.5V15.5H206.892V8.5H206.39Z" fill="#B3B3B3"/>
<path d="M222.957 1.23163V15.4343H223.459V1.23163H222.957Z" fill="#B3B3B3"/>
<path d="M216.935 1.23163V8.33295H217.437V1.23163H216.935Z" fill="#B3B3B3"/>
<path d="M217.438 8.31208L206.39 8.36945L206.393 8.87668L217.44 8.81931L217.438 8.31208Z" fill="#B3B3B3"/>
<path d="M223.2 0.99753L217.2 1.02869L217.203 1.53592L223.203 1.50476L223.2 0.99753Z" fill="#B3B3B3"/>
<path d="M169.731 5.79672H28.1206V6.8112H169.731V5.79672Z" fill="#B3B3B3"/>
<path d="M169.731 7.82568H28.1206V8.84016H169.731V7.82568Z" fill="#B3B3B3"/>
<path d="M28.1212 9.34741H0V11.3764H28.1212V9.34741Z" fill="#B3B3B3"/>
<path d="M174.25 9.85464H28.1206V10.8691H174.25V9.85464Z" fill="#B3B3B3"/>
<path d="M215.93 11.8836H28.1206V12.898H215.93V11.8836Z" fill="#B3B3B3"/>
<path d="M233.004 14.927H0.00439453V15.9415H233.004V14.927Z" fill="#B3B3B3"/>
<path d="M232.999 5.28949H231.46V15.4785H232.999V5.28949Z" fill="#B3B3B3"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3.19971" y="11.7114" width="12.1774" height="1.4" rx="0.7" transform="rotate(-45 3.19971 11.7114)" fill="white"/>
<rect x="4.18848" y="3.09937" width="12.1802" height="1.4" rx="0.7" transform="rotate(45 4.18848 3.09937)" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 348 B

View file

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3.19971" y="11.7114" width="12.1774" height="1.4" rx="0.7" transform="rotate(-45 3.19971 11.7114)" fill="white" fill-opacity="0.64"/>
<rect x="4.18848" y="3.09912" width="12.1802" height="1.4" rx="0.7" transform="rotate(45 4.18848 3.09912)" fill="white" fill-opacity="0.64"/>
</svg>

After

Width:  |  Height:  |  Size: 388 B

View file

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0002 0.833252C15.0628 0.833252 19.1668 4.93731 19.1668 9.99992C19.1668 15.0625 15.0628 19.1666 10.0002 19.1666C4.93755 19.1666 0.833496 15.0625 0.833496 9.99992C0.833496 4.93731 4.93755 0.833252 10.0002 0.833252ZM10.0002 12.7083C9.42487 12.7083 8.9585 13.1746 8.9585 13.7499C8.9585 14.3252 9.42487 14.7916 10.0002 14.7916C10.5755 14.7916 11.0418 14.3252 11.0418 13.7499C11.0418 13.1746 10.5755 12.7083 10.0002 12.7083ZM9.17244 5.73607C9.22057 5.32162 9.5728 4.99992 10.0002 4.99992C10.4275 4.99992 10.7798 5.32162 10.8279 5.73607L10.8335 5.83325V10.8333L10.8279 10.9304C10.7798 11.3449 10.4275 11.6666 10.0002 11.6666C9.5728 11.6666 9.22057 11.3449 9.17244 10.9304L9.16683 10.8333V5.83325L9.17244 5.73607Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 878 B

View file

@ -0,0 +1,18 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_12_4)">
<rect x="2" y="34" width="32" height="32" rx="2" transform="rotate(-90 2 34)" fill="#EEEEEE"/>
</g>
<path d="M13.3006 18.65C12.8998 18.3331 12.8998 17.6669 13.3006 17.35L19.8807 12.1469C20.351 11.7751 21 12.152 21 12.7969L21 23.2031C21 23.848 20.351 24.2249 19.8807 23.8531L13.3006 18.65Z" fill="#909090"/>
<defs>
<filter id="filter0_d_12_4" x="0.953722" y="0.953723" width="34.0926" height="34.0926" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.523139"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_12_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_12_4" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,18 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_12_8)">
<rect x="34" y="2" width="32" height="32" rx="2" transform="rotate(90 34 2)" fill="#EEEEEE"/>
</g>
<path d="M22.6994 17.35C23.1002 17.6669 23.1002 18.3331 22.6994 18.65L16.1193 23.8531C15.649 24.2249 15 23.848 15 23.2031L15 12.7969C15 12.152 15.649 11.7751 16.1193 12.1469L22.6994 17.35Z" fill="#909090"/>
<defs>
<filter id="filter0_d_12_8" x="0.953722" y="0.953722" width="34.0926" height="34.0926" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.523139"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_12_8"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_12_8" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,3 @@
<svg width="7" height="7" viewBox="0 0 7 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.84691 3.72084C6.04317 3.87625 6.32909 3.8633 6.51041 3.68198C6.70567 3.48672 6.70567 3.17014 6.51041 2.97488L3.68198 0.146449L3.63837 0.107596C3.44211 -0.0478172 3.15619 -0.0348658 2.97487 0.146449L0.146447 2.97488L0.107593 3.01849C-0.0478193 3.21475 -0.0348682 3.50067 0.146447 3.68198L0.190057 3.72084C0.386316 3.87625 0.672239 3.8633 0.853553 3.68198L3.32847 1.20711L5.8033 3.68198L5.84691 3.72084ZM5.84691 6.72084C6.04317 6.87625 6.32909 6.8633 6.51041 6.68198C6.70567 6.48672 6.70567 6.17014 6.51041 5.97488L3.68198 3.14645L3.63837 3.1076C3.44211 2.95218 3.15619 2.96513 2.97487 3.14645L0.146447 5.97488L0.107594 6.01849C-0.0478191 6.21475 -0.0348681 6.50067 0.146447 6.68198L0.190057 6.72084C0.386316 6.87625 0.672239 6.8633 0.853554 6.68198L3.32848 4.20711L5.8033 6.68198L5.84691 6.72084Z" fill="#6B6B6B"/>
</svg>

After

Width:  |  Height:  |  Size: 965 B

View file

@ -0,0 +1,3 @@
<svg width="7" height="7" viewBox="0 0 7 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.809942 3.10759C0.613683 2.95218 0.327761 2.96513 0.146446 3.14645C-0.0488168 3.34171 -0.0488168 3.65829 0.146446 3.85355L2.97487 6.68198L3.01848 6.72083C3.21474 6.87625 3.50066 6.8633 3.68198 6.68198L6.51041 3.85355L6.54926 3.80994C6.70467 3.61368 6.69172 3.32776 6.51041 3.14645L6.4668 3.10759C6.27054 2.95218 5.98461 2.96513 5.8033 3.14645L3.32838 5.62132L0.853552 3.14645L0.809942 3.10759ZM0.809941 0.107593C0.613683 -0.0478196 0.32776 -0.0348685 0.146445 0.146446C-0.0488167 0.341709 -0.0488167 0.658291 0.146445 0.853553L2.97487 3.68198L3.01848 3.72083C3.21474 3.87625 3.50066 3.8633 3.68198 3.68198L6.51041 0.853554L6.54926 0.809943C6.70467 0.613684 6.69172 0.327762 6.51041 0.146447L6.4668 0.107593C6.27054 -0.0478193 5.98461 -0.0348683 5.8033 0.146447L3.32838 2.62132L0.853552 0.146446L0.809941 0.107593Z" fill="#6B6B6B"/>
</svg>

After

Width:  |  Height:  |  Size: 982 B

View file

@ -0,0 +1,4 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5357 11.5462C9.59362 12.2735 8.41309 12.7065 7.13107 12.7065C4.05204 12.7065 1.55566 10.2101 1.55566 7.13107C1.55566 4.05204 4.05204 1.55566 7.13107 1.55566C10.2101 1.55566 12.7065 4.05204 12.7065 7.13107C12.7065 8.01817 12.4993 8.85621 12.1306 9.60123" stroke="#C4C4C4" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M6.69629 3.75439V7.25203C6.69629 7.40847 6.82314 7.53532 6.97958 7.53532H10.0891" stroke="#C4C4C4" stroke-miterlimit="10" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 591 B

View file

@ -0,0 +1,6 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.54156 4.72495C7.32505 5.50922 7.18694 6.61633 7.18694 7.8555C7.18694 9.09467 7.32505 10.2018 7.54156 10.986C7.65064 11.3811 7.77318 11.6704 7.89182 11.8511C7.9619 11.9579 8.01129 11.9995 8.03554 12.0152C8.03969 12.0125 8.0445 12.009 8.04996 12.0048C8.08868 11.9746 8.14128 11.9181 8.19342 11.829C8.30988 11.63 8.56558 11.5631 8.76456 11.6796C8.96353 11.796 9.03043 12.0518 8.91398 12.2507C8.81947 12.4122 8.70098 12.5561 8.56251 12.6638C8.42695 12.7692 8.24739 12.8582 8.04044 12.8582C7.64645 12.8582 7.36927 12.5765 7.19384 12.3092C7.00772 12.0257 6.85684 11.6431 6.73678 11.2082C6.49502 10.3325 6.35205 9.147 6.35205 7.8555C6.35205 6.564 6.49502 5.37847 6.73678 4.50277C6.85684 4.06788 7.00772 3.68531 7.19384 3.40175C7.36927 3.13445 7.64645 2.85278 8.04044 2.85278C8.424 2.85278 8.70476 3.12518 8.87921 3.39344C9.0049 3.58671 8.95011 3.84528 8.75684 3.97097C8.56356 4.09666 8.30499 4.04187 8.1793 3.84859C8.12564 3.76608 8.07955 3.72108 8.04978 3.6996C8.04606 3.69692 8.0428 3.69474 8.04 3.69298C8.0177 3.70628 7.9665 3.74607 7.89182 3.85986C7.77318 4.04061 7.65064 4.32987 7.54156 4.72495Z" fill="#C4C4C4"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.12945 4.60703C4.91294 5.3913 4.77483 6.49841 4.77483 7.73758C4.77483 8.97675 4.91294 10.0839 5.12945 10.8681C5.23853 11.2632 5.36108 11.5525 5.47971 11.7332C5.54979 11.84 5.59918 11.8816 5.62343 11.8973C5.62758 11.8945 5.63239 11.8911 5.63785 11.8868C5.67657 11.8567 5.72917 11.8002 5.78131 11.7111C5.89777 11.5121 6.15348 11.4452 6.35245 11.5617C6.55143 11.6781 6.61832 11.9338 6.50187 12.1328C6.40736 12.2943 6.28887 12.4382 6.1504 12.5459C6.01484 12.6513 5.83528 12.7403 5.62833 12.7403C5.23435 12.7403 4.95716 12.4586 4.78173 12.1913C4.59561 11.9078 4.44473 11.5252 4.32467 11.0903C4.08291 10.2146 3.93994 9.02908 3.93994 7.73758C3.93994 6.44608 4.08291 5.26055 4.32467 4.38485C4.44473 3.94996 4.59561 3.56739 4.78173 3.28383C4.95716 3.01653 5.23435 2.73486 5.62833 2.73486C6.01189 2.73486 6.29265 3.00726 6.46711 3.27552C6.59279 3.46879 6.538 3.72736 6.34473 3.85305C6.15145 3.97874 5.89288 3.92395 5.76719 3.73067C5.71353 3.64816 5.66744 3.60316 5.63767 3.58168C5.63395 3.579 5.63069 3.57682 5.62789 3.57506C5.60559 3.58836 5.5544 3.62815 5.47971 3.74194C5.36108 3.92269 5.23853 4.21195 5.12945 4.60703Z" fill="#C4C4C4"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1283 4.12035C9.87089 5.05906 9.70647 6.37948 9.70647 7.85462C9.70647 9.32977 9.87089 10.6502 10.1283 11.5889C10.2578 12.0612 10.4045 12.4133 10.5499 12.6374C10.6221 12.7489 10.6841 12.8132 10.7291 12.8468C10.7506 12.8628 10.7651 12.8695 10.7725 12.8723C10.7761 12.8736 10.7783 12.8741 10.7791 12.8742L10.7799 12.8744L10.7799 12.8744L10.7799 12.8744L10.7799 12.8744L10.78 12.8744L10.7808 12.8742C10.7816 12.8741 10.7838 12.8736 10.7874 12.8723C10.7947 12.8695 10.8093 12.8628 10.8307 12.8468C10.8757 12.8132 10.9378 12.7489 11.01 12.6374C11.1553 12.4133 11.3021 12.0612 11.4316 11.5889C11.689 10.6502 11.8534 9.32977 11.8534 7.85462C11.8534 6.37948 11.689 5.05906 11.4316 4.12035C11.3021 3.64802 11.1553 3.29599 11.01 3.07181C10.9378 2.96039 10.8757 2.89605 10.8307 2.86247C10.8093 2.84648 10.7947 2.8397 10.7874 2.83698C10.7838 2.83563 10.7816 2.83517 10.7808 2.83501L10.78 2.8349L10.7799 2.83489L10.7799 2.83489L10.7799 2.83489L10.7799 2.8349L10.7791 2.83501C10.7783 2.83517 10.7761 2.83563 10.7725 2.83698C10.7651 2.8397 10.7506 2.84648 10.7291 2.86247C10.6841 2.89605 10.6221 2.96039 10.5499 3.07181C10.4045 3.29599 10.2578 3.64802 10.1283 4.12035ZM9.84933 2.61764C10.0489 2.30973 10.3541 2 10.7799 2C11.2058 2 11.5109 2.30973 11.7105 2.61764C11.9219 2.94374 12.0965 3.38796 12.2368 3.89957C12.519 4.92873 12.6883 6.3269 12.6883 7.85462C12.6883 9.38235 12.519 10.7805 12.2368 11.8097C12.0965 12.3213 11.9219 12.7655 11.7105 13.0916C11.5109 13.3995 11.2058 13.7092 10.7799 13.7092C10.3541 13.7092 10.0489 13.3995 9.84933 13.0916C9.63793 12.7655 9.46341 12.3213 9.32312 11.8097C9.04092 10.7805 8.87158 9.38235 8.87158 7.85462C8.87158 6.3269 9.04092 4.92873 9.32312 3.89957C9.46341 3.38796 9.63793 2.94374 9.84933 2.61764Z" fill="#C4C4C4"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.26534 4.10905C2.00338 5.04001 1.83489 6.3532 1.83489 7.82957C1.83489 9.3071 1.9975 10.6275 2.25395 11.5656C2.38298 12.0376 2.52942 12.3889 2.67478 12.6124C2.74698 12.7235 2.80907 12.7876 2.8543 12.8211C2.87585 12.8371 2.8907 12.844 2.89855 12.8468C2.90244 12.8483 2.90492 12.8488 2.90614 12.8491C2.90733 12.8493 2.90797 12.8493 2.90835 12.8493H2.90847C2.91216 12.8493 2.96513 12.8497 3.06709 12.7299C3.17083 12.6081 3.28495 12.4059 3.39934 12.1128C3.48315 11.898 3.72519 11.7918 3.93997 11.8756C4.15475 11.9594 4.26093 12.2015 4.17713 12.4162C4.04711 12.7495 3.89238 13.0485 3.70282 13.2711C3.51271 13.4944 3.248 13.6842 2.90835 13.6842C2.48203 13.6842 2.17586 13.3767 1.97487 13.0676C1.76277 12.7414 1.58842 12.2972 1.44861 11.7858C1.16735 10.7569 1 9.35876 1 7.82957C1 6.2992 1.17368 4.90633 1.46166 3.88291C1.60483 3.37409 1.78273 2.93292 1.99773 2.60928C2.20189 2.30195 2.5096 2 2.9328 2C3.28967 2 3.56218 2.22163 3.74971 2.46002C3.94226 2.70478 4.10133 3.03449 4.23133 3.40764C4.30717 3.62535 4.19217 3.86333 3.97445 3.93918C3.75673 4.01503 3.51875 3.90002 3.44291 3.6823C3.32849 3.35389 3.20649 3.11983 3.09352 2.97622C2.99547 2.85157 2.93923 2.83649 2.93147 2.83496C2.92979 2.83512 2.9265 2.83569 2.92101 2.83768C2.91248 2.84077 2.89707 2.84791 2.87507 2.86396C2.829 2.89755 2.76618 2.96134 2.69316 3.07126C2.54612 3.29259 2.39713 3.64068 2.26534 4.10905Z" fill="#C4C4C4"/>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.88">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.4053 8.05654C11.6669 8.26376 12.0482 8.24649 12.2899 8.00474C12.5503 7.74439 12.5503 7.32228 12.2899 7.06193L8.51868 3.29069L8.46053 3.23889C8.19886 3.03167 7.81763 3.04894 7.57587 3.29069L3.80464 7.06193L3.75283 7.12008C3.54562 7.38176 3.56288 7.76299 3.80464 8.00474L3.86278 8.05654C4.12446 8.26376 4.50569 8.24649 4.74745 8.00474L8.04734 4.70491L11.3471 8.00474L11.4053 8.05654ZM11.4053 12.0565C11.6669 12.2638 12.0482 12.2465 12.2899 12.0047C12.5503 11.7444 12.5503 11.3223 12.2899 11.0619L8.51868 7.29069L8.46054 7.23889C8.19886 7.03167 7.81763 7.04894 7.57587 7.29069L3.80464 11.0619L3.75283 11.1201C3.54562 11.3818 3.56288 11.763 3.80464 12.0047L3.86278 12.0565C4.12446 12.2638 4.50569 12.2465 4.74745 12.0047L8.04734 8.70491L11.3471 12.0047L11.4053 12.0565Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 962 B

View file

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.88">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.59474 7.94346C4.33306 7.73624 3.95184 7.75351 3.71008 7.99526C3.44973 8.25561 3.44973 8.67772 3.71008 8.93807L7.48132 12.7093L7.53947 12.7611C7.80114 12.9683 8.18237 12.9511 8.42413 12.7093L12.1954 8.93807L12.2472 8.87992C12.4544 8.61824 12.4371 8.23701 12.1954 7.99526L12.1372 7.94346C11.8755 7.73624 11.4943 7.75351 11.2526 7.99526L7.95266 11.2951L4.65289 7.99526L4.59474 7.94346ZM4.59474 3.94346C4.33307 3.73624 3.95184 3.75351 3.71008 3.99526C3.44973 4.25561 3.44973 4.67772 3.71008 4.93807L7.48132 8.70931L7.53946 8.76111C7.80114 8.96833 8.18237 8.95106 8.42413 8.70931L12.1954 4.93807L12.2472 4.87992C12.4544 4.61824 12.4371 4.23701 12.1954 3.99526L12.1372 3.94346C11.8755 3.73624 11.4943 3.75351 11.2526 3.99526L7.95266 7.29509L4.65289 3.99526L4.59474 3.94346Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 963 B

View file

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="#00AE42"/>
</svg>

After

Width:  |  Height:  |  Size: 742 B

View file

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="#00AE42"/>
</svg>

After

Width:  |  Height:  |  Size: 742 B

View file

@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="#00AE42"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="black" fill-opacity="0.2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="#00AE42"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5131 3.11974L14.6335 3.23273C15.5708 4.16997 15.6083 5.66627 14.746 6.64825L14.6335 6.76825L6.87213 14.1673H3.3363V10.6315L11.0975 3.23227C12.0348 2.29498 13.5311 2.25748 14.5131 3.11974ZM16.6429 15.8337C17.1162 15.8337 17.5 16.2068 17.5 16.6671C17.5 17.1273 17.1162 17.5004 16.6429 17.5004H3.35714C2.88376 17.5004 2.5 17.1273 2.5 16.6671C2.5 16.2068 2.88376 15.8337 3.35714 15.8337H16.6429ZM12.2762 4.41124L12.3547 4.34192C12.6816 4.08778 13.1542 4.11088 13.4545 4.41124C13.7799 4.73663 13.7799 5.26418 13.4545 5.58957L6.1813 12.5006H5.00296V11.3223L12.2762 4.41124Z" fill="white" fill-opacity="0.2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,13 @@
<svg width="42" height="42" viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_11764_39986)">
<rect x="3.5" y="13.5" width="24" height="24" stroke="#262E30"/>
<rect x="14.5" y="4.5" width="24" height="24" stroke="#262E30"/>
<path d="M17.25 14L15 16.1M21 14L15 20.3M24.75 14L15 24.5M27 15.4L15.75 28M27 18.9L19.5 28M27 23.8L23.25 28" stroke="#00AE42" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="14.5" y="13.5" width="13" height="15" stroke="#00AE42"/>
</g>
<defs>
<clipPath id="clip0_11764_39986">
<rect width="42" height="42" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 643 B

View file

@ -0,0 +1,13 @@
<svg width="42" height="42" viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_11764_39986)">
<rect x="3.5" y="13.5" width="24" height="24" stroke="#B6B6B6"/>
<rect x="14.5" y="4.5" width="24" height="24" stroke="#B6B6B6"/>
<path d="M17.25 14L15 16.1M21 14L15 20.3M24.75 14L15 24.5M27 15.4L15.75 28M27 18.9L19.5 28M27 23.8L23.25 28" stroke="#00AE42" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="14.5" y="13.5" width="13" height="15" stroke="#00AE42"/>
</g>
<defs>
<clipPath id="clip0_11764_39986">
<rect width="42" height="42" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 643 B

View file

@ -0,0 +1,21 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="48" height="48" transform="matrix(1 0 0 -1 0 48)" fill="#FEFFFE"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 32)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 32)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 32)" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,21 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="48" height="48" transform="matrix(1 0 0 -1 0 48)" fill="#FEFFFE"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 0 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 8 32)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 16 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 24 32)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 8)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 24)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 32 40)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 0)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 16)" fill="#D9D9D9"/>
<rect width="8" height="8" transform="matrix(0 1 1 0 40 32)" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,4 @@
<svg width="50" height="68" viewBox="0 0 50 68" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50 64C50 66.2091 48.2091 68 46 68H4C1.79086 68 0 66.2091 0 64V4C0 1.79086 1.79086 0 4 0H46C48.2091 0 50 1.79086 50 4V64Z" fill="#FEFFFE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.84619 4V0H7.69234V4H3.84619ZM0 4V8H3.84615V4H0ZM23.0767 4V8H19.231V4H23.0767ZM19.231 64V68H23.0771V64H26.9229V60H23.0771V56H26.9229V52H23.0771V48H26.9229V44H23.0771V40H26.9229V36H23.0771V32H26.9229V28H23.0771V24H26.9229V20H23.0771V16H26.9229V12H23.0771V8H26.9229V4H23.0771V0H19.231L19.231 4H15.3848V8H19.231V12H15.3848V16H19.231V20H15.3848V24H19.231L19.231 28H15.3848V32H19.231V36H15.3848V40H19.231V44H15.3848V48H19.231V52H15.3848V56H19.231L19.231 60H15.3848V64H19.231ZM19.231 64V60H23.0767V64H19.231ZM19.231 56V52H23.0767V56H19.231ZM19.231 48V44H23.0767V48H19.231ZM19.231 40V36H23.0767V40H19.231ZM19.231 32L19.231 28H23.0767V32H19.231ZM19.231 24V20H23.0767V24H19.231ZM19.231 16H23.0767V12H19.231V16ZM0 40V36H3.84615V40H0ZM0 16V12H3.84615V16H0ZM0 48V44H3.84615V48H0ZM0 24V20H3.84615V24H0ZM0 56V52H3.84615V56H0ZM3.84619 28V24H7.69234V28H3.84619ZM26.9233 24V28H30.769V32H26.9233V36H30.769V40H26.9233V44H30.769V48H26.9233V52H30.769V56H26.9233V60H30.769V64H26.9233V68H30.7694V64H34.6152V68H38.4613V64H34.6152V60H38.4613V56H34.6152V52H38.4613V48H34.6152V44H38.4613V40H34.6152V36H38.4613V32H34.6152L34.6152 28H38.4613V24H34.6152V20H38.4613V16H34.6152V12H38.4613V8H34.6152V4H38.4613V0H34.6152L34.6152 4H30.7694V0H26.9233V4H30.769V8H26.9233V12H30.769V16H26.9233V20H30.769V24H26.9233ZM34.6152 8H30.7694V12H34.6152V8ZM34.6152 16H30.7694V20H34.6152V16ZM34.6152 24L34.6152 28H30.7694V24H34.6152ZM34.6152 32V36H30.7694V32H34.6152ZM34.6152 40H30.7694V44H34.6152V40ZM34.6152 48H30.7694V52H34.6152V48ZM34.6152 56L34.6152 60H30.7694V56H34.6152ZM3.84619 60V56H7.69234V60H3.84619ZM3.84619 64V68H7.69234V64H3.84619ZM0 32V28H3.84615V32H0ZM0 64V60H3.84615V64H0ZM3.84619 36V32H7.69234V36H3.84619ZM3.84619 12V8H7.69234V12H3.84619ZM3.84619 44V40H7.69234V44H3.84619ZM3.84619 20V16H7.69234V20H3.84619ZM3.84619 52V48H7.69234V52H3.84619ZM7.69238 8V4H11.5386V8H7.69238ZM7.69238 40V36H11.5386V40H7.69238ZM7.69238 16V12H11.5386V16H7.69238ZM7.69238 48V44H11.5386V48H7.69238ZM7.69238 24V20H11.5386V24H7.69238ZM7.69238 56V52H11.5386V56H7.69238ZM11.5386 28V24H15.3847V28H11.5386ZM11.5386 60V56H15.3847V60H11.5386ZM11.5386 64V68H15.3847V64H11.5386ZM7.69238 32V28H11.5386V32H7.69238ZM7.69238 64V60H11.5386V64H7.69238ZM11.5386 4V0H15.3847V4H11.5386ZM11.5386 36V32H15.3847V36H11.5386ZM11.5386 12V8H15.3847V12H11.5386ZM11.5386 44V40H15.3847V44H11.5386ZM11.5386 20V16H15.3847V20H11.5386ZM11.5386 52V48H15.3847V52H11.5386ZM38.4614 4V8H42.3076V12H38.4614V16H42.3076V20H38.4614V24H42.3076L42.3076 28H38.4614V32H42.3076V36H38.4614V40H42.3076V44H38.4614V48H42.3076V52H38.4614V56H42.3076L42.3076 60H38.4614V64H42.3076V68H46.1537V64H42.3076V60H46.1537V56H42.3076V52H46.1537V48H42.3076V44H46.1537V40H42.3076V36H46.1537V32H42.3076L42.3076 28H46.1537V24H42.3076V20H46.1537V16H42.3076V12H46.1537V8H42.3076V4H46.1537V0H42.3076L42.3076 4H38.4614ZM46.1538 32V28H50V32H46.1538ZM46.1538 60V64H50V60H46.1538ZM46.1538 8V4H50V8H46.1538ZM46.1538 36V40H50V36H46.1538ZM46.1538 16V12H50V16H46.1538ZM46.1538 44V48H50V44H46.1538ZM46.1538 24V20H50V24H46.1538ZM46.1538 52V56H50V52H46.1538Z" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -0,0 +1,4 @@
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25 12.5C25 5.59644 19.4036 0 12.5 0V0C5.59644 0 0 5.59644 0 12.5V12.5C0 19.4036 5.59644 25 12.5 25V25C19.4036 25 25 19.4036 25 12.5V12.5Z" fill="#FEFFFE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.250045 15C0.0860757 14.1922 0 13.3562 0 12.5C0 11.6438 0.0860756 10.8078 0.250045 10H5V15H0.250045ZM5 22.5009C4.05303 21.7896 3.21038 20.947 2.49908 20H5V22.5009ZM15 24.75C14.1922 24.9139 13.3562 25 12.5 25C11.6438 25 10.8078 24.9139 10 24.75V20H15V24.75ZM22.5009 20C21.7896 20.947 20.947 21.7896 20 22.5009V20H22.5009ZM25 12.5C25 13.3562 24.9139 14.1922 24.75 15H20V10H24.75C24.9139 10.8078 25 11.6438 25 12.5ZM20 2.49908C20.947 3.21038 21.7896 4.05303 22.5009 5H20V2.49908ZM10 0.250045C10.8078 0.0860756 11.6438 0 12.5 0C13.3562 0 14.1922 0.0860757 15 0.250045V5H10V0.250045ZM5 2.49908C4.05303 3.21038 3.21038 4.05303 2.49908 5H5V10H10V15H5V20H10V15H15V20H20V15H15V10H20V5H15V10H10V5H5V2.49908Z" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,76 @@
<svg width="45" height="44" viewBox="0 0 45 44" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_10957_38888)">
<path d="M45 44H0V0H45V44Z" fill="#FEFFFE"/>
<path d="M0 8V4H4V8H0Z" fill="#D9D9D9"/>
<path d="M24 8V4H28V8H24Z" fill="#D9D9D9"/>
<path d="M0 40V36H4V40H0Z" fill="#D9D9D9"/>
<path d="M24 40V36H28V40H24Z" fill="#D9D9D9"/>
<path d="M0 16V12H4V16H0Z" fill="#D9D9D9"/>
<path d="M24 16V12H28V16H24Z" fill="#D9D9D9"/>
<path d="M0 24V20H4V24H0Z" fill="#D9D9D9"/>
<path d="M24 24V20H28V24H24Z" fill="#D9D9D9"/>
<path d="M4 28V24H8V28H4Z" fill="#D9D9D9"/>
<path d="M28 28V24H32V28H28Z" fill="#D9D9D9"/>
<path d="M0 32V28H4V32H0Z" fill="#D9D9D9"/>
<path d="M24 32V28H28V32H24Z" fill="#D9D9D9"/>
<path d="M4 4V0H8V4H4Z" fill="#D9D9D9"/>
<path d="M28 4V0H32V4H28Z" fill="#D9D9D9"/>
<path d="M4 36V32H8V36H4Z" fill="#D9D9D9"/>
<path d="M4 44V40H8V44H4Z" fill="#D9D9D9"/>
<path d="M28 36V32H32V36H28Z" fill="#D9D9D9"/>
<path d="M28 44V40H32V44H28Z" fill="#D9D9D9"/>
<path d="M4 12V8H8V12H4Z" fill="#D9D9D9"/>
<path d="M28 12V8H32V12H28Z" fill="#D9D9D9"/>
<path d="M4 20V16H8V20H4Z" fill="#D9D9D9"/>
<path d="M28 20V16H32V20H28Z" fill="#D9D9D9"/>
<path d="M8 8V4H12V8H8Z" fill="#D9D9D9"/>
<path d="M32 8V4H36V8H32Z" fill="#D9D9D9"/>
<path d="M40 8V4H44V8H40Z" fill="#D9D9D9"/>
<path d="M8 40V36H12V40H8Z" fill="#D9D9D9"/>
<path d="M32 40V36H36V40H32Z" fill="#D9D9D9"/>
<path d="M40 40V36H44V40H40Z" fill="#D9D9D9"/>
<path d="M8 16V12H12V16H8Z" fill="#D9D9D9"/>
<path d="M32 16V12H36V16H32Z" fill="#D9D9D9"/>
<path d="M40 16V12H44V16H40Z" fill="#D9D9D9"/>
<path d="M8 24V20H12V24H8Z" fill="#D9D9D9"/>
<path d="M32 24V20H36V24H32Z" fill="#D9D9D9"/>
<path d="M40 24V20H44V24H40Z" fill="#D9D9D9"/>
<path d="M12 28V24H16V28H12Z" fill="#D9D9D9"/>
<path d="M36 28V24H40V28H36Z" fill="#D9D9D9"/>
<path d="M44 28V24H48V28H44Z" fill="#D9D9D9"/>
<path d="M8 32V28H12V32H8Z" fill="#D9D9D9"/>
<path d="M32 32V28H36V32H32Z" fill="#D9D9D9"/>
<path d="M40 32V28H44V32H40Z" fill="#D9D9D9"/>
<path d="M12 4V0H16V4H12Z" fill="#D9D9D9"/>
<path d="M36 4V0H40V4H36Z" fill="#D9D9D9"/>
<path d="M44 4V0H48V4H44Z" fill="#D9D9D9"/>
<path d="M12 36V32H16V36H12Z" fill="#D9D9D9"/>
<path d="M12 44V40H16V44H12Z" fill="#D9D9D9"/>
<path d="M36 36V32H40V36H36Z" fill="#D9D9D9"/>
<path d="M44 36V32H48V36H44Z" fill="#D9D9D9"/>
<path d="M36 44V40H40V44H36Z" fill="#D9D9D9"/>
<path d="M44 44V40H48V44H44Z" fill="#D9D9D9"/>
<path d="M12 12V8H16V12H12Z" fill="#D9D9D9"/>
<path d="M36 12V8H40V12H36Z" fill="#D9D9D9"/>
<path d="M44 12V8H48V12H44Z" fill="#D9D9D9"/>
<path d="M12 20V16H16V20H12Z" fill="#D9D9D9"/>
<path d="M36 20V16H40V20H36Z" fill="#D9D9D9"/>
<path d="M44 20V16H48V20H44Z" fill="#D9D9D9"/>
<path d="M16 8V4H20V8H16Z" fill="#D9D9D9"/>
<path d="M16 40V36H20V40H16Z" fill="#D9D9D9"/>
<path d="M16 16V12H20V16H16Z" fill="#D9D9D9"/>
<path d="M16 24V20H20V24H16Z" fill="#D9D9D9"/>
<path d="M20 28V24H24V28H20Z" fill="#D9D9D9"/>
<path d="M16 32V28H20V32H16Z" fill="#D9D9D9"/>
<path d="M20 4V0H24V4H20Z" fill="#D9D9D9"/>
<path d="M20 36V32H24V36H20Z" fill="#D9D9D9"/>
<path d="M20 44V40H24V44H20Z" fill="#D9D9D9"/>
<path d="M20 12V8H24V12H20Z" fill="#D9D9D9"/>
<path d="M20 20V16H24V20H20Z" fill="#D9D9D9"/>
</g>
<defs>
<clipPath id="clip0_10957_38888">
<rect width="45" height="44" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,11 @@
<svg width="62" height="32" viewBox="0 0 62 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_10955_38884)">
<path d="M0 0H62V32H0V0Z" fill="#FEFFFE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0V4H3V8H0V12H3V16H0V20H3V24H0V28H3V32H7V28H11V32H15V28H19V32H23V28H27V32H31V28H35V32H39V28H43V32H47V28H51V32H55V28H59V32H62V28H59V24H62V20H59V16H62V12H59V8H62V4H59V0H55V4H51V0H47V4H43V0H39V4H35V0H31V4H27V0H23V4H19V0H15V4H11V0H7V4H3V0H0ZM7 8V4H11V8H7ZM7 12V8H3V12H7ZM11 12V8H15V12H11ZM11 16V12H7V16H3V20H7V24H3V28H7V24H11V28H15V24H19V28H23V24H27V28H31V24H35V28H39V24H43V28H47V24H51V28H55V24H59V20H55V16H59V12H55V8H59V4H55V8H51V4H47V8H43V4H39V8H35V4H31V8H27V4H23V8H19V4H15V8H19V12H15V16H11ZM11 20V24H15V20H19V24H23V20H27V24H31V20H35V24H39V20H43V24H47V20H51V24H55V20H51V16H55V12H51V8H47V12H43V8H39V12H35V8H31V12H27V8H23V12H19V16H15V20H11ZM23 16V12H27V16H23ZM31 16V12H35V16H31ZM39 16V12H43V16H39ZM47 16V20H43V16H47ZM39 16V20H35V16H39ZM31 16V20H27V16H31ZM23 16V20H19V16H23ZM47 16H51V12H47V16ZM11 20H7V16H11V20Z" fill="#D9D9D9"/>
</g>
<defs>
<clipPath id="clip0_10955_38884">
<rect width="62" height="32" rx="5" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,4 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 2C14 0.89543 13.1046 0 12 0H2C0.89543 0 0 0.895431 0 2V12C0 13.1046 0.895431 14 2 14H12C13.1046 14 14 13.1046 14 12V2Z" fill="#FEFFFE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9992 12.0564V11.2002H11.1992V14H12C13.0857 14 13.9693 13.1349 13.9992 12.0564ZM8.40156 14V11.2002H5.60156V14H8.40156ZM2.8 14V11.2002H0V12C0 13.1046 0.895431 14 2 14H2.8ZM0 8.4001H2.8V5.6001H0V8.4001ZM0 2.8H2.8V0H2C0.89543 0 0 0.895431 0 2V2.8ZM5.60156 0V2.8H8.39844V5.5998H11.1984V2.7998H8.40156V0H5.60156ZM11.1992 0V2.8H13.9992V1.94356C13.9693 0.865088 13.0857 0 12 0H11.1992ZM2.80078 5.5998V2.7998H5.60078V5.5998H2.80078ZM11.1992 8.4001V5.6001H13.9992V8.4001H11.1992ZM2.80078 11.1999V8.3999H5.60078V11.1999H2.80078ZM5.60156 5.6001V8.4001H8.39844V11.1999H11.1984V8.3999H8.40156V5.6001H5.60156Z" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 919 B

View file

@ -0,0 +1,4 @@
<svg width="60" height="25" viewBox="0 0 60 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 8C0 3.58172 3.58172 0 8 0H52C56.4183 0 60 3.58172 60 8V17C60 21.4183 56.4183 25 52 25H8C3.58172 25 0 21.4183 0 17V8Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.581517 5C0.206507 5.92643 0 6.9391 0 8V10H5V15H0V17C0 18.0609 0.206507 19.0736 0.581517 20H5V24.4185C5.92643 24.7935 6.9391 25 8 25H10V20H15V25H20V20H25V25H30V20H35V25H40V20H45V25H50V20H55V24.4185C57.0054 23.6067 58.6067 22.0054 59.4185 20H55V15H60V10H55V5H59.4185C58.6067 2.9946 57.0054 1.39328 55 0.581517V5H50V0H45V5H40V0H35V5H30V0H25V5H20V0H15V5H10V0H8C6.9391 0 5.92643 0.206507 5 0.581517V5H0.581517ZM10 10V5H5V10H10ZM15 10H10V15H5V20H10V15H15V20H20V15H25V20H30V15H35V20H40V15H45V20H50V15H55V10H50V5H45V10H40V5H35V10H30V5H25V10H20V5H15V10ZM15 10V15H20V10H15ZM25 10H30V15H25V10ZM35 10H40V15H35V10ZM45 10H50V15H45V10Z" fill="#D9D9D9"/>
</svg>

After

Width:  |  Height:  |  Size: 939 B

View file

@ -341,8 +341,9 @@ const float bed3d_ax3s_default_tip_length = 5.0f;
int CLI::run(int argc, char **argv)
{
// Mark the main thread for the debugger and for runtime checks.
set_current_thread_name("bambustu_main");
set_current_thread_name("orcaslicer_main");
// Save the thread ID of the main thread.
save_main_thread_id();
#ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on
// startup if gtk3 is used. This env var has to be set explicitly to
@ -2993,7 +2994,7 @@ LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
#if defined(_MSC_VER) || defined(__MINGW32__)
extern "C" {
__declspec(dllexport) int __stdcall bambustu_main(int argc, wchar_t **argv)
__declspec(dllexport) int __stdcall orcaslicer_main(int argc, wchar_t **argv)
{
// Convert wchar_t arguments to UTF8.
std::vector<std::string> argv_narrow;

View file

@ -204,7 +204,7 @@ bool OpenGLVersionCheck::message_pump_exit = false;
extern "C" {
typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv);
Slic3rMainFunc bambustu_main = nullptr;
Slic3rMainFunc orcaslicer_main = nullptr;
}
extern "C" {
@ -292,19 +292,19 @@ int wmain(int argc, wchar_t **argv)
}
// resolve function address here
bambustu_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,
orcaslicer_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,
#ifdef _WIN64
// there is just a single calling conversion, therefore no mangling of the function name.
"bambustu_main"
"orcaslicer_main"
#else // stdcall calling convention declaration
"_bambustu_main@8"
#endif
);
if (bambustu_main == nullptr) {
printf("could not locate the function bambustu_main in OrcaSlicer.dll\n");
if (orcaslicer_main == nullptr) {
printf("could not locate the function orcaslicer_main in OrcaSlicer.dll\n");
return -1;
}
// argc minus the trailing nullptr of the argv
return bambustu_main((int)argv_extended.size() - 1, argv_extended.data());
return orcaslicer_main((int)argv_extended.size() - 1, argv_extended.data());
}
}

View file

@ -193,6 +193,10 @@ namespace ImGui
const wchar_t CollapseBtn = 0x0831;
const wchar_t RevertBtn = 0x0832;
const wchar_t CloseBlockNotifButton = 0x0833;
const wchar_t CloseBlockNotifHoverButton = 0x0834;
const wchar_t BlockNotifErrorIcon = 0x0835;
// void MyFunction(const char* name, const MyMatrix44& v);
}

View file

@ -461,6 +461,11 @@ public:
const PrintObjects& objects() const { return m_objects; }
// PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
// in the notification center.
const SLAPrintObject* get_print_object_by_model_object_id(ObjectID object_id) const {
auto it = std::find_if(m_objects.begin(), m_objects.end(),
[object_id](const SLAPrintObject* obj) { return obj->model_object()->id() == object_id; });
return (it == m_objects.end()) ? nullptr : *it;
}
const SLAPrintObject* get_object(ObjectID object_id) const {
auto it = std::find_if(m_objects.begin(), m_objects.end(),
[object_id](const SLAPrintObject *obj) { return obj->id() == object_id; });

View file

@ -137,6 +137,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Gizmos/GLGizmoSeam.hpp
GUI/Gizmos/GLGizmoText.cpp
GUI/Gizmos/GLGizmoText.hpp
GUI/Gizmos/GLGizmoMeshBoolean.cpp
GUI/Gizmos/GLGizmoMeshBoolean.hpp
GUI/GLSelectionRectangle.cpp
GUI/GLSelectionRectangle.hpp
GUI/Gizmos/GizmoObjectManipulation.cpp

View file

@ -71,30 +71,34 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char
// BBS
std::vector<std::array<float, 4>> get_extruders_colors()
{
unsigned char rgb_color[3] = {};
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
unsigned char rgba_color[4] = {};
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<std::array<float, 4>> colors_out(colors.size());
for (const std::string& color : colors) {
Slic3r::GUI::BitmapCache::parse_color(color, rgb_color);
size_t color_idx = &color - &colors.front();
colors_out[color_idx] = { float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f };
for (const std::string &color : colors) {
Slic3r::GUI::BitmapCache::parse_color4(color, rgba_color);
size_t color_idx = &color - &colors.front();
colors_out[color_idx] = {
float(rgba_color[0]) / 255.f,
float(rgba_color[1]) / 255.f,
float(rgba_color[2]) / 255.f,
float(rgba_color[3]) / 255.f,
};
}
return colors_out;
}
std::array<float, 4> adjust_color_for_rendering(const std::array<float, 4>& colors)
float FullyTransparentMaterialThreshold = 0.1f;
float FullTransparentModdifiedToFixAlpha = 0.3f;
std::array<float, 4> adjust_color_for_rendering(const std::array<float, 4> &colors)
{
if ((colors[0] < 0.1) && (colors[1] < 0.1) && (colors[2] < 0.1))
{
std::array<float, 4> new_color;
new_color[0] = 0.1;
new_color[1] = 0.1;
new_color[2] = 0.1;
new_color[3] = colors[3];
return new_color;
}
if (colors[3] < FullyTransparentMaterialThreshold) { // completely transparent
std::array<float, 4> new_color;
new_color[0] = 1;
new_color[1] = 1;
new_color[2] = 1;
new_color[3] = FullTransparentModdifiedToFixAlpha;
return new_color;
}
return colors;
}
@ -514,8 +518,13 @@ void GLVolume::set_render_color()
}
}
if (force_transparent)
render_color[3] = color[3];
if (force_transparent) {
if (color[3] < FullyTransparentMaterialThreshold) {
render_color[3] = FullTransparentModdifiedToFixAlpha;
} else {
render_color[3] = color[3];
}
}
//BBS set unprintable color
if (!printable) {
@ -1017,12 +1026,21 @@ void GLWipeTowerVolume::render(bool with_outline) const
}
this->iva_per_colors[i].render();
}
glsafe(::glPopMatrix());
if (this->is_left_handed())
glFrontFace(GL_CCW);
}
bool GLWipeTowerVolume::IsTransparent() {
for (size_t i = 0; i < m_colors.size(); i++) {
if (m_colors[i][3] < 1.0f) {
return true;
}
}
return false;
}
std::vector<int> GLVolumeCollection::load_object(
const ModelObject *model_object,
int obj_idx,
@ -1211,8 +1229,12 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) {
GLVolume* volume = volumes[i];
bool is_transparent = (volume->render_color[3] < 1.0f);
if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) ||
(type == GLVolumeCollection::ERenderType::Transparent && is_transparent) ||
auto tempGlwipeTowerVolume = dynamic_cast<GLWipeTowerVolume *>(volume);
if (tempGlwipeTowerVolume) {
is_transparent = tempGlwipeTowerVolume->IsTransparent();
}
if (((type == GLVolumeCollection::ERenderType::Opaque && !is_transparent) ||
(type == GLVolumeCollection::ERenderType::Transparent && is_transparent) ||
type == GLVolumeCollection::ERenderType::All) &&
(! filter_func || filter_func(*volume)))
list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0)));
@ -1236,8 +1258,17 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
return list;
}
int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_support) const
{
const DynamicPrintConfig& glb_cfg = GUI::wxGetApp().preset_bundle->prints.get_edited_preset().config;
enable_support = glb_cfg.opt_bool("enable_support");
int support_threshold_angle = glb_cfg.opt_int("support_threshold_angle");
return support_threshold_angle ;
}
//BBS: add outline drawing logic
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func, bool with_outline) const
void GLVolumeCollection::render(
GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d &view_matrix, std::function<bool(const GLVolume &)> filter_func, bool with_outline) const
{
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
if (to_render.empty())
@ -1305,10 +1336,16 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
//use -1 ad a invalid type
shader->set_uniform("print_volume.type", -1);
}
bool enable_support;
int support_threshold_angle = get_selection_support_threshold_angle(enable_support);
float normal_z = -::cos(Geometry::deg2rad((float) support_threshold_angle));
shader->set_uniform("volume_world_matrix", volume.first->world_matrix());
shader->set_uniform("slope.actived", m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower);
shader->set_uniform("slope.actived", m_slope.isGlobalActive && !volume.first->is_modifier && !volume.first->is_wipe_tower);
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
shader->set_uniform("slope.normal_z", m_slope.normal_z);
shader->set_uniform("slope.normal_z", normal_z);
#if ENABLE_ENVIRONMENT_MAP
unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id();
@ -1496,34 +1533,35 @@ void GLVolumeCollection::reset_outside_state()
}
}
void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* config)
void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig *config, bool is_update_alpha)
{
static const float inv_255 = 1.0f / 255.0f;
struct Color
{
std::string text;
unsigned char rgb[3];
unsigned char rgba[4];
Color()
: text("")
{
rgb[0] = 255;
rgb[1] = 255;
rgb[2] = 255;
rgba[0] = 255;
rgba[1] = 255;
rgba[2] = 255;
rgba[3] = 255;
}
void set(const std::string& text, unsigned char* rgb)
void set(const std::string& text, unsigned char* rgba)
{
this->text = text;
::memcpy((void*)this->rgb, (const void*)rgb, 3 * sizeof(unsigned char));
::memcpy((void*)this->rgba, (const void*)rgba, 4 * sizeof(unsigned char));
}
};
if (config == nullptr)
return;
unsigned char rgb[3];
unsigned char rgba[4];
std::vector<Color> colors;
if (static_cast<PrinterTechnology>(config->opt_int("printer_technology")) == ptSLA)
@ -1531,9 +1569,9 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
const std::string& txt_color = config->opt_string("material_colour").empty() ?
print_config_def.get("material_colour")->get_default_value<ConfigOptionString>()->value :
config->opt_string("material_colour");
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb)) {
if (Slic3r::GUI::BitmapCache::parse_color4(txt_color, rgba)) {
colors.resize(1);
colors[0].set(txt_color, rgb);
colors[0].set(txt_color, rgba);
}
}
else
@ -1549,8 +1587,8 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
for (unsigned int i = 0; i < colors_count; ++i) {
const std::string& txt_color = config->opt_string("filament_colour", i);
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
colors[i].set(txt_color, rgb);
if (Slic3r::GUI::BitmapCache::parse_color4(txt_color, rgba))
colors[i].set(txt_color, rgba);
}
}
@ -1564,8 +1602,14 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
const Color& color = colors[extruder_id];
if (!color.text.empty()) {
for (int i = 0; i < 3; ++i) {
volume->color[i] = (float)color.rgb[i] * inv_255;
for (int i = 0; i < 4; ++i) {
if (is_update_alpha == false) {
if (i < 3) {
volume->color[i] = (float) color.rgba[i] * inv_255;
}
continue;
}
volume->color[i] = (float) color.rgba[i] * inv_255;
}
}
}

View file

@ -31,7 +31,9 @@
#define glcheck()
#endif // HAS_GLSAFE
extern std::vector<std::array<float, 4>> get_extruders_colors();
extern std::array<float, 4> adjust_color_for_rendering(const std::array<float, 4>& colors);
extern float FullyTransparentMaterialThreshold;
extern float FullTransparentModdifiedToFixAlpha;
extern std::array<float, 4> adjust_color_for_rendering(const std::array<float, 4> &colors);
namespace Slic3r {
@ -558,6 +560,7 @@ public:
virtual void render(bool with_outline = false) const;
std::vector<GLIndexedVertexArray> iva_per_colors;
bool IsTransparent();
private:
std::vector<std::array<float, 4>> m_colors;
@ -604,7 +607,8 @@ private:
struct Slope
{
// toggle for slope rendering
bool active{ false };
bool active{ false };//local active
bool isGlobalActive{false};
float normal_z;
};
@ -656,9 +660,14 @@ public:
GLVolume* new_toolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats = 0);
GLVolume* new_nontoolpath_volume(const std::array<float, 4>& rgba, size_t reserve_vbo_floats = 0);
int get_selection_support_threshold_angle(bool&) const;
// Render the volumes by OpenGL.
//BBS: add outline drawing logic
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = std::function<bool(const GLVolume&)>(), bool with_outline = true) const;
void render(ERenderType type,
bool disable_cullface,
const Transform3d & view_matrix,
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
bool with_outline = true) const;
// Finalize the initialization of the geometry & indices,
// upload the geometry and indices to OpenGL VBO objects
@ -678,8 +687,10 @@ public:
void set_z_range(float min_z, float max_z) { m_z_range[0] = min_z; m_z_range[1] = max_z; }
void set_clipping_plane(const double* coeffs) { m_clipping_plane[0] = coeffs[0]; m_clipping_plane[1] = coeffs[1]; m_clipping_plane[2] = coeffs[2]; m_clipping_plane[3] = coeffs[3]; }
bool is_slope_GlobalActive() const { return m_slope.isGlobalActive; }
bool is_slope_active() const { return m_slope.active; }
void set_slope_active(bool active) { m_slope.active = active; }
void set_slope_GlobalActive(bool active) { m_slope.isGlobalActive = active; }
float get_slope_normal_z() const { return m_slope.normal_z; }
void set_slope_normal_z(float normal_z) { m_slope.normal_z = normal_z; }
@ -691,7 +702,7 @@ public:
bool check_outside_state(const Slic3r::BuildVolume& build_volume, ModelInstanceEPrintVolumeState* out_state) const;
void reset_outside_state();
void update_colors_by_extruder(const DynamicPrintConfig* config);
void update_colors_by_extruder(const DynamicPrintConfig *config, bool is_update_alpha = true);
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
std::vector<double> get_current_print_zs(bool active_only) const;

View file

@ -46,9 +46,10 @@ bool SlicingProcessCompletedEvent::critical_error() const
} catch (const Slic3r::SlicingError &) {
// Exception derived from SlicingError is non-critical.
return false;
} catch (...) {
}
return true;
} catch (const Slic3r::SlicingErrors &) {
return false;
} catch (...) {}
return true;
}
bool SlicingProcessCompletedEvent::invalidate_plater() const
@ -69,7 +70,7 @@ bool SlicingProcessCompletedEvent::invalidate_plater() const
return false;
}
std::pair<std::string, size_t> SlicingProcessCompletedEvent::format_error_message() const
std::pair<std::string, std::vector<size_t>> SlicingProcessCompletedEvent::format_error_message() const
{
std::string error;
size_t monospace = 0;
@ -88,12 +89,20 @@ std::pair<std::string, size_t> SlicingProcessCompletedEvent::format_error_messag
} catch (SlicingError &ex) {
error = ex.what();
monospace = ex.objectId();
} catch (SlicingErrors &exs) {
std::vector<size_t> ids;
for (auto &ex : exs.errors_) {
error = ex.what();
monospace = ex.objectId();
ids.push_back(monospace);
}
return std::make_pair(std::move(error), ids);
} catch (std::exception &ex) {
error = ex.what();
} catch (...) {
error = "Unknown C++ exception.";
}
return std::make_pair(std::move(error), monospace);
error = ex.what();
} catch (...) {
error = "Unknown C++ exception.";
}
return std::make_pair(std::move(error), std::vector<size_t>{monospace});
}
BackgroundSlicingProcess::BackgroundSlicingProcess()
@ -308,6 +317,8 @@ void BackgroundSlicingProcess::thread_proc()
break;
// Process the background slicing task.
m_state = STATE_RUNNING;
//BBS: internal cancel
m_internal_cancelled = false;
lck.unlock();
std::exception_ptr exception;
#ifdef _WIN32
@ -328,6 +339,10 @@ void BackgroundSlicingProcess::thread_proc()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": send SlicingProcessCompletedEvent to main, status %1%")%evt.status();
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
}
else {
//BBS: internal cancel
m_internal_cancelled = true;
}
m_print->restart();
lck.unlock();
// Let the UI thread wake up if it is waiting for the background task to finish.

View file

@ -60,7 +60,7 @@ public:
void rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
// Produce a human readable message to be displayed by a notification or a message box.
// 2nd parameter defines whether the output should be displayed with a monospace font.
std::pair<std::string, size_t> format_error_message() const;
std::pair<std::string, std::vector<size_t>> format_error_message() const;
private:
StatusType m_status;
@ -185,6 +185,7 @@ public:
//BBS: improve the finished logic, also judge the m_gcode_result
//bool finished() const { return m_print->finished(); }
bool finished() const { return m_print->finished() && !m_gcode_result->moves.empty(); }
bool is_internal_cancelled() { return m_internal_cancelled; }
//BBS: add Plater to friend class
//need to call stop_internal in ui thread
@ -275,6 +276,7 @@ private:
//BBS: partplate related
GUI::PartPlate* m_current_plate;
PrinterTechnology m_printer_tech = ptUnknown;
bool m_internal_cancelled = false;
PrintState<BackgroundSlicingProcessStep, bspsCount> m_step_state;
bool set_step_started(BackgroundSlicingProcessStep step);

View file

@ -375,7 +375,7 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
std::vector<unsigned char> data(n_pixels * 4, 0);
// BBS: support resize by fill border
if (scale_in_center > 0) {
if (scale_in_center > 0 && scale_in_center < svg_scale) {
int w = (int)(image->width * scale_in_center);
int h = (int)(image->height * scale_in_center);
::nsvgRasterize(rast, image, 0, 0, scale_in_center, data.data() + int(height - h) / 2 * width * 4 + int(width - w) / 2 * 4, w, h, width * 4);
@ -433,6 +433,14 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
{
if (scolor.size() == 9) {
unsigned char rgba[4];
parse_color4(scolor, rgba);
rgb_out[0] = rgba[0];
rgb_out[1] = rgba[1];
rgb_out[2] = rgba[2];
return true;
}
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;
if (scolor.size() != 7 || scolor.front() != '#')
return false;
@ -444,6 +452,23 @@ bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
return false;
rgb_out[i] = (unsigned char)(digit1 * 16 + digit2);
}
return true;
}
bool BitmapCache::parse_color4(const std::string& scolor, unsigned char* rgba_out)
{
rgba_out[0] = rgba_out[1] = rgba_out[2] = 0; rgba_out[3] = 255;
if ((scolor.size() != 7 && scolor.size() != 9) || scolor.front() != '#')
return false;
const char* c = scolor.data() + 1;
for (size_t i = 0; i < scolor.size() / 2; ++i) {
int digit1 = hex_digit_to_int(*c++);
int digit2 = hex_digit_to_int(*c++);
if (digit1 == -1 || digit2 == -1)
return false;
rgba_out[i] = (unsigned char)(digit1 * 16 + digit2);
}
return true;
}

View file

@ -48,6 +48,7 @@ public:
wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
static bool parse_color4(const std::string& scolor, unsigned char* rgba_out);
private:
std::map<std::string, wxBitmap*> m_map;

View file

@ -835,10 +835,12 @@ public:
bool can_export_toolpaths() const;
std::vector<int> get_plater_extruder();
const float get_max_print_height() const { return m_max_print_height; }
const BoundingBoxf3& get_paths_bounding_box() const { return m_paths_bounding_box; }
const BoundingBoxf3& get_max_bounding_box() const { return m_max_bounding_box; }
const BoundingBoxf3& get_shell_bounding_box() const { return m_shell_bounding_box; }
const std::vector<double>& get_layers_zs() const { return m_layers.get_zs(); }
const std::array<unsigned int,2> &get_layers_z_range() const { return m_layers_z_range; }
const SequentialView& get_sequential_view() const { return m_sequential_view; }
void update_sequential_view_current(unsigned int first, unsigned int last);

View file

@ -748,7 +748,7 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
}
// updates print order strings
if (sorted_instances.size() > 1) {
if (sorted_instances.size() > 0) {
for (size_t i = 0; i < sorted_instances.size(); ++i) {
size_t id = sorted_instances[i]->id().id;
std::vector<Owner>::iterator it = std::find_if(owners.begin(), owners.end(), [id](const Owner& owner) {
@ -1296,6 +1296,15 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) {
m_gizmos.set_icon_dirty();
}
}
if (m_canvas_type == CanvasAssembleView) {
m_gizmos.on_change_color_mode(is_dark);
if (reinit) {
// reset svg
m_gizmos.switch_gizmos_icon_filename();
// set dirty to re-generate icon texture
m_gizmos.set_icon_dirty();
}
}
}
void GLCanvas3D::set_as_dirty()
@ -1614,6 +1623,8 @@ void GLCanvas3D::enable_main_toolbar(bool enable)
void GLCanvas3D::reset_select_plate_toolbar_selection() {
if (m_sel_plate_toolbar.m_all_plates_stats_item)
m_sel_plate_toolbar.m_all_plates_stats_item->selected = false;
if (wxGetApp().mainframe)
wxGetApp().mainframe->update_slice_print_status(MainFrame::eEventSliceUpdate, true, true);
}
void GLCanvas3D::enable_select_plate_toolbar(bool enable)
@ -1887,32 +1898,30 @@ void GLCanvas3D::render(bool only_init)
_render_selection();
if (!no_partplate)
_render_bed(!camera.is_looking_downward(), show_axes);
//BBS: add outline logic
if (!no_partplate) //BBS: add outline logic
_render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id, true);
_render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running());
if (!no_partplate)
_render_platelist(!camera.is_looking_downward(), only_current, only_body, hover_id);
}
/* preview render */
else if (m_canvas_type == ECanvasType::CanvasPreview && m_render_preview) {
//BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//BBS: GUI refactor: add canvas size as parameters
_render_gcode(cnv_size.get_width(), cnv_size.get_height());
_render_sla_slices();
_render_selection();
_render_bed(!camera.is_looking_downward(), show_axes);
_render_platelist(!camera.is_looking_downward(), only_current, true, hover_id);
// BBS: GUI refactor: add canvas size as parameters
_render_gcode(cnv_size.get_width(), cnv_size.get_height());
}
/* assemble render*/
else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
//BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//_render_bed(!camera.is_looking_downward(), show_axes);
//BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running());
_render_plane();
//BBS: add outline logic insteadof selection under assemble view
//_render_selection();
// BBS: add outline logic
_render_objects(GLVolumeCollection::ERenderType::Transparent, !m_gizmos.is_running());
}
_render_sequential_clearance();
@ -2377,9 +2386,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
deleted_wipe_towers.emplace_back(volume, volume_id);
delete volume;
}
// BBS
m_explosion_ratio = 1.0;
}
else {
// This GLVolume will be reused.
@ -2635,7 +2641,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const float margin = 15.f;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_bounding_box();
coordf_t plate_bbox_x_max_local_coord = plate_bbox.max(0) - plate_origin(0);
coordf_t plate_bbox_y_max_local_coord = plate_bbox.max(1) - plate_origin(1);
if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) {
x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin;
ConfigOptionFloat wt_x_opt(x);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0);
}
if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) {
y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin;
ConfigOptionFloat wt_y_opt(y);
@ -2673,6 +2685,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
//BBS:exclude the assmble view
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
_set_warning_notification_if_needed(EWarning::GCodeConflict);
// checks for geometry outside the print volume to render it accordingly
if (!m_volumes.empty()) {
ModelInstanceEPrintVolumeState state;
@ -2758,6 +2771,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
if (wxGetApp().is_editor()) {
//BBS: always load shell at preview, do this in load_shells
//m_gcode_viewer.update_shells_color_by_extruder(m_config);
_set_warning_notification_if_needed(EWarning::ToolHeightOutside);
_set_warning_notification_if_needed(EWarning::ToolpathOutside);
_set_warning_notification_if_needed(EWarning::GCodeConflict);
}
@ -2902,6 +2916,7 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
// BBS
//m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state();
_update_imgui_select_plate_toolbar();
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
m_dirty |= mouse3d_controller_applied;
m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this);
@ -3051,7 +3066,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */
case WXK_CONTROL_Y:
#endif /* __APPLE__ */
if (m_canvas_type == CanvasView3D) {
if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) {
post_event(SimpleEvent(EVT_GLCANVAS_REDO));
}
break;
@ -3062,7 +3077,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case WXK_CONTROL_Z:
#endif /* __APPLE__ */
// only support redu/undo in CanvasView3D
if (m_canvas_type == CanvasView3D) {
if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) {
post_event(SimpleEvent(EVT_GLCANVAS_UNDO));
}
break;
@ -3477,7 +3492,10 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
}
else if (keyCode == WXK_CONTROL)
m_dirty = true;
else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
else if (keyCode == WXK_TAB && evt.ShiftDown() && !evt.ControlDown() && !wxGetApp().is_gcode_viewer()) {
// Collapse side-panel with Shift+Tab
post_event(SimpleEvent(EVT_GLCANVAS_COLLAPSE_SIDEBAR));
} else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) {
auto _do_rotate = [this](double angle_z_rad) {
m_selection.start_dragging();
m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint));
@ -3769,7 +3787,7 @@ void GLCanvas3D::on_gesture(wxGestureEvent &evt)
float z = 0;
const Vec3d &p2 = _mouse_to_3d({p.x, p.y}, &z);
const Vec3d &p1 = _mouse_to_3d({p.x - d.x, p.y - d.y}, &z);
camera.set_target(camera.get_target() + p2 - p1);
camera.set_target(camera.get_target() + p1 - p2);
} else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) {
static float zoom_start = 1;
if (evt.IsGestureStart())
@ -4151,7 +4169,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// if dragging over blank area with left button, rotate
if ((any_gizmo_active || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) {
const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.);
if (this->m_canvas_type == ECanvasType::CanvasAssembleView) {
if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports ||
m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
//BBS rotate around target
Camera& camera = wxGetApp().plater()->get_camera();
Vec3d rotate_target = Vec3d::Zero();
@ -4181,13 +4200,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
camera.recover_from_free_camera();
//BBS modify rotation
if (m_gizmos.get_current_type() == GLGizmosManager::FdmSupports
|| m_gizmos.get_current_type() == GLGizmosManager::Seam
|| m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
//camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target);
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, rotate_target);
}
else if (evt.ControlDown() || evt.CmdDown()) {
//if (m_gizmos.get_current_type() == GLGizmosManager::FdmSupports
// || m_gizmos.get_current_type() == GLGizmosManager::Seam
// || m_gizmos.get_current_type() == GLGizmosManager::MmuSegmentation) {
// //camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target);
// //camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, rotate_target);
//}
//else
if (evt.ControlDown() || evt.CmdDown()) {
if ((m_rotation_center.x() == 0.f) && (m_rotation_center.y() == 0.f) && (m_rotation_center.z() == 0.f)) {
auto canvas_w = float(get_canvas_size().get_width());
auto canvas_h = float(get_canvas_size().get_height());
@ -4280,7 +4300,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
wxGetApp().plater()->select_plate_by_hover_id(hover_idx);
//wxGetApp().plater()->get_partplate_list().select_plate_view();
//deselect all the objects
if (m_hover_volume_idxs.empty())
if (m_gizmos.get_current_type() != GLGizmosManager::MeshBoolean && m_hover_volume_idxs.empty())
deselect_all();
}
else if (evt.RightUp() && !is_layers_editing_enabled()) {
@ -5269,13 +5289,13 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa
if (imgui->checkbox(_L("Enable rotation"), settings.enable_rotation)) {
settings_out.enable_rotation = settings.enable_rotation;
appcfg->set("orient", rot_key, settings_out.enable_rotation);
appcfg->set("orient", rot_key, settings_out.enable_rotation ? "1" : "0");
settings_changed = true;
}
if (imgui->checkbox(_L("Optimize support interface area"), settings.min_area)) {
settings_out.min_area = settings.min_area;
appcfg->set("orient", key_min_area, settings_out.min_area);
appcfg->set("orient", key_min_area, settings_out.min_area ? "1" : "0");
settings_changed = true;
}
@ -5292,8 +5312,8 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa
settings_out = OrientSettings{};
settings_out.overhang_angle = 60.f;
appcfg->set("orient", angle_key, std::to_string(settings_out.overhang_angle));
appcfg->set("orient", rot_key, settings_out.enable_rotation );
appcfg->set("orient", key_min_area, settings_out.min_area);
appcfg->set("orient", rot_key, settings_out.enable_rotation ? "1" : "0");
appcfg->set("orient", key_min_area, settings_out.min_area? "1" : "0");
settings_changed = true;
}
@ -5644,7 +5664,8 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
curr_color[2] = vol->color[2];
curr_color[3] = vol->color[3];
shader->set_uniform("uniform_color", curr_color);
std::array<float, 4> new_color = adjust_color_for_rendering(curr_color);
shader->set_uniform("uniform_color", new_color);
shader->set_uniform("volume_world_matrix", vol->world_matrix());
//BBS set all volume to orange
//shader->set_uniform("uniform_color", orange);
@ -5683,6 +5704,8 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns
return;
bool multisample = OpenGLManager::can_multisample();
if (for_picking)
multisample = false;
//if (!multisample)
// glsafe(::glEnable(GL_MULTISAMPLE));
@ -5789,6 +5812,8 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
return;
bool multisample = OpenGLManager::can_multisample();
if (for_picking)
multisample = false;
//if (!multisample)
// glsafe(::glEnable(GL_MULTISAMPLE));
@ -6068,6 +6093,8 @@ bool GLCanvas3D::_init_main_toolbar()
wxGetApp().plater()->orient();
//BBS do not show orient menu
//_render_orient_menu(left, right, bottom, top);
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) agent->track_update_property("auto_orient", std::to_string(++auto_orient_count));
}
};
if (!m_main_toolbar.add_item(item))
@ -6664,9 +6691,9 @@ void GLCanvas3D::_render_bed_for_picking(bool bottom)
//m_bed.render_for_picking(*this, bottom, scale_factor);
}
void GLCanvas3D::_render_platelist(bool bottom, bool only_current, bool only_body, int hover_id) const
void GLCanvas3D::_render_platelist(bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali) const
{
wxGetApp().plater()->get_partplate_list().render(bottom, only_current, only_body, hover_id);
wxGetApp().plater()->get_partplate_list().render(bottom, only_current, only_body, hover_id, render_cali);
}
void GLCanvas3D::_render_plates_for_picking() const
@ -6739,7 +6766,10 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else {
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
}
m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances());
if (m_canvas_type == CanvasAssembleView)
m_volumes.set_show_sinking_contours(false);
else
m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances());
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
ECanvasType canvas_type = this->m_canvas_type;
@ -7056,8 +7086,9 @@ void GLCanvas3D::_render_overlays()
if (m_layers_editing.last_object_id >= 0 && m_layers_editing.object_max_z() > 0.0f)
m_layers_editing.render_overlay(*this);
const ConfigOptionEnum<PrintSequence>* opt = dynamic_cast<const ConfigOptionEnum<PrintSequence>*>(m_config->option<ConfigOptionEnum<PrintSequence>>("print_sequence"));
bool sequential_print = opt != nullptr && (opt->value == PrintSequence::ByObject);
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
auto curr_print_seq = curr_plate->get_real_print_seq();
bool sequential_print = (curr_print_seq == PrintSequence::ByObject);
std::vector<const ModelInstance*> sorted_instances;
if (sequential_print) {
const Print* print = fff_print();
@ -7230,9 +7261,6 @@ void GLCanvas3D::_render_gizmos_overlay()
const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale());
m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
#endif /* __WXMSW__ */
if (m_canvas_type == CanvasAssembleView)
return;
m_gizmos.render_overlay();
if (m_gizmo_highlighter.m_render_arrow)
@ -7394,7 +7422,6 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, scroll_col);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 10.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
@ -7410,7 +7437,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
imgui.begin(_L("Select Plate"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
ImGui::SetWindowFontScale(1.2f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * f_scale);
ImVec2 size = ImVec2(button_width, button_height); // Size of the image we want to make visible
ImVec4 bg_col = ImVec4(128.0f, 128.0f, 128.0f, 0.0f);
@ -7435,7 +7462,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
}
else {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_hover);
}
}
@ -7477,6 +7504,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImVec2 size = ImVec2(button_width, button_height * all_plates_stats_item->percent / 100.0f);
ImVec2 rect_start_pos = ImVec2(start_pos.x, start_pos.y + size.y);
ImVec2 rect_end_pos = ImVec2(start_pos.x + button_width, start_pos.y + button_height);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, rect_end_pos, IM_COL32(0, 0, 0, 10));
ImGui::GetForegroundDrawList()->AddRectFilled(rect_start_pos, rect_end_pos, IM_COL32(0, 0, 0, 80));
}
else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
@ -7485,6 +7513,11 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(40, 1, 1, 64));
ImGui::GetForegroundDrawList()->AddRect(start_pos, end_pos, IM_COL32(208, 27, 27, 255), 0.0f, 0, 1.0f);
}
else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICED) {
ImVec2 size = ImVec2(button_width, button_height);
ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(0, 0, 0, 10));
}
// draw text
GImGui->FontSize = 15.0f;
@ -7508,16 +7541,31 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImVec2 uv0 = ImVec2(0.0f, 1.0f); // UV coordinates for lower-left
ImVec2 uv1 = ImVec2(1.0f, 0.0f); // UV coordinates in our texture
auto button_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(button_pos + margin);
ImGui::Image(item->texture_id, size, uv0, uv1, tint_col);
ImGui::SetCursorPos(button_pos);
// invisible button
auto button_size = size + margin + margin + ImVec2(2 * frame_padding, 2 * frame_padding);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f * f_scale);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
if (item->selected) {
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
ImGui::PushStyleColor(ImGuiCol_Border, button_active);
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
if (ImGui::IsMouseHoveringRect(button_pos, button_pos + button_size)) {
ImGui::PushStyleColor(ImGuiCol_Border, button_hover);
}
else {
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(.0f, .0f, .0f, .0f));
}
}
if (ImGui::ImageButton2(item->texture_id, size, uv0, uv1, frame_padding, bg_col, tint_col, margin)) {
if(ImGui::Button("##invisible_button", button_size)){
if (m_process && !m_process->running()) {
all_plates_stats_item->selected = false;
item->selected = true;
@ -7527,8 +7575,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
wxQueueEvent(wxGetApp().plater(), evt);
}
}
ImGui::PopStyleColor(2);
ImGui::PopStyleColor(4);
ImGui::PopStyleVar();
ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
if (item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
@ -7539,12 +7587,17 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImVec2 size = ImVec2(button_width, button_height * item->percent / 100.0f);
ImVec2 rect_start_pos = ImVec2(start_pos.x, start_pos.y + size.y);
ImVec2 rect_end_pos = ImVec2(start_pos.x + button_width, start_pos.y + button_height);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, rect_end_pos, IM_COL32(0, 0, 0, 10));
ImGui::GetForegroundDrawList()->AddRectFilled(rect_start_pos, rect_end_pos, IM_COL32(0, 0, 0, 80));
} else if (item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
ImVec2 size = ImVec2(button_width, button_height);
ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(40, 1, 1, 64));
ImGui::GetForegroundDrawList()->AddRect(start_pos, end_pos, IM_COL32(208, 27, 27, 255), 0.0f, 0, 1.0f);
} else if (item->slice_state == IMToolbarItem::SliceState::SLICED) {
ImVec2 size = ImVec2(button_width, button_height);
ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
ImGui::GetForegroundDrawList()->AddRectFilled(start_pos, end_pos, IM_COL32(0, 0, 0, 10));
}
// draw text
@ -7554,7 +7607,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
ImGui::PopID();
}
ImGui::SetWindowFontScale(1.0f);
ImGui::PopStyleColor(9);
ImGui::PopStyleColor(8);
ImGui::PopStyleVar(5);
if (ImGui::IsWindowHovered() || is_hovered) {
@ -7645,6 +7698,8 @@ void GLCanvas3D::_render_return_toolbar() const
if (ImGui::ImageTextButton(real_size,_utf8(L("return")).c_str(), m_return_toolbar.get_return_texture_id(), button_icon_size, uv0, uv1, -1, bg_col, tint_col, margin)) {
if (m_canvas != nullptr)
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
}
ImGui::PopStyleColor(5);
ImGui::PopStyleVar(1);
@ -7846,6 +7901,7 @@ void GLCanvas3D::_render_paint_toolbar() const
ImGui::BBLRenderArrow(draw_list, right_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Right, 2.0f);
}
m_paint_toolbar_width = (ImGui::GetWindowWidth() + 50.0f * em_unit * f_scale);
imgui.end();
ImGui::PopStyleVar(3);
ImGui::PopStyleColor();
@ -7858,6 +7914,10 @@ void GLCanvas3D::_render_assemble_control() const
GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
return;
}
if (m_gizmos.get_current_type() == GLGizmosManager::EType::MmuSegmentation) {
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(0.0, true);
return;
}
ImGuiWrapper* imgui = wxGetApp().imgui();
@ -8845,15 +8905,22 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
{
_set_current();
bool show = false;
if (!m_volumes.empty())
if (!m_volumes.empty()) {
show = _is_any_volume_outside();
else {
show &= m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
} else {
if (wxGetApp().is_editor()) {
if (current_printer_technology() != ptSLA)
if (warning == EWarning::ToolpathOutside)
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
else if (warning==EWarning::GCodeConflict)
if (current_printer_technology() != ptSLA) {
unsigned int max_z_layer = m_gcode_viewer.get_layers_z_range().back();
if (warning == EWarning::ToolHeightOutside) // check if max z_layer height exceed max print height
show = m_gcode_viewer.has_data() && (m_gcode_viewer.get_layers_zs()[max_z_layer] - m_gcode_viewer.get_max_print_height() >= 1e-6);
else if (warning == EWarning::ToolpathOutside) { // check if max x,y coords exceed bed area
show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed() &&
(m_gcode_viewer.get_max_print_height() -m_gcode_viewer.get_layers_zs()[max_z_layer] >= 1e-6);
}
else if (warning == EWarning::GCodeConflict)
show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
}
}
}
@ -8887,12 +8954,17 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
enum ErrorType{
PLATER_WARNING,
PLATER_ERROR,
SLICING_SERIOUS_WARNING,
SLICING_ERROR
};
std::string text;
ErrorType error = ErrorType::PLATER_WARNING;
const ModelObject* conflictObj=nullptr;
switch (warning) {
case EWarning::GCodeConflict: {
static std::string prevConflictText;
text = prevConflictText;
error = ErrorType::SLICING_SERIOUS_WARNING;
if (!m_gcode_viewer.m_conflict_result) { break; }
std::string objName1 = m_gcode_viewer.m_conflict_result.value()._objName1;
std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2;
@ -8901,10 +8973,13 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
text = (boost::format(_u8L("Conflicts of gcode paths have been found at layer %d, z = %.2lf mm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
height % objName1 % objName2)
.str();
error = ErrorType::SLICING_ERROR;
prevConflictText = text;
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(m_gcode_viewer.m_conflict_result.value()._obj2);
conflictObj = obj2->model_object();
break;
}
case EWarning::ObjectOutside: text = _u8L("An object is layed over the boundary of plate."); break;
case EWarning::ToolHeightOutside: text = _u8L("A G-code path goes beyond the max print height."); error = ErrorType::SLICING_ERROR; break;
case EWarning::ToolpathOutside: text = _u8L("A G-code path goes beyond the boundary of plate."); error = ErrorType::SLICING_ERROR; break;
// BBS: remove _u8L() for SLA
case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
@ -8920,25 +8995,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
return;
auto& notification_manager = *wxGetApp().plater()->get_notification_manager();
if (warning == EWarning::GCodeConflict && m_gcode_viewer.m_conflict_result) {
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(m_gcode_viewer.m_conflict_result.value()._obj2);
auto mo = obj2->model_object();
ObjectID id = mo->id();
auto action_fn = [id](wxEvtHandler *) {
auto &objects = wxGetApp().model().objects;
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
}
return false;
};
auto hypertext = _u8L("Jump to");
hypertext += std::string(" [") + mo->name + "]";
notification_manager.push_notification(NotificationType::PlaterError, NotificationManager::NotificationLevel::ErrorNotificationLevel, _u8L("ERROR:") + "\n" + text,
hypertext, action_fn);
return;
}
switch (error)
{
case PLATER_WARNING:
@ -8953,9 +9009,15 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
else
notification_manager.close_plater_error_notification(text);
break;
case SLICING_SERIOUS_WARNING:
if (state)
notification_manager.push_slicing_serious_warning_notification(text, {conflictObj});
else
notification_manager.close_slicing_serious_warning_notification(text);
break;
case SLICING_ERROR:
if (state)
notification_manager.push_slicing_error_notification(text, nullptr);
notification_manager.push_slicing_error_notification(text, {conflictObj});
else
notification_manager.close_slicing_error_notification(text);
break;

View file

@ -373,7 +373,8 @@ class GLCanvas3D
SlaSupportsOutside,
SomethingNotShown,
ObjectClashed,
GCodeConflict
GCodeConflict,
ToolHeightOutside
};
class RenderStats
@ -439,6 +440,8 @@ class GLCanvas3D
bool is_enabled() const { return m_enabled; }
void use(bool use) { m_volumes.set_slope_active(m_enabled ? use : false); }
bool is_used() const { return m_volumes.is_slope_active(); }
void globalUse(bool use) { m_volumes.set_slope_GlobalActive(m_enabled ? use : false); }
bool is_GlobalUsed() const { return m_volumes.is_slope_GlobalActive(); }
void set_normal_angle(float angle_in_deg) const {
m_volumes.set_slope_normal_z(-::cos(Geometry::deg2rad(90.0f - angle_in_deg)));
}
@ -515,6 +518,7 @@ private:
mutable IMToolbar m_sel_plate_toolbar;
mutable GLToolbar m_assemble_view_toolbar;
mutable IMReturnToolbar m_return_toolbar;
mutable float m_paint_toolbar_width;
//BBS: add canvas type for assemble view usage
ECanvasType m_canvas_type;
@ -619,6 +623,15 @@ private:
ArrangeSettings &get_arrange_settings() { return get_arrange_settings(this); }
//BBS:record key botton frequency
int auto_orient_count = 0;
int auto_arrange_count = 0;
int split_to_objects_count = 0;
int split_to_part_count = 0;
int custom_height_count = 0;
int custom_painting_count = 0;
public:
OrientSettings& get_orient_settings()
{
@ -707,6 +720,7 @@ public:
bool init();
void post_event(wxEvent &&event);
void reset_explosion_ratio() { m_explosion_ratio = 1.0; }
void on_change_color_mode(bool is_dark, bool reinit = true);
const bool get_dark_mode_status() { return m_is_dark; }
void set_as_dirty();
@ -716,6 +730,7 @@ public:
const GLVolumeCollection& get_volumes() const { return m_volumes; }
void reset_volumes();
ModelInstanceEPrintVolumeState check_volumes_outside_state() const;
bool is_all_plates_selected() { return m_sel_plate_toolbar.m_all_plates_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item->selected; }
const float get_scale() const;
//BBS
@ -813,6 +828,7 @@ public:
float get_main_toolbar_width() { return m_main_toolbar.get_width();}
float get_assemble_view_toolbar_width() { return m_assemble_view_toolbar.get_width(); }
float get_assemble_view_toolbar_height() { return m_assemble_view_toolbar.get_height(); }
float get_assembly_paint_toolbar_width() { return m_paint_toolbar_width; }
float get_separator_toolbar_width() { return m_separator_toolbar.get_width(); }
float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); }
float get_collapse_toolbar_width();
@ -992,6 +1008,9 @@ public:
bool are_labels_shown() const { return m_labels.is_shown(); }
void show_labels(bool show) { m_labels.show(show); }
bool is_overhang_shown() const { return m_slope.is_GlobalUsed(); }
void show_overhang(bool show) { m_slope.globalUse(show); }
bool is_using_slope() const { return m_slope.is_used(); }
void use_slope(bool use) { m_slope.use(use); }
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }
@ -1093,7 +1112,7 @@ private:
void _render_bed(bool bottom, bool show_axes);
void _render_bed_for_picking(bool bottom);
//BBS: add part plate related logic
void _render_platelist(bool bottom, bool only_current, bool only_body = false, int hover_id = -1) const;
void _render_platelist(bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false) const;
void _render_plates_for_picking() const;
//BBS: add outline drawing logic
void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline = true);

View file

@ -3545,6 +3545,18 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
}
}
void ObjectList::add_objects_to_list(std::vector<size_t> obj_idxs, bool call_selection_changed, bool notify_partplate, bool do_info_update)
{
#ifdef __WXOSX__
AssociateModel(nullptr);
#endif
for (const size_t idx : obj_idxs) {
add_object_to_list(idx, call_selection_changed, notify_partplate, do_info_update);
}
#ifdef __WXOSX__
AssociateModel(m_objects_model);
#endif
}
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, bool notify_partplate, bool do_info_update)

View file

@ -325,6 +325,8 @@ public:
void part_selection_changed();
// Add object to the list
// @param do_info_update: [Arthur] this function becomes slow as more functions are added, but I only need a fast version in FillBedJob, and I don't care about any info updates, so I pass a do_info_update param to skip all the uneccessary steps.
void add_objects_to_list(std::vector<size_t> obj_idxs, bool call_selection_changed = true, bool notify_partplate = true, bool do_info_update = true);
void add_object_to_list(size_t obj_idx, bool call_selection_changed = true, bool notify_partplate = true, bool do_info_update = true);
// Add object's volumes to the list
// Return selected items, if add_to_selection is defined

View file

@ -1297,7 +1297,7 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
unsigned int current_active_id = ImGui::GetActiveID();
Vec3d rotation = {Geometry::rad2deg(m_rotation(0)), Geometry::rad2deg(m_rotation(1)), Geometry::rad2deg(m_rotation(2))};
Vec3d rotation = {Geometry::rad2deg(m_buffered_rotation(0)), Geometry::rad2deg(m_buffered_rotation(1)), Geometry::rad2deg(m_buffered_rotation(2))};
char buf[3][64];
float buf_size[3];
float vec_max = 0, unit_size = 0;
@ -1450,6 +1450,10 @@ void GLGizmoAdvancedCut::render_cut_plane_input_window(float x, float y, float b
m_imgui->disabled_begin(has_connectors);
m_imgui->bbl_checkbox(_L("Cut to parts"), m_cut_to_parts);
if (m_cut_to_parts) {
m_keep_upper = true;
m_keep_lower = true;
}
m_imgui->disabled_end();
#if 0
@ -1585,7 +1589,9 @@ void GLGizmoAdvancedCut::render_connectors_input_window(float x, float y, float
if (render_combo(_u8L("Style"), connector_styles, m_connector_style))
apply_selected_connectors([this, &connectors](size_t idx) { connectors[idx].attribs.style = CutConnectorStyle(m_connector_style); });
m_imgui->disabled_end();
ImGuiWrapper::pop_combo_style();
ImGuiWrapper::push_combo_style(m_parent.get_scale());
if (render_combo(_u8L("Shape"), connector_shapes, m_connector_shape_id))
apply_selected_connectors([this, &connectors](size_t idx) { connectors[idx].attribs.shape = CutConnectorShape(m_connector_shape_id); });
ImGuiWrapper::pop_combo_style();
@ -1728,11 +1734,13 @@ bool GLGizmoAdvancedCut::render_combo(const std::string &label, const std::vecto
bool GLGizmoAdvancedCut::render_slider_double_input(const std::string &label, float &value_in, float &tolerance_in)
{
// -------- [ ] -------- [ ]
// slider_with + item_in_gap + first_input_width + item_out_gap + slider_with + item_in_gap + second_input_width
double slider_with = 0.24 * m_editing_window_width; // m_control_width * 0.35;
double item_in_gap = 0.01 * m_editing_window_width;
double item_out_gap = 0.02 * m_editing_window_width;
double first_input_width = 0.33 * m_editing_window_width;
double second_input_width = 0.15 * m_editing_window_width;
double item_out_gap = 0.01 * m_editing_window_width;
double first_input_width = 0.29 * m_editing_window_width;
double second_input_width = 0.29 * m_editing_window_width;
ImGui::AlignTextToFramePadding();
m_imgui->text(label);
@ -1770,18 +1778,21 @@ bool GLGizmoAdvancedCut::render_slider_double_input(const std::string &label, fl
ImGui::SameLine(left_width);
ImGui::PushItemWidth(slider_with);
float old_tolerance, tolerance = old_tolerance = tolerance_in * 100.f;
std::string format_t = tolerance_in < 0.f ? " " : "%.f %%";
float tolerance = tolerance_in;
if (m_imperial_units)
tolerance *= float(units_mm_to_in);
float old_tolerance = tolerance;
//std::string format_t = tolerance_in < 0.f ? " " : "%.f %%";
float min_tolerance = tolerance_in < 0.f ? UndefMinVal : 0.f;
m_imgui->bbl_slider_float_style(("##tolerance_" + label).c_str(), &tolerance, min_tolerance, 20.f, format_t.c_str(), 1.f, true, _L("Tolerance"));
m_imgui->bbl_slider_float_style(("##tolerance_" + label).c_str(), &tolerance, min_tolerance, 2.f, format.c_str(), 1.f, true, _L("Tolerance"));
left_width += (slider_with + item_in_gap);
ImGui::SameLine(left_width);
ImGui::PushItemWidth(second_input_width);
ImGui::BBLDragFloat(("##tolerance_input_" + label).c_str(), &tolerance, 0.05f, min_tolerance, 20.f, format_t.c_str());
ImGui::BBLDragFloat(("##tolerance_input_" + label).c_str(), &tolerance, 0.05f, min_tolerance, 2.f, format.c_str());
tolerance_in = tolerance * 0.01f;
tolerance_in = tolerance * float(m_imperial_units ? units_in_to_mm : 1.0);
return !is_approx(old_val, value) || !is_approx(old_tolerance, tolerance);
}

View file

@ -191,6 +191,9 @@ public:
virtual std::string get_tooltip() const { return ""; }
int get_count() { return ++count; }
std::string get_gizmo_name() { return on_get_name(); }
protected:
float last_input_window_width = 0;
virtual bool on_init() = 0;
@ -229,6 +232,7 @@ private:
// Flag for dirty visible state of Gizmo
// When True then need new rendering
bool m_dirty;
int count = 0;
};

View file

@ -186,7 +186,7 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
shader->set_uniform("volume_world_matrix", trafo_matrix);
shader->set_uniform("volume_mirrored", is_left_handed);
shader->set_uniform("slope.actived", m_parent.is_using_slope());
shader->set_uniform("slope.volume_world_normal_matrix", static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
shader->set_uniform("slope.normal_z", normal_z);
m_triangle_selectors[mesh_id]->render(m_imgui);
@ -290,7 +290,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::PushStyleColor(ImGuiCol_Button, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); // r, g, b, a
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0);
}

View file

@ -141,6 +141,7 @@ void GLGizmoFlatten::update_planes()
// Following constants are used for discarding too small polygons.
const float minimal_area = 5.f; // in square mm (world coordinates)
const float minimal_side = 1.f; // mm
const float minimal_angle = 1.f; // degree, initial value was 10, but cause bugs
// Now we'll go through all the facets and append Points of facets sharing the same normal.
// This part is still performed in mesh coordinate system.
@ -151,9 +152,9 @@ void GLGizmoFlatten::update_planes()
std::vector<bool> facet_visited(num_of_facets, false);
int facet_queue_cnt = 0;
const stl_normal* normal_ptr = nullptr;
int facet_idx = 0;
while (1) {
// Find next unvisited triangle:
int facet_idx = 0;
for (; facet_idx < num_of_facets; ++ facet_idx)
if (!facet_visited[facet_idx]) {
facet_queue[facet_queue_cnt ++] = facet_idx;
@ -235,7 +236,7 @@ void GLGizmoFlatten::update_planes()
discard = true;
else {
// We also check the inner angles and discard polygons with angles smaller than the following threshold
const double angle_threshold = ::cos(10.0 * (double)PI / 180.0);
const double angle_threshold = ::cos(minimal_angle * (double)PI / 180.0);
for (unsigned int i = 0; i < polygon.size(); ++i) {
const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1];
@ -250,7 +251,8 @@ void GLGizmoFlatten::update_planes()
}
if (discard) {
m_planes.erase(m_planes.begin() + (polygon_id--));
m_planes[polygon_id--] = std::move(m_planes.back());
m_planes.pop_back();
continue;
}

View file

@ -0,0 +1,466 @@
#include "GLGizmoMeshBoolean.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "libslic3r/MeshBoolean.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/NotificationManager.hpp"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <imgui/imgui_internal.h>
namespace Slic3r {
namespace GUI {
static const std::string warning_text = _u8L("Unable to perform boolean operation on selected parts");
GLGizmoMeshBoolean::GLGizmoMeshBoolean(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
{
}
GLGizmoMeshBoolean::~GLGizmoMeshBoolean()
{
}
bool GLGizmoMeshBoolean::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
{
if (action == SLAGizmoEventType::LeftDown) {
const ModelObject* mo = m_c->selection_info()->model_object();
if (mo == nullptr)
return true;
const ModelInstance* mi = mo->instances[m_parent.get_selection().get_instance_idx()];
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume* mv : mo->volumes) {
//if (mv->is_model_part()) {
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
//}
}
const Camera& camera = wxGetApp().plater()->get_camera();
Vec3f normal = Vec3f::Zero();
Vec3f hit = Vec3f::Zero();
size_t facet = 0;
Vec3f closest_hit = Vec3f::Zero();
Vec3f closest_normal = Vec3f::Zero();
double closest_hit_squared_distance = std::numeric_limits<double>::max();
int closest_hit_mesh_id = -1;
// Cast a ray on all meshes, pick the closest hit and save it for the respective mesh
for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) {
MeshRaycaster mesh_raycaster = MeshRaycaster(mo->volumes[mesh_id]->mesh());
if (mesh_raycaster.unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal,
m_c->object_clipper()->get_clipping_plane(), &facet)) {
// Is this hit the closest to the camera so far?
double hit_squared_distance = (camera.get_position() - trafo_matrices[mesh_id] * hit.cast<double>()).squaredNorm();
if (hit_squared_distance < closest_hit_squared_distance) {
closest_hit_squared_distance = hit_squared_distance;
closest_hit_mesh_id = mesh_id;
closest_hit = hit;
closest_normal = normal;
}
}
}
if (closest_hit == Vec3f::Zero() && closest_normal == Vec3f::Zero())
return true;
if (get_selecting_state() == MeshBooleanSelectingState::SelectTool) {
m_tool.trafo = trafo_matrices[closest_hit_mesh_id];
m_tool.volume_idx = closest_hit_mesh_id;
set_tool_volume(mo->volumes[closest_hit_mesh_id]);
return true;
}
if (get_selecting_state() == MeshBooleanSelectingState::SelectSource) {
m_src.trafo = trafo_matrices[closest_hit_mesh_id];
m_src.volume_idx = closest_hit_mesh_id;
set_src_volume(mo->volumes[closest_hit_mesh_id]);
m_selecting_state = MeshBooleanSelectingState::SelectTool;
return true;
}
}
return true;
}
bool GLGizmoMeshBoolean::on_init()
{
m_shortcut_key = WXK_CONTROL_B;
return true;
}
std::string GLGizmoMeshBoolean::on_get_name() const
{
return _u8L("Mesh Boolean");
}
bool GLGizmoMeshBoolean::on_is_activable() const
{
return m_parent.get_selection().is_single_full_instance() && m_parent.get_selection().get_volume_idxs().size() > 1;
}
void GLGizmoMeshBoolean::on_render()
{
if (m_parent.get_selection().get_object_idx() < 0)
return;
static ModelObject* last_mo = nullptr;
ModelObject* curr_mo = m_parent.get_selection().get_model()->objects[m_parent.get_selection().get_object_idx()];
if (last_mo != curr_mo) {
last_mo = curr_mo;
m_src.reset();
m_tool.reset();
m_operation_mode = MeshBooleanOperation::Union;
m_selecting_state = MeshBooleanSelectingState::SelectSource;
return;
}
BoundingBoxf3 src_bb;
BoundingBoxf3 tool_bb;
const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[m_parent.get_selection().get_instance_idx()];
const Selection& selection = m_parent.get_selection();
const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int i : idxs) {
const GLVolume* volume = selection.get_volume(i);
if(volume->volume_idx() == m_src.volume_idx) {
src_bb = volume->transformed_convex_hull_bounding_box();
}
if (volume->volume_idx() == m_tool.volume_idx) {
tool_bb = volume->transformed_convex_hull_bounding_box();
}
}
float src_color[3] = { 1.0f, 1.0f, 1.0f };
float tool_color[3] = { 0.0f, 174.0f / 255.0f, 66.0f / 255.0f };
m_parent.get_selection().render_bounding_box(src_bb, src_color, m_parent.get_scale());
m_parent.get_selection().render_bounding_box(tool_bb, tool_color, m_parent.get_scale());
}
void GLGizmoMeshBoolean::on_set_state()
{
if (m_state == EState::On) {
m_src.reset();
m_tool.reset();
bool m_diff_delete_input = false;
bool m_inter_delete_input = false;
m_operation_mode = MeshBooleanOperation::Union;
m_selecting_state = MeshBooleanSelectingState::SelectSource;
}
else if (m_state == EState::Off) {
m_src.reset();
m_tool.reset();
bool m_diff_delete_input = false;
bool m_inter_delete_input = false;
m_operation_mode = MeshBooleanOperation::Undef;
m_selecting_state = MeshBooleanSelectingState::Undef;
wxGetApp().notification_manager()->close_plater_warning_notification(warning_text);
}
}
CommonGizmosDataID GLGizmoMeshBoolean::on_get_requirements() const
{
return CommonGizmosDataID(
int(CommonGizmosDataID::SelectionInfo)
| int(CommonGizmosDataID::InstancesHider)
| int(CommonGizmosDataID::Raycaster)
| int(CommonGizmosDataID::ObjectClipper));
}
void GLGizmoMeshBoolean::on_render_input_window(float x, float y, float bottom_limit)
{
y = std::min(y, bottom_limit - ImGui::GetWindowHeight());
static float last_y = 0.0f;
static float last_w = 0.0f;
const float currt_scale = m_parent.get_scale();
ImGuiWrapper::push_toolbar_style(currt_scale);
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
GizmoImguiBegin("MeshBoolean", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
const int max_tab_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(_L("Union").c_str()).x,
std::max(ImGui::CalcTextSize(_L("Difference").c_str()).x, ImGui::CalcTextSize(_L("Intersection").c_str()).x));
const int max_cap_length = ImGui::GetStyle().WindowPadding.x + ImGui::GetStyle().ItemSpacing.x + std::max(ImGui::CalcTextSize(_L("Source Volume").c_str()).x, ImGui::CalcTextSize(_L("Tool Volume").c_str()).x);
const int select_btn_length = 2 * ImGui::GetStyle().FramePadding.x + std::max(ImGui::CalcTextSize(("1 " + _L("selected")).c_str()).x, ImGui::CalcTextSize(_L("Select").c_str()).x);
auto selectable = [this](const wxString& label, bool selected, const ImVec2& size_arg) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0,0 });
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImVec2 label_size = ImGui::CalcTextSize(label.c_str(), NULL, true);
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = ImGui::CalcItemSize(size_arg, label_size.x + ImGui::GetStyle().FramePadding.x * 2.0f, label_size.y + ImGui::GetStyle().FramePadding.y * 2.0f);
bool hovered = ImGui::IsMouseHoveringRect(pos, pos + size);
if (selected || hovered) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
}
else {
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f });
}
bool res = ImGui::Button(label.c_str(), size_arg);
if (selected || hovered) {
ImGui::PopStyleColor(4);
}
else {
ImGui::PopStyleColor(2);
}
ImGui::PopStyleVar(1);
return res;
};
auto operate_button = [this](const wxString &label, bool enable) {
if (!enable) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
if (m_is_dark_mode) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(39.0f / 255.0f, 39.0f / 255.0f, 39.0f / 255.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(108.0f / 255.0f, 108.0f / 255.0f, 108.0f / 255.0f, 1.0f));
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(230.0f / 255.0f, 230.0f / 255.0f, 230.0f / 255.0f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(163.0f / 255.0f, 163.0f / 255.0f, 163.0f / 255.0f, 1.0f));
}
}
bool res = m_imgui->button(label.c_str());
if (!enable) {
ImGui::PopItemFlag();
ImGui::PopStyleColor(2);
}
return res;
};
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
if (selectable(_L("Union").c_str(), m_operation_mode == MeshBooleanOperation::Union, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Union;
}
ImGui::SameLine(0, 0);
if (selectable(_L("Difference").c_str(), m_operation_mode == MeshBooleanOperation::Difference, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Difference;
}
ImGui::SameLine(0, 0);
if (selectable(_L("Intersection").c_str(), m_operation_mode == MeshBooleanOperation::Intersection, ImVec2(max_tab_length, 0.0f))) {
m_operation_mode = MeshBooleanOperation::Intersection;
}
ImGui::PopStyleVar();
ImGui::AlignTextToFramePadding();
std::string cap_str1 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 1") : _u8L("Subtract from");
m_imgui->text(cap_str1);
ImGui::SameLine(max_cap_length);
wxString select_src_str = m_src.mv ? "1 " + _L("selected") : _L("Select");
select_src_str << "##select_source_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_src_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectSource, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectSource;
ImGui::PopItemWidth();
if (m_src.mv) {
ImGui::SameLine();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_src.mv->name);
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_Border, { 0, 0, 0, 0 });
if (ImGui::Button((into_u8(ImGui::TextSearchCloseIcon) + "##src").c_str(), {18, 18}))
{
m_src.reset();
}
ImGui::PopStyleColor(5);
}
ImGui::AlignTextToFramePadding();
std::string cap_str2 = m_operation_mode != MeshBooleanOperation::Difference ? _u8L("Part 2") : _u8L("Subtract with");
m_imgui->text(cap_str2);
ImGui::SameLine(max_cap_length);
wxString select_tool_str = m_tool.mv ? "1 " + _L("selected") : _L("Select");
select_tool_str << "##select_tool_volume";
ImGui::PushItemWidth(select_btn_length);
if (selectable(select_tool_str.c_str(), m_selecting_state == MeshBooleanSelectingState::SelectTool, ImVec2(select_btn_length, 0)))
m_selecting_state = MeshBooleanSelectingState::SelectTool;
ImGui::PopItemWidth();
if (m_tool.mv) {
ImGui::SameLine();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_tool.mv->name);
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
ImGui::PushStyleColor(ImGuiCol_Border, { 0, 0, 0, 0 });
if (ImGui::Button((into_u8(ImGui::TextSearchCloseIcon) + "tool").c_str(), {18, 18}))
{
m_tool.reset();
}
ImGui::PopStyleColor(5);
}
bool enable_button = m_src.mv && m_tool.mv;
if (m_operation_mode == MeshBooleanOperation::Union)
{
if (operate_button(_L("Union") + "##btn", enable_button)) {
TriangleMesh temp_src_mesh = m_src.mv->mesh();
temp_src_mesh.transform(m_src.trafo);
TriangleMesh temp_tool_mesh = m_tool.mv->mesh();
temp_tool_mesh.transform(m_tool.trafo);
std::vector<TriangleMesh> temp_mesh_resuls;
Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "UNION");
if (temp_mesh_resuls.size() != 0) {
generate_new_volume(true, *temp_mesh_resuls.begin());
wxGetApp().notification_manager()->close_plater_warning_notification(warning_text);
}
else {
wxGetApp().notification_manager()->push_plater_warning_notification(warning_text);
}
}
}
else if (m_operation_mode == MeshBooleanOperation::Difference) {
m_imgui->bbl_checkbox(_L("Delete input"), m_diff_delete_input);
if (operate_button(_L("Difference") + "##btn", enable_button)) {
TriangleMesh temp_src_mesh = m_src.mv->mesh();
temp_src_mesh.transform(m_src.trafo);
TriangleMesh temp_tool_mesh = m_tool.mv->mesh();
temp_tool_mesh.transform(m_tool.trafo);
std::vector<TriangleMesh> temp_mesh_resuls;
Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "A_NOT_B");
if (temp_mesh_resuls.size() != 0) {
generate_new_volume(m_diff_delete_input, *temp_mesh_resuls.begin());
wxGetApp().notification_manager()->close_plater_warning_notification(warning_text);
}
else {
wxGetApp().notification_manager()->push_plater_warning_notification(warning_text);
}
}
}
else if (m_operation_mode == MeshBooleanOperation::Intersection){
m_imgui->bbl_checkbox(_L("Delete input"), m_inter_delete_input);
if (operate_button(_L("Intersection") + "##btn", enable_button)) {
TriangleMesh temp_src_mesh = m_src.mv->mesh();
temp_src_mesh.transform(m_src.trafo);
TriangleMesh temp_tool_mesh = m_tool.mv->mesh();
temp_tool_mesh.transform(m_tool.trafo);
std::vector<TriangleMesh> temp_mesh_resuls;
Slic3r::MeshBoolean::mcut::make_boolean(temp_src_mesh, temp_tool_mesh, temp_mesh_resuls, "INTERSECTION");
if (temp_mesh_resuls.size() != 0) {
generate_new_volume(m_inter_delete_input, *temp_mesh_resuls.begin());
wxGetApp().notification_manager()->close_plater_warning_notification(warning_text);
}
else {
wxGetApp().notification_manager()->push_plater_warning_notification(warning_text);
}
}
}
float win_w = ImGui::GetWindowWidth();
if (last_w != win_w || last_y != y) {
// ask canvas for another frame to render the window in the correct position
m_imgui->set_requires_extra_frame();
m_parent.set_as_dirty();
m_parent.request_extra_frame();
if (last_w != win_w)
last_w = win_w;
if (last_y != y)
last_y = y;
}
GizmoImguiEnd();
ImGuiWrapper::pop_toolbar_style();
}
void GLGizmoMeshBoolean::on_load(cereal::BinaryInputArchive &ar)
{
ar(m_enable, m_operation_mode, m_selecting_state, m_diff_delete_input, m_inter_delete_input, m_src, m_tool);
ModelObject *curr_model_object = m_c->selection_info() ? m_c->selection_info()->model_object() : nullptr;
m_src.mv = curr_model_object == nullptr ? nullptr : m_src.volume_idx < 0 ? nullptr : curr_model_object->volumes[m_src.volume_idx];
m_tool.mv = curr_model_object == nullptr ? nullptr : m_tool.volume_idx < 0 ? nullptr : curr_model_object->volumes[m_tool.volume_idx];
}
void GLGizmoMeshBoolean::on_save(cereal::BinaryOutputArchive &ar) const
{
ar(m_enable, m_operation_mode, m_selecting_state, m_diff_delete_input, m_inter_delete_input, m_src, m_tool);
}
void GLGizmoMeshBoolean::generate_new_volume(bool delete_input, const TriangleMesh& mesh_result) {
wxGetApp().plater()->take_snapshot("Mesh Boolean");
ModelObject* curr_model_object = m_c->selection_info()->model_object();
// generate new volume
ModelVolume* new_volume = curr_model_object->add_volume(std::move(mesh_result));
// assign to new_volume from old_volume
ModelVolume* old_volume = m_src.mv;
std::string suffix;
switch (m_operation_mode)
{
case MeshBooleanOperation::Union:
suffix = "union";
break;
case MeshBooleanOperation::Difference:
suffix = "difference";
break;
case MeshBooleanOperation::Intersection:
suffix = "intersection";
break;
}
new_volume->name = old_volume->name + " - " + suffix;
new_volume->set_new_unique_id();
new_volume->config.apply(old_volume->config);
new_volume->set_type(old_volume->type());
new_volume->set_material_id(old_volume->material_id());
new_volume->set_transformation(old_volume->get_transformation());
//Vec3d translate_z = { 0,0, (new_volume->source.mesh_offset - old_volume->source.mesh_offset).z() };
//new_volume->translate(new_volume->get_transformation().get_matrix(true) * translate_z);
//new_volume->supported_facets.assign(old_volume->supported_facets);
//new_volume->seam_facets.assign(old_volume->seam_facets);
//new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);
// delete old_volume
std::swap(curr_model_object->volumes[m_src.volume_idx], curr_model_object->volumes.back());
curr_model_object->delete_volume(curr_model_object->volumes.size() - 1);
if (delete_input) {
std::vector<ItemForDelete> items;
auto obj_idx = m_parent.get_selection().get_object_idx();
items.emplace_back(ItemType::itVolume, obj_idx, m_tool.volume_idx);
wxGetApp().obj_list()->delete_from_model_and_list(items);
}
//bool sinking = curr_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD;
//if (!sinking)
// curr_model_object->ensure_on_bed();
//curr_model_object->sort_volumes(true);
wxGetApp().plater()->update();
wxGetApp().obj_list()->select_item([this, new_volume]() {
wxDataViewItem sel_item;
wxDataViewItemArray items = wxGetApp().obj_list()->reorder_volumes_and_get_selection(m_parent.get_selection().get_object_idx(), [new_volume](const ModelVolume* volume) { return volume == new_volume; });
if (!items.IsEmpty())
sel_item = items.front();
return sel_item;
});
m_src.reset();
m_tool.reset();
m_selecting_state = MeshBooleanSelectingState::SelectSource;
}
}}

View file

@ -0,0 +1,88 @@
#ifndef slic3r_GLGizmoMeshBoolean_hpp_
#define slic3r_GLGizmoMeshBoolean_hpp_
#include "GLGizmoBase.hpp"
#include "GLGizmosCommon.hpp"
#include "libslic3r/Model.hpp"
namespace Slic3r {
namespace GUI {
enum class MeshBooleanSelectingState {
Undef,
SelectSource,
SelectTool,
};
enum class MeshBooleanOperation{
Undef,
Union,
Difference,
Intersection,
};
struct VolumeInfo {
ModelVolume* mv{ nullptr };
int volume_idx{-1};
Transform3d trafo;
void reset() {
mv = nullptr;
volume_idx = -1;
trafo = Transform3d::Identity();
};
template<class Archive>
void serialize(Archive& ar) {
ar(volume_idx, trafo);
}
};
class GLGizmoMeshBoolean : public GLGizmoBase
{
public:
GLGizmoMeshBoolean(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
~GLGizmoMeshBoolean();
void set_enable(bool enable) { m_enable = enable; }
bool get_enable() { return m_enable; }
MeshBooleanSelectingState get_selecting_state() { return m_selecting_state; }
void set_src_volume(ModelVolume* mv) {
m_src.mv = mv;
if (m_src.mv == m_tool.mv)
m_tool.reset();
}
void set_tool_volume(ModelVolume* mv) {
m_tool.mv = mv;
if (m_tool.mv == m_src.mv)
m_src.reset();
}
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_render() override;
virtual void on_render_for_picking() override {}
virtual void on_set_state() override;
virtual CommonGizmosDataID on_get_requirements() const override;
virtual void on_render_input_window(float x, float y, float bottom_limit);
void on_load(cereal::BinaryInputArchive &ar) override;
void on_save(cereal::BinaryOutputArchive &ar) const override;
private:
bool m_enable{ false };
MeshBooleanOperation m_operation_mode;
MeshBooleanSelectingState m_selecting_state;
bool m_diff_delete_input = false;
bool m_inter_delete_input = false;
VolumeInfo m_src;
VolumeInfo m_tool;
void generate_new_volume(bool delete_input, const TriangleMesh& mesh_result);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoMeshBoolean_hpp_

View file

@ -212,7 +212,14 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
++mesh_id;
const Transform3d trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix();
Transform3d trafo_matrix;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix();
trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
}
else {
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix();
}
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
if (is_left_handed)
@ -459,14 +466,14 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
if (m_selected_extruder_idx != extruder_idx) flags |= ImGuiColorEditFlags_NoBorder;
#ifdef __APPLE__
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0);
bool color_picked = ImGui::ColorButton(color_label.c_str(), color_vec, flags, button_size);
ImGui::PopStyleVar(2);
ImGui::PopStyleColor(1);
#else
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 2.0);
bool color_picked = ImGui::ColorButton(color_label.c_str(), color_vec, flags, button_size);
@ -512,7 +519,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::PushStyleColor(ImGuiCol_Button, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); // r, g, b, a
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0);
}

View file

@ -85,10 +85,15 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const
continue;
++mesh_id;
const Transform3d trafo_matrix =
mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() *
mv->get_matrix();
Transform3d trafo_matrix;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix();
trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
}
else {
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix();
}
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
if (is_left_handed)
@ -124,7 +129,16 @@ void GLGizmoPainterBase::render_cursor() const
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume* mv : mo->volumes) {
if (mv->is_model_part())
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
{
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
Transform3d temp = mi->get_assemble_transformation().get_matrix() * mv->get_matrix();
temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
trafo_matrices.emplace_back(temp);
}
else {
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
}
}
}
// Raycast and return if there's no hit.
update_raycast_cache(m_parent.get_local_mouse_position(), camera, trafo_matrices);
@ -230,17 +244,35 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co
const BoundingBoxf3 box = bounding_box();
Vec3d hit_world = trafo * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2));
float max_z = (float)box.max.z();
float min_z = (float)box.min.z();
float cursor_z = std::clamp((float)hit_world.z(), 0.f, max_z);
std::array<float, 2> zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, 0.f, max_z) };
for (int i = 0; i < zs.size(); i++) {
update_contours(zs[i], max_z);
float cursor_z = std::clamp((float)hit_world.z(), min_z, max_z);
std::array<float, 2> zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, min_z, max_z) };
const Selection& selection = m_parent.get_selection();
const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()];
const ModelInstance* mi = model_object->instances[selection.get_instance_idx()];
for (const ModelVolume* mv : model_object->volumes) {
TriangleMesh vol_mesh = mv->mesh();
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
Transform3d temp = mi->get_assemble_transformation().get_matrix() * mv->get_matrix();
temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
vol_mesh.transform(temp);
}
else {
vol_mesh.transform(mi->get_transformation().get_matrix() * mv->get_matrix());
}
for (int i = 0; i < zs.size(); i++) {
update_contours(vol_mesh, zs[i], max_z, min_z);
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z()));
glsafe(::glLineWidth(2.0f));
m_cut_contours.contours.render();
glsafe(::glPopMatrix());
}
glsafe(::glPushMatrix());
glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z()));
glsafe(::glLineWidth(2.0f));
m_cut_contours.contours.render();
glsafe(::glPopMatrix());
}
}
@ -257,7 +289,7 @@ BoundingBoxf3 GLGizmoPainterBase::bounding_box() const
return ret;
}
void GLGizmoPainterBase::update_contours(float cursor_z, float max_z) const
void GLGizmoPainterBase::update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const
{
const Selection& selection = m_parent.get_selection();
const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin());
@ -266,33 +298,32 @@ void GLGizmoPainterBase::update_contours(float cursor_z, float max_z) const
const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()];
const int instance_idx = selection.get_instance_idx();
if (0.0 < cursor_z && cursor_z < max_z) {
if (m_cut_contours.cut_z != cursor_z || m_cut_contours.object_id != model_object->id() || m_cut_contours.instance_idx != instance_idx) {
m_cut_contours.cut_z = cursor_z;
if (min_z < cursor_z && cursor_z < max_z) {
if (m_cut_contours.cut_z != cursor_z || m_cut_contours.object_id != model_object->id() || m_cut_contours.instance_idx != instance_idx) {
m_cut_contours.cut_z = cursor_z;
if (m_cut_contours.object_id != model_object->id())
m_cut_contours.mesh = model_object->raw_mesh();
m_cut_contours.mesh = vol_mesh;
m_cut_contours.position = box.center();
m_cut_contours.shift = Vec3d::Zero();
m_cut_contours.object_id = model_object->id();
m_cut_contours.instance_idx = instance_idx;
m_cut_contours.contours.reset();
m_cut_contours.position = box.center();
m_cut_contours.shift = Vec3d::Zero();
m_cut_contours.object_id = model_object->id();
m_cut_contours.instance_idx = instance_idx;
m_cut_contours.contours.reset();
MeshSlicingParams slicing_params;
slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix();
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params);
if (!polys.empty()) {
m_cut_contours.contours.init_from(polys, static_cast<float>(cursor_z));
m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f });
MeshSlicingParams slicing_params;
slicing_params.trafo = Transform3d::Identity().matrix();
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params);
if (!polys.empty()) {
m_cut_contours.contours.init_from(polys, static_cast<float>(cursor_z));
m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f });
}
}
else if (box.center() != m_cut_contours.position) {
m_cut_contours.shift = box.center() - m_cut_contours.position;
}
}
else if (box.center() != m_cut_contours.position) {
m_cut_contours.shift = box.center() - m_cut_contours.position;
}
}
else
m_cut_contours.contours.reset();
else
m_cut_contours.contours.reset();
}
bool GLGizmoPainterBase::is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const
@ -451,8 +482,12 @@ std::vector<GLGizmoPainterBase::ProjectedHeightRange> GLGizmoPainterBase::get_pr
const Selection& selection = m_parent.get_selection();
const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
for (int mesh_idx = 0; mesh_idx < part_volumes.size(); mesh_idx++) {
if (mesh_idx == m_rr.mesh_id)
@ -518,8 +553,12 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true);
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
const Transform3d trafo_matrix_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true) :
mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true);
const Transform3d trafo_matrix = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix() :
mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle,
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data();
@ -581,8 +620,12 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
std::vector<const ModelVolume*> part_volumes;
// Precalculate transformations of individual meshes.
@ -590,7 +633,14 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
std::vector<Transform3d> trafo_matrices_not_translate;
for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) {
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
Transform3d temp = instance_trafo * mv->get_matrix();
temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
trafo_matrices.emplace_back(temp);
}
else {
trafo_matrices.emplace_back(instance_trafo* mv->get_matrix());
}
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
part_volumes.push_back(mv);
}
@ -713,15 +763,26 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
const Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true);
const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix() :
mi->get_transformation().get_matrix();
const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
mi->get_assemble_transformation().get_matrix(true) :
mi->get_transformation().get_matrix(true);
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
std::vector<Transform3d> trafo_matrices_not_translate;
for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) {
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
Transform3d temp = instance_trafo * mv->get_matrix();
temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
trafo_matrices.emplace_back(temp);
}
else {
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
}
trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
}
@ -811,7 +872,8 @@ void GLGizmoPainterBase::update_raycast_cache(const Vec2d& mouse_position,
hit,
normal,
m_c->object_clipper()->get_clipping_plane(),
&facet))
&facet,
m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView))
{
// In case this hit is clipped, skip it.
if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id]))

View file

@ -368,7 +368,7 @@ private:
mutable CutContours m_cut_contours;
BoundingBoxf3 bounding_box() const;
void update_contours(float cursor_z, float max_z) const;
void update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const;
protected:
void on_set_state() override;

View file

@ -241,7 +241,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
ImGui::PushStyleColor(ImGuiCol_Button, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f)); // r, g, b, a
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_is_dark_mode ? ImVec4(43 / 255.0f, 64 / 255.0f, 54 / 255.0f, 1.00f) : ImVec4(0.86f, 0.99f, 0.91f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0);
}

View file

@ -273,8 +273,8 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.81f, 0.81f, 0.81f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.81f, 0.81f, 0.81f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.81f, 0.81f, 0.81f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
if (m_imgui->bbl_sliderin("##ReductionLevel", &reduction, 0, 4, reduce_captions[reduction].c_str())) {
if (reduction < 0) reduction = 0;

View file

@ -26,6 +26,7 @@
namespace Slic3r {
namespace GUI {
static const double PI = 3.141592653589793238;
static const wxColour FONT_TEXTURE_BG = wxColour(0, 0, 0, 0);
static const wxColour FONT_TEXTURE_FG = *wxWHITE;
static const int FONT_SIZE = 12;
@ -560,7 +561,7 @@ void GLGizmoText::push_button_style(bool pressed) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(43 / 255.f, 64 / 255.f, 54 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 150 / 255.f, 136 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 174 / 255.f, 66 / 255.f, 1.f));
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(45.f / 255.f, 45.f / 255.f, 49.f / 255.f, 1.f));
@ -574,7 +575,7 @@ void GLGizmoText::push_button_style(bool pressed) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(219 / 255.f, 253 / 255.f, 231 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 150 / 255.f, 136 / 255.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.f, 174 / 255.f, 66 / 255.f, 1.f));
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.f, 1.f, 1.f, 1.f));
@ -595,10 +596,10 @@ void GLGizmoText::push_combo_style(const float scale) {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG_DARK);
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.59f, 0.53f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.59f, 0.53f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG_DARK);
ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f });
}
@ -606,10 +607,10 @@ void GLGizmoText::push_combo_style(const float scale) {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.59f, 0.53f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.59f, 0.53f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.59f, 0.53f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f });
}
@ -1071,6 +1072,11 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
Vec3d rotation_axis;
Matrix3d rotation_matrix;
Geometry::rotation_from_two_vectors(m_cut_plane_dir, Vec3d::UnitZ(), rotation_axis, phi, &rotation_matrix);
if (abs(phi - PI) < 1e-6) {
Transform3d transform = Transform3d::Identity();
transform.rotate(Eigen::AngleAxisd(phi, m_mouse_normal_world));
rotation_matrix = transform.matrix().block<3, 3>(0, 0);
}
Transform3d transfo1;
transfo1.setIdentity();
@ -1312,7 +1318,7 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
}
TriangleMesh mesh = slice_meshs;
std::vector<double> mesh_values(m_position_points.size(), 1'000'000'000);
std::vector<double> mesh_values(m_position_points.size(), 1e9);
m_normal_points.resize(m_position_points.size());
auto point_in_triangle_delete_area = [](const Vec3d &point, const Vec3d &point0, const Vec3d &point1, const Vec3d &point2) {
Vec3d p0_p = point - point0;
@ -1383,7 +1389,6 @@ TriangleMesh GLGizmoText::get_text_mesh(const char* text_str, const Vec3d &posit
new_text_dir.normalize();
Geometry::rotation_from_two_vectors(old_text_dir, new_text_dir, rotation_axis, phi, &rotation_matrix);
static double const PI = 3.141592653589793238;
if (abs(phi - PI) < EPSILON)
rotation_axis = normal;
@ -1466,6 +1471,9 @@ void GLGizmoText::generate_text_volume(bool is_temp)
mesh.merge(sub_mesh);
}
if (mesh.empty())
return;
Plater *plater = wxGetApp().plater();
if (!plater)
return;

View file

@ -145,6 +145,11 @@ void InstancesHider::on_update()
const ModelObject* mo = get_pool()->selection_info()->model_object();
int active_inst = get_pool()->selection_info()->get_active_instance();
GLCanvas3D* canvas = get_pool()->get_canvas();
double z_min;
if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView)
z_min = std::numeric_limits<double>::max();
else
z_min = -SINKING_Z_THRESHOLD;
if (mo && active_inst != -1) {
canvas->toggle_model_objects_visibility(false);
@ -152,7 +157,7 @@ void InstancesHider::on_update()
canvas->toggle_sla_auxiliaries_visibility(m_show_supports, mo, active_inst);
canvas->set_use_clipping_planes(true);
// Some objects may be sinking, do not show whatever is below the bed.
canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), z_min));
canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), std::numeric_limits<double>::max()));
@ -164,7 +169,7 @@ void InstancesHider::on_update()
m_clippers.clear();
for (const TriangleMesh* mesh : meshes) {
m_clippers.emplace_back(new MeshClipper);
m_clippers.back()->set_plane(ClippingPlane(-Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
m_clippers.back()->set_plane(ClippingPlane(-Vec3d::UnitZ(), z_min));
m_clippers.back()->set_mesh(*mesh);
}
m_old_meshes = meshes;
@ -404,18 +409,30 @@ void ObjectClipper::render_cut() const
return;
const SelectionInfo* sel_info = get_pool()->selection_info();
const ModelObject* mo = sel_info->model_object();
Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation();
Geometry::Transformation inst_trafo;
bool is_assem_cnv = get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView;
inst_trafo = is_assem_cnv ?
mo->instances[sel_info->get_active_instance()]->get_assemble_transformation() :
mo->instances[sel_info->get_active_instance()]->get_transformation();
auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly();
size_t clipper_id = 0;
for (const ModelVolume* mv : mo->volumes) {
Geometry::Transformation vol_trafo = mv->get_transformation();
Geometry::Transformation trafo = inst_trafo * vol_trafo;
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
if (is_assem_cnv) {
trafo.set_offset(trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0) + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0));
}
else {
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
}
auto& clipper = m_clippers[clipper_id];
clipper->set_plane(*m_clp);
clipper->set_transformation(trafo);
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
if (is_assem_cnv)
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), std::numeric_limits<double>::max()));
else
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
glsafe(::glPushMatrix());
// BBS
glsafe(::glColor3f(0.25f, 0.25f, 0.25f));
@ -438,14 +455,27 @@ void ObjectClipper::set_position(double pos, bool keep_normal)
// camera_dir(2) = 0;
Vec3d normal = (keep_normal && m_clp) ? m_clp->get_normal() : /*-camera_dir;*/ -wxGetApp().plater()->get_camera().get_dir_forward();
const Vec3d& center = mo->instances[active_inst]->get_offset() + Vec3d(0., 0., z_shift);
Vec3d center;
if (get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
const SelectionInfo* sel_info = get_pool()->selection_info();
auto trafo = mo->instances[sel_info->get_active_instance()]->get_assemble_transformation();
auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly();
center = trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0);
}
else {
center = mo->instances[active_inst]->get_offset() + Vec3d(0., 0., z_shift);
}
float dist = normal.dot(center);
if (pos < 0.)
pos = m_clp_ratio;
m_clp_ratio = pos;
m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius) - m_clp_ratio * 2*m_active_inst_bb_radius)));
m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius) - m_clp_ratio * 2 * m_active_inst_bb_radius)));
get_pool()->get_canvas()->set_as_dirty();
}

View file

@ -23,6 +23,7 @@
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoText.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoMeshBoolean.hpp"
#include "libslic3r/format.hpp"
#include "libslic3r/Model.hpp"
@ -54,9 +55,16 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
{
std::vector<size_t> out;
for (size_t i=0; i<m_gizmos.size(); ++i)
if (m_gizmos[i]->is_selectable())
out.push_back(i);
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
for (size_t i = 0; i < m_gizmos.size(); ++i)
if (m_gizmos[i]->get_sprite_id() == (unsigned int)MmuSegmentation)
out.push_back(i);
}
else {
for (size_t i = 0; i < m_gizmos.size(); ++i)
if (m_gizmos[i]->is_selectable())
out.push_back(i);
}
return out;
}
@ -78,6 +86,8 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
#if BBS_TOOLBAR_ON_TOP
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();;
float top_x = std::max(m_parent.get_main_toolbar_width() + border, 0.5f * (cnv_w - width + m_parent.get_main_toolbar_width() + m_parent.get_collapse_toolbar_width() - m_parent.get_assemble_view_toolbar_width()) + border);
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView)
top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width());
float top_y = 0;
float stride_x = m_layout.scaled_stride_x();
@ -161,7 +171,11 @@ void GLGizmosManager::switch_gizmos_icon_filename()
case(EType::MmuSegmentation):
gizmo->set_icon_filename(m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg");
break;
case(EType::MeshBoolean):
gizmo->set_icon_filename(m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg");
break;
}
}
}
@ -191,6 +205,7 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, m_is_dark ? "toolbar_scale_dark.svg" : "toolbar_scale.svg", EType::Scale, &m_object_manipulation));
m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, m_is_dark ? "toolbar_flatten_dark.svg" : "toolbar_flatten.svg", EType::Flatten));
m_gizmos.emplace_back(new GLGizmoAdvancedCut(m_parent, m_is_dark ? "toolbar_cut_dark.svg" : "toolbar_cut.svg", EType::Cut));
m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg", EType::MeshBoolean));
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg", EType::FdmSupports));
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg", EType::Seam));
m_gizmos.emplace_back(new GLGizmoText(m_parent, m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg", EType::Text));
@ -629,6 +644,8 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
return dynamic_cast<GLGizmoText*>(m_gizmos[Text].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == Cut)
return dynamic_cast<GLGizmoAdvancedCut *>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else if (m_current == MeshBoolean)
return dynamic_cast<GLGizmoMeshBoolean*>(m_gizmos[MeshBoolean].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
else
return false;
}
@ -875,7 +892,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
if (evt.LeftDown() && (!control_down || grabber_contains_mouse())) {
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports ||
m_current == Seam || m_current == MmuSegmentation || m_current == Text || m_current == Cut)
m_current == Seam || m_current == MmuSegmentation || m_current == Text || m_current == Cut || m_current == MeshBoolean)
&& gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown()))
// the gizmo got the event and took some action, there is no need to do anything more
processed = true;
@ -965,6 +982,17 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
update_on_off_state(mouse_pos);
update_data();
m_parent.set_as_dirty();
try {
if ((int)m_hover >= 0 && (int)m_hover < m_gizmos.size()) {
std::string name = get_name_from_gizmo_etype(m_hover);
int count = m_gizmos[m_hover]->get_count();
NetworkAgent* agent = GUI::wxGetApp().getAgent();
if (agent) {
agent->track_update_property(name, std::to_string(count));
}
}
}
catch (...) {}
}
}
else if (evt.MiddleDown()) {
@ -1372,17 +1400,23 @@ void GLGizmosManager::do_render_overlay() const
float width = get_scaled_total_width();
float zoomed_border = m_layout.scaled_border() * inv_zoom;
//BBS: GUI refactor: GLToolbar&&Gizmo adjust
float zoomed_top_x;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
zoomed_top_x = 0.5f * m_parent.get_assembly_paint_toolbar_width() * inv_zoom;
}
else {
//BBS: GUI refactor: GLToolbar&&Gizmo adjust
#if BBS_TOOLBAR_ON_TOP
float main_toolbar_width = (float)m_parent.get_main_toolbar_width();
float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width();
float collapse_width = (float)m_parent.get_collapse_toolbar_width();
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
//float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom;
float main_toolbar_width = (float)m_parent.get_main_toolbar_width();
float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width();
float collapse_width = (float)m_parent.get_collapse_toolbar_width();
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();
//float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom;
float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom;
//float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom;
float zoomed_top_x = main_toolbar_left + (main_toolbar_width) *inv_zoom;
float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom;
//float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom;
zoomed_top_x = main_toolbar_left + (main_toolbar_width)*inv_zoom;
}
float zoomed_top_y = 0.5f * cnv_h * inv_zoom;
#else
//float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom;
@ -1653,5 +1687,28 @@ int GLGizmosManager::get_shortcut_key(GLGizmosManager::EType type) const
return m_gizmos[type]->get_shortcut_key();
}
std::string get_name_from_gizmo_etype(GLGizmosManager::EType type)
{
switch (type) {
case GLGizmosManager::EType::Move:
return "Move";
case GLGizmosManager::EType::Rotate:
return "Rotate";
case GLGizmosManager::EType::Scale:
return "Scale";
case GLGizmosManager::EType::Flatten:
return "Flatten";
case GLGizmosManager::EType::FdmSupports:
return "FdmSupports";
case GLGizmosManager::EType::Seam:
return "Seam";
case GLGizmosManager::EType::Text:
return "Text";
default:
return "";
}
return "";
}
} // namespace GUI
} // namespace Slic3r

View file

@ -70,6 +70,7 @@ public:
Scale,
Flatten,
Cut,
MeshBoolean,
FdmSupports,
Seam,
// BBS
@ -327,7 +328,7 @@ private:
bool grabber_contains_mouse() const;
};
std::string get_name_from_gizmo_etype(GLGizmosManager::EType type);
} // namespace GUI
} // namespace Slic3r

View file

@ -452,6 +452,7 @@ void GizmoObjectManipulation::set_uniform_scaling(const bool new_value)
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
// Is the angle close to a multiple of 90 degrees?
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Cannot apply scaling in the world coordinate system.
// BBS: remove tilt prompt dialog

View file

@ -241,7 +241,7 @@ void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3
bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane,
size_t* facet_idx) const
size_t* facet_idx, bool sinking_limit) const
{
Vec3d point;
Vec3d direction;
@ -258,8 +258,8 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d&
// Also, remove anything below the bed (sinking objects).
for (i=0; i<hits.size(); ++i) {
Vec3d transformed_hit = trafo * hits[i].position();
if (transformed_hit.z() >= SINKING_Z_THRESHOLD &&
(! clipping_plane || ! clipping_plane->is_point_clipped(transformed_hit)))
if (transformed_hit.z() >= (sinking_limit ? SINKING_Z_THRESHOLD : -std::numeric_limits<double>::max()) &&
(!clipping_plane || !clipping_plane->is_point_clipped(transformed_hit)))
break;
}

View file

@ -150,7 +150,8 @@ public:
Vec3f& position, // where to save the positibon of the hit (mesh coords)
Vec3f& normal, // normal of the triangle that was hit
const ClippingPlane* clipping_plane = nullptr, // clipping plane (if active)
size_t* facet_idx = nullptr // index of the facet hit
size_t* facet_idx = nullptr, // index of the facet hit
bool sinking_limit = true
) const;
// Given a vector of points in woorld coordinates, this returns vector

View file

@ -306,6 +306,96 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
if (fading_pop)
ImGui::PopStyleColor(3);
}
void NotificationManager::PopNotification::bbl_render_block_notification(GLCanvas3D &canvas, float initial_y, bool move_from_overlay, float overlay_width, float right_margin)
{
if (m_state == EState::Unknown)
init();
if (m_state == EState::Hidden) {
m_top_y = initial_y - GAP_WIDTH;
return;
}
if (m_state == EState::ClosePending || m_state == EState::Finished)
{
m_state = EState::Finished;
return;
}
Size cnv_size = canvas.get_canvas_size();
ImGuiWrapper& imgui = *wxGetApp().imgui();
float right_gap = right_margin + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
bool fading_pop = false;
if (m_line_height != ImGui::CalcTextSize("A").y)
init();
set_next_window_size(imgui);
// top y of window
m_top_y = initial_y + m_window_height;
ImVec2 win_pos(1.0f * (float) cnv_size.get_width() - right_gap, 1.0f * (float) cnv_size.get_height() - m_top_y);
imgui.set_next_window_pos(win_pos.x, win_pos.y, ImGuiCond_Always, 1.0f, 0.0f);
imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always);
// color change based on fading out
if (m_state == EState::FadingOut) {
push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), true, m_current_fade_opacity);
push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), true, m_current_fade_opacity);
push_style_color(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered), true, m_current_fade_opacity);
fading_pop = true;
}
bool bgrnd_color_pop = push_background_color();
// name of window indentifies window - has to be unique string
if (m_id == 0)
m_id = m_id_provider.allocate_id();
std::string name = "!!Ntfctn" + std::to_string(m_id);
use_bbl_theme();
if (m_data.level == NotificationLevel::SeriousWarningNotificationLevel)
{
push_style_color(ImGuiCol_Border, {245.f / 255.f, 155 / 255.f, 22 / 255.f, 1}, true, m_current_fade_opacity);
push_style_color(ImGuiCol_WindowBg, {245.f / 255.f, 155 / 255.f, 22 / 255.f, 1}, true, m_current_fade_opacity);
}
if (m_data.level == NotificationLevel::ErrorNotificationLevel) {
push_style_color(ImGuiCol_Border, {225.f / 255.f, 71 / 255.f, 71 / 255.f, 1}, true, m_current_fade_opacity);
push_style_color(ImGuiCol_WindowBg, {225.f / 255.f, 71 / 255.f, 71 / 255.f, 1}, true, m_current_fade_opacity);
}
push_style_color(ImGuiCol_Text, { 1,1,1,1 }, true, m_current_fade_opacity);
if (imgui.begin(name, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
ImVec2 win_size = ImGui::GetWindowSize();
ImVec2 win_pos = ImGui::GetWindowPos();
if (ImGui::IsMouseHoveringRect(win_pos, win_pos + win_size)) {
set_hovered();
}
//render left icon
bbl_render_block_notif_left_sign(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
bbl_render_block_notif_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
bbl_render_block_notif_buttons(imgui, win_size, win_pos);
//render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
//m_minimize_b_visible = false;
//if (m_multiline && m_lines_count > 3)
// render_minimize_button(imgui, win_pos.x, win_pos.y);
}
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
imgui.end();
ImGui::PopStyleColor(3);
restore_default_theme();
if (bgrnd_color_pop)
ImGui::PopStyleColor();
if (fading_pop)
ImGui::PopStyleColor(3);
}
bool NotificationManager::PopNotification::push_background_color()
{
if (m_is_gray) {
@ -345,6 +435,10 @@ void NotificationManager::PopNotification::count_spaces()
// m_left_indentation = picture_width + m_line_height / 2;
//}
m_window_width_offset = m_left_indentation + m_line_height * 3.f;
if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::SeriousWarningNotificationLevel) {
m_left_indentation = 32 + m_line_height;
m_window_width_offset = 90.f;
}
m_window_width = m_line_height * 25;
}
@ -464,6 +558,68 @@ void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& im
m_window_height += 1 * m_line_height; // top and bottom
}
void NotificationManager::PopNotification::bbl_render_block_notif_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
float x_offset = m_left_indentation;
int last_end = 0;
float starting_y = (m_lines_count == 2 ? win_size_y / 2 - m_line_height : (m_lines_count == 1 ? win_size_y / 2 - m_line_height / 2 : m_line_height / 2));
float shift_y = m_line_height;
std::string line;
for (size_t i = 0; i < (m_multiline ? m_endlines.size() : std::min(m_endlines.size(), (size_t)2)); i++) {
assert(m_endlines.size() > i && m_text1.size() >= m_endlines[i]);
line.clear();
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y);
if (m_endlines.size() > i && m_text1.size() >= m_endlines[i]) {
if (i == 1 && m_endlines.size() > 2 && !m_multiline) {
// second line with "more" hypertext
line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
while (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x) {
line = line.substr(0, line.length() - 1);
}
line += "..";
}
else {
// regural line
line = m_text1.substr(last_end, m_endlines[i] - last_end);
}
last_end = m_endlines[i];
if (m_text1.size() > m_endlines[i])
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
if (pos_start != string::npos && pos_end != string::npos && m_endlines[i] - line.length() >= pos_start && m_endlines[i] <= pos_end) {
push_style_color(ImGuiCol_Text, m_ErrorColor, m_state == EState::FadingOut, m_current_fade_opacity);
imgui.text(line.c_str());
ImGui::PopStyleColor();
}
else {
imgui.text(line.c_str());
}
}
}
//hyperlink text
if (!m_multiline && m_lines_count > 2) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + " ").c_str()).x, starting_y + shift_y, _u8L("More"), true);
}
else if (!m_hypertext.empty()) {
const ImVec2 button_size = {52, 28};
ImVec2 cursor_pos = { win_size_x - m_line_height * 6.0f, win_size_y / 2 - button_size.y / 2 };
ImGui::SetCursorPos(cursor_pos);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 2);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.f, 1.f, 1.f, 1.f));
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.f, 1.f, 1.f, 0.f));
//if (imgui.button(_L("Jump"), button_size.x, button_size.y)) { if (on_text_click()) { close(); } }
ImGui::PopStyleColor(2);
ImGui::PopStyleVar(2);
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext);
}
// text2 (text after hypertext) is not rendered for regular notifications
// its rendering is in HintNotification::render_text
}
void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
float x_offset = m_left_indentation;
@ -539,9 +695,18 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
ImGui::PopStyleColor(3);
//hover color
ImVec4 HyperColor = m_HyperTextColor;
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
HyperColor.y += 0.1f;
ImVec4 HyperColor = m_HyperTextColor;//ImVec4(150.f / 255.f, 100.f / 255.f, 0.f / 255.f, 1)
if (m_data.level == NotificationLevel::SeriousWarningNotificationLevel)
HyperColor = ImVec4(0.f, 0.f, 0.f, 0.4f);
if (m_data.level == NotificationLevel::ErrorNotificationLevel)
HyperColor = ImVec4(135.f / 255.f, 43 / 255.f, 43 / 255.f, 1);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
{
HyperColor.y += 0.1f;
if (m_data.level == NotificationLevel::SeriousWarningNotificationLevel || m_data.level == NotificationLevel::SeriousWarningNotificationLevel)
HyperColor.x += 0.2f;
}
//text
push_style_color(ImGuiCol_Text, HyperColor, m_state == EState::FadingOut, m_current_fade_opacity);
@ -607,6 +772,64 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
ImGui::PopStyleColor(5);
}
void NotificationManager::PopNotification::bbl_render_block_notif_buttons(ImGuiWrapper& imgui, ImVec2 win_size, ImVec2 win_pos)
{
// close button
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::wstring button_text;
button_text = ImGui::CloseBlockNotifButton;
ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str());
ImVec2 button_size(button_pic_size.x * 2.f, button_pic_size.y * 2.f);
ImVec2 cursor_pos = { win_size.x - m_line_height * 2.0f, win_size.y / 2 - button_size.y / 2 };
ImGui::SetCursorPos(cursor_pos);
//if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y + win_size.y / 2 - button_pic_size.y),
// ImVec2(win_pos.x - win_size.x / 20.f, win_pos.y + win_size.y / 2 + button_pic_size.y),
// true))
if(ImGui::IsMouseHoveringRect(win_pos + cursor_pos, win_pos + cursor_pos + button_size))
{
button_text = ImGui::CloseBlockNotifHoverButton;
}
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
close();
}
ImGui::PopStyleColor(5);
//// minimize button
//ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
//ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
//push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity);
//push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
//push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
////button - if part if treggered
//std::wstring button_text;
//button_text = m_is_dark ? ImGui::MinimalizeDarkButton : ImGui::MinimalizeButton;
//if (ImGui::IsMouseHoveringRect(ImVec2(win_pos_x - m_window_width / 10.f, win_pos_y + m_window_height - 2 * m_line_height + 1),
// ImVec2(win_pos_x, win_pos_y + m_window_height),
// true))
//{
// button_text = m_is_dark ? ImGui::MinimalizeHoverDarkButton : ImGui::MinimalizeHoverButton;
//}
//ImVec2 button_pic_size = ImGui::CalcTextSize(into_u8(button_text).c_str());
//ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
//ImGui::SetCursorPosX(m_window_width - m_line_height * 1.8f);
//ImGui::SetCursorPosY(m_window_height - button_size.y - 5);
//if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
//{
// m_multiline = false;
//}
//ImGui::PopStyleColor(5);
//m_minimize_b_visible = true;
}
//void NotificationManager::PopNotification::render_multiline(ImGuiWrapper &imgui, const float win_pos_x, const float win_pos_y)
//{
// if (m_data.type == NotificationType::BBLObjectInfo)
@ -615,6 +838,19 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
// }
//}
void NotificationManager::PopNotification::bbl_render_block_notif_left_sign(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
auto window = ImGui::GetCurrentWindow();
//window->DrawList->AddImage(user_texture_id, bb.Min + padding + margin, bb.Max - padding - margin, uv0, uv1, ImGui::GetColorU32(tint_col));
std::wstring text;
text = ImGui::BlockNotifErrorIcon;
ImGui::SetCursorPosX(m_line_height / 3);
ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
imgui.text(text.c_str());
}
void NotificationManager::PopNotification::bbl_render_left_sign(ImGuiWrapper &imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImDrawList *draw_list = ImGui::GetWindowDrawList();
@ -1630,19 +1866,39 @@ void NotificationManager::push_validate_error_notification(StringObjectException
set_slicing_progress_hidden();
}
void NotificationManager::push_slicing_error_notification(const std::string &text, ModelObject const *obj)
void NotificationManager::push_slicing_error_notification(const std::string &text, std::vector<ModelObject const *> objs)
{
auto callback = obj ? [id = obj->id()](wxEvtHandler *) {
std::vector<ObjectID> ids;
for (auto optr : objs) {
if (optr)
ids.push_back(optr->id());
}
auto callback = !objs.empty() ? [ids](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) {
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({*iter, nullptr}); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
} : std::function<bool(wxEvtHandler *)>();
auto link = callback ? _u8L("Jump to") : "";
if (obj) link += std::string(" [") + obj->name + "]";
if (!objs.empty()) {
link += " [";
for (auto obj : objs) {
if (obj)
link += obj->name + ", ";
}
if (!objs.empty()) {
link.pop_back();
link.pop_back();
}
link += "] ";
}
set_all_slicing_errors_gray(false);
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text, link, callback }, 0);
set_slicing_progress_hidden();
@ -1653,8 +1909,8 @@ void NotificationManager::push_slicing_warning_notification(const std::string& t
auto & objects = wxGetApp().model().objects;
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) {
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
}
return false;
} : std::function<bool(wxEvtHandler *)>();
@ -1869,6 +2125,53 @@ void NotificationManager::upload_job_notification_show_error(int id, const std::
}
}
void NotificationManager::push_slicing_serious_warning_notification(const std::string &text, std::vector<ModelObject const *> objs)
{
std::vector<ObjectID> ids;
for (auto optr : objs) {
if (optr) ids.push_back(optr->id());
}
auto callback = !objs.empty() ?
[ids](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({*iter, nullptr}); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
} :
std::function<bool(wxEvtHandler *)>();
auto link = callback ? _u8L("Jump to") : "";
if (!objs.empty()) {
link += " [";
for (auto obj : objs) {
if (obj) link += obj->name + ", ";
}
if (!objs.empty()) {
link.pop_back();
link.pop_back();
}
link += "] ";
}
set_all_slicing_warnings_gray(false);
push_notification_data({NotificationType::SlicingSeriousWarning, NotificationLevel::SeriousWarningNotificationLevel, 0, _u8L("Serious warning:") + "\n" + text, link,
callback},
0);
set_slicing_progress_hidden();
}
void NotificationManager::close_slicing_serious_warning_notification(const std::string &text)
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingSeriousWarning && notification->compare_text(_u8L("Serious warning:") + "\n" + text)) { notification->close(); }
}
}
void NotificationManager::init_slicing_progress_notification(std::function<bool()> cancel_callback)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
@ -2114,12 +2417,13 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
if (m_initialized) { // ignore update action - it cant be initialized if canvas and imgui context is not ready
if (notification->get_type() == NotificationType::SlicingWarning) {
m_pop_notifications.back()->append(notification->get_data().ori_text);
}
else
m_pop_notifications.back()->update(notification->get_data());
} else {
m_pop_notifications.back()->update(notification->get_data());
}
}
} else {
m_pop_notifications.emplace_back(std::move(notification));
retval = true;
}
if (!m_initialized)
@ -2129,7 +2433,10 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
return retval;
}
void NotificationManager::push_delayed_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, std::function<bool(void)> condition_callback, int64_t initial_delay, int64_t delay_interval)
void NotificationManager::push_delayed_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification,
std::function<bool(void)> condition_callback,
int64_t initial_delay,
int64_t delay_interval)
{
if (initial_delay == 0 && condition_callback()) {
if( push_notification_data(std::move(notification), 0))
@ -2155,13 +2462,20 @@ void NotificationManager::render_notifications(GLCanvas3D &canvas, float overlay
{
sort_notifications();
float last_y = bottom_margin * m_scale;
float bottom_up_last_y = bottom_margin * m_scale;
for (const auto& notification : m_pop_notifications) {
if (notification->get_state() != PopNotification::EState::Hidden) {
notification->render(canvas, last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
last_y = notification->get_top() + GAP_WIDTH;
if (notification->get_data().level == NotificationLevel::ErrorNotificationLevel || notification->get_data().level == NotificationLevel::SeriousWarningNotificationLevel) {
notification->bbl_render_block_notification(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
else {
if (notification->get_state() != PopNotification::EState::Hidden) {
notification->render(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
}
}
m_last_render = GLCanvas3D::timestamp_now();
@ -2295,6 +2609,8 @@ void NotificationManager::set_in_preview(bool preview)
notification->hide(preview);
if (m_in_preview && notification->get_type() == NotificationType::DidYouKnowHint)
notification->close();
if (notification->get_type() == NotificationType::ValidateWarning)
notification->hide(preview);
}
}

View file

@ -73,6 +73,8 @@ enum class NotificationType
// Slicing error produced by BackgroundSlicingProcess::validate() or by the BackgroundSlicingProcess background
// thread thowing a SlicingError exception.
SlicingError,
//Gcode conflict generates slicing severe warning
SlicingSeriousWarning,
// Slicing warnings, issued by the slicing process.
// Slicing warnings are registered for a particular Print milestone or a PrintObject and its milestone.
SlicingWarning,
@ -162,6 +164,8 @@ public:
ImportantNotificationLevel,
// Warning, no fade-out.
WarningNotificationLevel,
// Serious warning, bold reminder
SeriousWarningNotificationLevel,
// Error, no fade-out. Top most position.
ErrorNotificationLevel,
};
@ -191,8 +195,10 @@ public:
void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage);
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
void push_slicing_serious_warning_notification(const std::string &text, std::vector<ModelObject const *> objs);
void close_slicing_serious_warning_notification(const std::string &text);
// Creates Slicing Error notification with a custom text and no fade out.
void push_slicing_error_notification(const std::string &text, ModelObject const *obj);
void push_slicing_error_notification(const std::string &text, std::vector<ModelObject const *> objs);
// Creates Slicing Warning notification with a custom text and no fade out.
void push_slicing_warning_notification(const std::string &text, bool gray, ModelObject const *obj, ObjectID oid, int warning_step, int warning_msg_id);
// marks slicing errors as gray
@ -375,6 +381,7 @@ private:
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
virtual void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width, float right_margin);
virtual void bbl_render_block_notification(GLCanvas3D &canvas, float initial_y, bool move_from_overlay, float overlay_width, float right_margin);
// close will dissapear notification on next render
virtual void close() { m_state = EState::ClosePending; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);}
// data from newer notification of same type
@ -384,6 +391,8 @@ private:
void reinit() { m_state = EState::Unknown; }
// returns top after movement
float get_top() const { return m_top_y; }
// returns bottom after movement
float get_bottom() const { return m_bottom_y; }
//returns top in actual frame
float get_current_top() const { return m_top_y; }
const NotificationType get_type() const { return m_data.type; }
@ -420,6 +429,13 @@ private:
const float text_x, const float text_y,
const std::string text,
bool more = false);
virtual void bbl_render_block_notif_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
virtual void bbl_render_block_notif_buttons(ImGuiWrapper& imgui,
ImVec2 win_size,
ImVec2 win_pos);
virtual void bbl_render_block_notif_left_sign(ImGuiWrapper &imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y);
// Left sign could be error or warning sign
virtual void bbl_render_left_sign(ImGuiWrapper &imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y);
@ -511,6 +527,8 @@ private:
float m_window_width { 450.0f };
//Distance from bottom of notifications to top of this notification
float m_top_y { 0.0f };
//Distance from top of block notifications to bottom of this notification
float m_bottom_y { 0.0f };
// Height of text - Used as basic scaling unit!
float m_line_height;
// endlines for text1, hypertext excluded

View file

@ -38,7 +38,7 @@
#include "format.hpp"
#include "slic3r/GUI/GUI.hpp"
#include <imgui/imgui_internal.h>
#include <wx/dcgraph.h>
using boost::optional;
namespace fs = boost::filesystem;
@ -577,7 +577,7 @@ void PartPlate::render_logo_texture(GLTexture &logo_texture, const GeometryBuffe
}
}
void PartPlate::render_logo(bool bottom) const
void PartPlate::render_logo(bool bottom, bool render_cali) const
{
if (!m_partplate_list->render_bedtype_logo) {
// render third-party printer texture logo
@ -656,6 +656,7 @@ void PartPlate::render_logo(bool bottom) const
}
m_partplate_list->load_bedtype_textures();
m_partplate_list->load_cali_textures();
// btDefault should be skipped
auto curr_bed_type = get_bed_type();
@ -665,6 +666,7 @@ void PartPlate::render_logo(bool bottom) const
curr_bed_type = proj_cfg.opt_enum<BedType>(std::string("curr_bed_type"));
}
int bed_type_idx = (int)curr_bed_type;
// render bed textures
for (auto &part : m_partplate_list->bed_texture_info[bed_type_idx].parts) {
if (part.texture) {
if (part.buffer && part.buffer->get_vertices_count() > 0
@ -681,6 +683,24 @@ void PartPlate::render_logo(bool bottom) const
}
}
}
// render cali texture
if (render_cali) {
for (auto& part : m_partplate_list->cali_texture_info.parts) {
if (part.texture) {
if (part.buffer && part.buffer->get_vertices_count() > 0) {
if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
part.offset = Vec2d(m_origin.x(), m_origin.y());
part.update_buffer();
}
render_logo_texture(*(part.texture),
*(part.buffer),
bottom,
part.vbo_id);
}
}
}
}
}
void PartPlate::render_exclude_area(bool force_default_color) const {
@ -1311,6 +1331,14 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
}
// layer range
for (auto layer_range : mo->layer_config_ranges) {
if (layer_range.second.has("extruder")) {
if (auto id = layer_range.second.option("extruder")->getInt(); id > 0)
plate_extruders.push_back(id);
}
}
bool obj_support = false;
const ConfigOption* obj_support_opt = mo->config.option("enable_support");
const ConfigOption *obj_raft_opt = mo->config.option("raft_layers");
@ -1365,6 +1393,142 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
return plate_extruders;
}
std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, DynamicPrintConfig& full_config) const
{
std::vector<int> plate_extruders;
// if 3mf file
int glb_support_intf_extr = full_config.opt_int("support_interface_filament");
int glb_support_extr = full_config.opt_int("support_filament");
bool glb_support = full_config.opt_bool("enable_support");
glb_support |= full_config.opt_int("raft_layers") > 0;
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
{
int obj_id = it->first;
int instance_id = it->second;
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
{
ModelObject* object = m_model->objects[obj_id];
ModelInstance* instance = object->instances[instance_id];
if (!instance->printable)
continue;
for (ModelVolume* mv : object->volumes) {
std::vector<int> volume_extruders = mv->get_extruders();
plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
}
// layer range
for (auto layer_range : object->layer_config_ranges) {
if (layer_range.second.has("extruder")) {
if (auto id = layer_range.second.option("extruder")->getInt(); id > 0)
plate_extruders.push_back(id);
}
}
bool obj_support = false;
const ConfigOption* obj_support_opt = object->config.option("enable_support");
const ConfigOption *obj_raft_opt = object->config.option("raft_layers");
if (obj_support_opt != nullptr || obj_raft_opt != nullptr) {
if (obj_support_opt != nullptr)
obj_support = obj_support_opt->getBool();
if (obj_raft_opt != nullptr)
obj_support |= obj_raft_opt->getInt() > 0;
}
else
obj_support = glb_support;
if (!obj_support)
continue;
int obj_support_intf_extr = 0;
const ConfigOption* support_intf_extr_opt = object->config.option("support_interface_filament");
if (support_intf_extr_opt != nullptr)
obj_support_intf_extr = support_intf_extr_opt->getInt();
if (obj_support_intf_extr != 0)
plate_extruders.push_back(obj_support_intf_extr);
else if (glb_support_intf_extr != 0)
plate_extruders.push_back(glb_support_intf_extr);
int obj_support_extr = 0;
const ConfigOption* support_extr_opt = object->config.option("support_filament");
if (support_extr_opt != nullptr)
obj_support_extr = support_extr_opt->getInt();
if (obj_support_extr != 0)
plate_extruders.push_back(obj_support_extr);
else if (glb_support_extr != 0)
plate_extruders.push_back(glb_support_extr);
}
}
if (conside_custom_gcode) {
//BBS
int nums_extruders = 0;
if (const ConfigOptionStrings *color_option = dynamic_cast<const ConfigOptionStrings *>(full_config.option("filament_colour"))) {
nums_extruders = color_option->values.size();
if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
plate_extruders.push_back(item.extruder);
}
}
}
}
std::sort(plate_extruders.begin(), plate_extruders.end());
auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
return plate_extruders;
}
std::vector<int> PartPlate::get_extruders_without_support(bool conside_custom_gcode) const
{
std::vector<int> plate_extruders;
// if gcode.3mf file
if (m_model->objects.empty()) {
for (int i = 0; i < slice_filaments_info.size(); i++) {
plate_extruders.push_back(slice_filaments_info[i].id + 1);
}
return plate_extruders;
}
// if 3mf file
const DynamicPrintConfig& glb_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
if (!contain_instance_totally(obj_idx, 0))
continue;
ModelObject* mo = m_model->objects[obj_idx];
for (ModelVolume* mv : mo->volumes) {
std::vector<int> volume_extruders = mv->get_extruders();
plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
}
}
if (conside_custom_gcode) {
//BBS
int nums_extruders = 0;
if (const ConfigOptionStrings* color_option = dynamic_cast<const ConfigOptionStrings*>(wxGetApp().preset_bundle->project_config.option("filament_colour"))) {
nums_extruders = color_option->values.size();
if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
plate_extruders.push_back(item.extruder);
}
}
}
}
std::sort(plate_extruders.begin(), plate_extruders.end());
auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
return plate_extruders;
}
std::vector<int> PartPlate::get_used_extruders()
{
std::vector<int> used_extruders;
@ -1916,6 +2080,47 @@ void PartPlate::translate_all_instance(Vec3d position)
return;
}
void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, std::map<int, bool>& skip_objects)
{
std::set<std::pair<int, int>> old_obj_list = obj_to_instance_set;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id %1%, dup_count %2%") % m_plate_index % dup_count;
for (std::set<std::pair<int, int>>::iterator it = old_obj_list.begin(); it != old_obj_list.end(); ++it)
{
int obj_id = it->first;
int instance_id = it->second;
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
{
ModelObject* object = m_model->objects[obj_id];
ModelInstance* instance = object->instances[instance_id];
if (need_skip)
{
if (skip_objects.find(instance->loaded_id) != skip_objects.end())
{
instance->printable = false;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": skipped object, loaded_id %1%, name %2%, set to unprintable, no need to duplicate") % instance->loaded_id % object->name;
continue;
}
}
for (size_t index = 0; index < dup_count; index ++)
{
ModelObject* newObj = m_model->add_object(*object);
newObj->name = object->name +"_"+ std::to_string(index+1);
int new_obj_id = m_model->objects.size() - 1;
for ( size_t new_instance_id = 0; new_instance_id < object->instances.size(); new_instance_id++ )
{
obj_to_instance_set.emplace(std::pair(new_obj_id, new_instance_id));
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicate object into plate: index_pair [%1%,%2%], obj_id %3%") % new_obj_id % new_instance_id % newObj->id().id;
}
}
}
}
return;
}
//update instance exclude state
void PartPlate::update_instance_exclude_status(int obj_id, int instance_id, BoundingBoxf3* bounding_box)
@ -2012,6 +2217,28 @@ bool PartPlate::has_printable_instances()
return result;
}
bool PartPlate::is_all_instances_unprintable()
{
bool result = true;
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
int obj_id = it->first;
int instance_id = it->second;
if (obj_id >= m_model->objects.size()) continue;
ModelObject * object = m_model->objects[obj_id];
ModelInstance *instance = object->instances[instance_id];
if ((instance->printable)) {
result = false;
break;
}
}
return result;
}
//move instances to left or right PartPlate
void PartPlate::move_instances_to(PartPlate& left_plate, PartPlate& right_plate, BoundingBoxf3* bounding_box)
{
@ -2301,7 +2528,7 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const
return print_volume.intersects(bb);
}
void PartPlate::render(bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id)
void PartPlate::render(bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali)
{
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glEnable(GL_BLEND));
@ -2318,7 +2545,10 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color,
render_grid(bottom);
if (!bottom && m_selected && !force_background_color) {
render_logo(bottom);
if (m_partplate_list)
render_logo(bottom, m_partplate_list->render_cali_logo && render_cali);
else
render_logo(bottom);
}
render_height_limit(mode);
@ -2838,6 +3068,7 @@ void PartPlateList::release_icon_textures()
}
//reset
PartPlateList::is_load_bedtype_textures = false;
PartPlateList::is_load_cali_texture = false;
for (int i = 0; i < btCount; i++) {
for (auto& part: bed_texture_info[i].parts) {
if (part.texture) {
@ -3944,8 +4175,7 @@ bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& r
bool added = false;
std::vector<BoundingBoxf> nonprefered_regions;
nonprefered_regions.emplace_back(Vec2d{ 45,0 }, Vec2d{ 225,25 }); // extrusion calibration region
nonprefered_regions.emplace_back(Vec2d{ 25,0 }, Vec2d{ 50,60 }); // hand-eye calibration region
nonprefered_regions.emplace_back(Vec2d{ 18,0 }, Vec2d{ 240,15 }); // new extrusion & hand-eye calibration region
//has exclude areas
PartPlate* plate = m_plate_list[0];
@ -4102,7 +4332,7 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
/*rendering related functions*/
//render
void PartPlateList::render(bool bottom, bool only_current, bool only_body, int hover_id)
void PartPlateList::render(bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali)
{
const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
std::vector<PartPlate*>::iterator it = m_plate_list.begin();
@ -4127,15 +4357,15 @@ void PartPlateList::render(bool bottom, bool only_current, bool only_body, int h
if (current_index == m_current_plate) {
PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode;
if (plate_hover_index == current_index)
(*it)->render(bottom, only_body, false, height_mode, plate_hover_action);
(*it)->render(bottom, only_body, false, height_mode, plate_hover_action, render_cali);
else
(*it)->render(bottom, only_body, false, height_mode, -1);
(*it)->render(bottom, only_body, false, height_mode, -1, render_cali);
}
else {
if (plate_hover_index == current_index)
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action);
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali);
else
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1);
(*it)->render(bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali);
}
}
}
@ -4323,14 +4553,23 @@ bool PartPlateList::is_all_slice_results_valid() const
//check whether all plates's slice result valid for print
bool PartPlateList::is_all_slice_results_ready_for_print() const
{
for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i)
{
if (!m_plate_list[i]->is_slice_result_ready_for_print()
&& m_plate_list[i]->has_printable_instances()
)
return false;
}
return true;
bool res = false;
for (unsigned int i = 0; i < (unsigned int) m_plate_list.size(); ++i) {
if (!m_plate_list[i]->empty()) {
if (m_plate_list[i]->is_all_instances_unprintable()) {
continue;
}
if (!m_plate_list[i]->is_slice_result_ready_for_print()) {
return false;
}
}
if (m_plate_list[i]->is_slice_result_ready_for_print()) {
res = true;
}
}
return res;
}
@ -4564,6 +4803,7 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
plate_data_item->gcode_prediction = std::to_string(
(int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time);
plate_data_item->toolpath_outside = m_plate_list[i]->m_gcode_result->toolpath_outside;
plate_data_item->is_label_object_enabled = m_plate_list[i]->m_gcode_result->label_object_enabled;
Print *print = nullptr;
m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr);
if (print) {
@ -4612,8 +4852,8 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
{
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":plate index %1% seems invalid, skip it")% plate_data_list[i]->plate_index;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%, is_support_used %5%")
%i %plate_data_list[i]->gcode_file %plate_data_list[i]->is_sliced_valid %plate_data_list[i]->toolpath_outside %plate_data_list[i]->is_support_used;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%, is_support_used %5% is_label_object_enabled %6%")
%i %plate_data_list[i]->gcode_file %plate_data_list[i]->is_sliced_valid %plate_data_list[i]->toolpath_outside %plate_data_list[i]->is_support_used %plate_data_list[i]->is_label_object_enabled;
//load object and instance from 3mf
//just test for file correct or not, we will rebuild later
/*for (std::vector<std::pair<int, int>>::iterator it = plate_data_list[i]->objects_and_instances.begin(); it != plate_data_list[i]->objects_and_instances.end(); ++it)
@ -4634,6 +4874,7 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
}
ps.total_used_filament *= 1000; //koef
gcode_result->toolpath_outside = plate_data_list[i]->toolpath_outside;
gcode_result->label_object_enabled = plate_data_list[i]->is_label_object_enabled;
m_plate_list[index]->slice_filaments_info = plate_data_list[i]->slice_filaments_info;
gcode_result->warnings = plate_data_list[i]->warnings;
if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) {
@ -4722,6 +4963,7 @@ void PartPlateList::print() const
}
bool PartPlateList::is_load_bedtype_textures = false;
bool PartPlateList::is_load_cali_texture = false;
void PartPlateList::BedTextureInfo::TexturePart::update_buffer()
{
@ -4812,5 +5054,39 @@ void PartPlateList::load_bedtype_textures()
PartPlateList::is_load_bedtype_textures = true;
}
void PartPlateList::init_cali_texture_info()
{
BedTextureInfo::TexturePart cali_line(18, 2, 224, 16, "bbl_cali_lines.svg");
cali_texture_info.parts.push_back(cali_line);
for (int j = 0; j < cali_texture_info.parts.size(); j++) {
cali_texture_info.parts[j].update_buffer();
}
}
void PartPlateList::load_cali_textures()
{
if (PartPlateList::is_load_cali_texture) return;
init_cali_texture_info();
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048;
for (int i = 0; i < (unsigned int)btCount; ++i) {
for (int j = 0; j < cali_texture_info.parts.size(); j++) {
std::string filename = resources_dir() + "/images/" + cali_texture_info.parts[j].filename;
if (boost::filesystem::exists(filename)) {
PartPlateList::cali_texture_info.parts[j].texture = new GLTexture();
if (!PartPlateList::cali_texture_info.parts[j].texture->load_from_svg_file(filename, true, true, true, logo_tex_size)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load cali texture from %1% failed!") % filename;
}
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load cali texture from %1% failed!") % filename;
}
}
}
PartPlateList::is_load_cali_texture = true;
}
}//end namespace GUI
}//end namespace slic3r

View file

@ -170,10 +170,8 @@ private:
void calc_vertex_for_number(int index, bool one_number, GeometryBuffer &buffer);
void calc_vertex_for_icons(int index, GeometryBuffer &buffer);
void calc_vertex_for_icons_background(int icon_count, GeometryBuffer &buffer);
//void calc_vertex_for_name_tex(GeometryBuffer &buffer);
void render_background(bool force_default_color = false) const;
void render_logo(bool bottom) const;
void render_logo(bool bottom, bool render_cali = true) const;
void render_logo_texture(GLTexture& logo_texture, const GeometryBuffer& logo_buffer, bool bottom, unsigned int vbo_id) const;
void render_exclude_area(bool force_default_color) const;
//void render_background_for_picking(const float* render_color) const;
@ -288,6 +286,8 @@ public:
Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const double w, const double wipe_volume) const;
std::vector<int> get_extruders(bool conside_custom_gcode = false) const;
std::vector<int> get_extruders_under_cli(bool conside_custom_gcode, DynamicPrintConfig& full_config) const;
std::vector<int> get_extruders_without_support(bool conside_custom_gcode = false) const;
std::vector<int> get_used_extruders();
/* instance related operations*/
@ -315,6 +315,9 @@ public:
//translate instance on the plate
void translate_all_instance(Vec3d position);
//duplicate all instance for count
void duplicate_all_instance(unsigned int dup_count, bool need_skip, std::map<int, bool>& skip_objects);
//update instance exclude state
void update_instance_exclude_status(int obj_id, int instance_id, BoundingBoxf3* bounding_box = nullptr);
@ -328,6 +331,7 @@ public:
//whether it is has printable instances
bool has_printable_instances();
bool is_all_instances_unprintable();
//move instances to left or right PartPlate
void move_instances_to(PartPlate& left_plate, PartPlate& right_plate, BoundingBoxf3* bounding_box = nullptr);
@ -340,7 +344,7 @@ public:
bool contains(const BoundingBoxf3& bb) const;
bool intersects(const BoundingBoxf3& bb) const;
void render(bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1);
void render(bool bottom, bool only_body = false, bool force_background_color = false, HeightLimitMode mode = HEIGHT_LIMIT_NONE, int hover_id = -1, bool render_cali = false);
void render_for_picking() const { on_render_for_picking(); }
void set_selected();
void set_unselected();
@ -400,7 +404,7 @@ public:
{
bool result = m_slice_result_valid;
if (result)
result = m_gcode_result ? (!m_gcode_result->toolpath_outside && !m_gcode_result->conflict_result.has_value()) : false;
result = m_gcode_result ? (!m_gcode_result->toolpath_outside) : false;// && !m_gcode_result->conflict_result.has_value() gcode conflict can also print
return result;
}
@ -524,6 +528,7 @@ class PartPlateList : public ObjectBase
// set render option
bool render_bedtype_logo = true;
bool render_plate_settings = true;
bool render_cali_logo = true;
bool m_is_dark = false;
@ -587,6 +592,7 @@ public:
static const unsigned int MAX_PLATES_COUNT = MAX_PLATE_COUNT;
static GLTexture bed_textures[(unsigned int)btCount];
static bool is_load_bedtype_textures;
static bool is_load_cali_texture;
PartPlateList(int width, int depth, int height, Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
PartPlateList(Plater* platerObj, Model* modelObj, PrinterTechnology tech = ptFFF);
@ -732,9 +738,10 @@ public:
/*rendering related functions*/
void on_change_color_mode(bool is_dark) { m_is_dark = is_dark; }
void render(bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1);
void render(bool bottom, bool only_current = false, bool only_body = false, int hover_id = -1, bool render_cali = false);
void render_for_picking_pass();
void set_render_option(bool bedtype_texture, bool plate_settings);
void set_render_cali(bool value = true) { render_cali_logo = value; }
BoundingBoxf3& get_bounding_box() { return m_bounding_box; }
//int select_plate_by_hover_id(int hover_id);
int select_plate_by_obj(int obj_index, int instance_index);
@ -792,7 +799,12 @@ public:
void init_bed_type_info();
void load_bedtype_textures();
void show_cali_texture(bool show = true);
void init_cali_texture_info();
void load_cali_textures();
BedTextureInfo bed_texture_info[btCount];
BedTextureInfo cali_texture_info;
};
} // namespace GUI

View file

@ -60,6 +60,10 @@
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/ClipperUtils.hpp"
// For stl export
#include "libslic3r/CSGMesh/ModelToCSGMesh.hpp"
#include "libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp"
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
@ -169,6 +173,8 @@ wxDEFINE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent);
wxDEFINE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent);
//BBS: change light/dark mode
wxDEFINE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent);
//BBS: print
wxDEFINE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent);
bool Plater::has_illegal_filename_characters(const wxString& wxs_name)
@ -528,8 +534,8 @@ Sidebar::Sidebar(Plater *parent)
p->m_text_printer_settings = new Label(p->m_panel_printer_title, _L("Printer"), LB_PROPAGATE_MOUSE_EVENT);
p->m_printer_icon->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
auto wizard_t = new ConfigWizard(wxGetApp().mainframe);
wizard_t->run(ConfigWizard::RR_USER, ConfigWizard::SP_CUSTOM);
//auto wizard_t = new ConfigWizard(wxGetApp().mainframe);
//wizard_t->run(ConfigWizard::RR_USER, ConfigWizard::SP_CUSTOM);
});
@ -619,11 +625,8 @@ Sidebar::Sidebar(Plater *parent)
m_bed_type_list = new ComboBox(p->m_panel_printer_content, wxID_ANY, wxString(""), wxDefaultPosition, {-1, FromDIP(30)}, 0, nullptr, wxCB_READONLY);
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
if (bed_type_def && bed_type_def->enum_keys_map) {
for (auto item : *bed_type_def->enum_keys_map) {
if (item.first == "Default Plate")
continue;
m_bed_type_list->AppendString(_L(item.first));
for (auto item : bed_type_def->enum_labels) {
m_bed_type_list->AppendString(_L(item));
}
}
@ -1628,6 +1631,10 @@ bool Sidebar::show_object_list(bool show) const
{
if (!p->m_object_list->Show(show))
return false;
if (!show)
p->object_layers->Show(false);
else
p->m_object_list->part_selection_changed();
p->scrolled->Layout();
return true;
}
@ -1731,6 +1738,7 @@ struct Plater::priv
bool m_slice_all{false};
bool m_is_slicing {false};
bool m_is_publishing {false};
int m_is_RightClickInLeftUI{-1};
int m_cur_slice_plate;
//BBS: m_slice_all in .gcode.3mf file case, set true when slice all
bool m_slice_all_only_has_gcode{ false };
@ -1906,6 +1914,12 @@ struct Plater::priv
bool are_view3D_labels_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->are_labels_shown(); }
void show_view3D_labels(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_labels(show); }
bool is_view3D_overhang_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_overhang_shown(); }
void show_view3D_overhang(bool show)
{
if (current_panel == view3D) view3D->get_canvas3d()->show_overhang(show);
}
bool is_sidebar_collapsed() const { return sidebar->is_collapsed(); }
void collapse_sidebar(bool collapse);
@ -2115,6 +2129,7 @@ struct Plater::priv
//void show_action_buttons(const bool is_ready_to_slice) const;
bool show_publish_dlg(bool show = true);
void update_publish_dialog_status(wxString &msg, int percent = -1);
void on_action_print_plate_from_sdcard(SimpleEvent&);
// Set the bed shape to a single closed 2D polygon(array of two element arrays),
// triangulate the bed and store the triangles into m_bed.m_triangles,
@ -2227,6 +2242,9 @@ private:
std::vector<std::pair<Slic3r::PrintStateBase::Warning, size_t>> current_warnings;
bool show_warning_dialog { false };
//record print preset
void record_start_print_preset(std::string action);
};
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf)", std::regex::icase);
@ -2499,6 +2517,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
assemble_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
assemble_canvas->Bind(EVT_GLVIEWTOOLBAR_3D, [q](SimpleEvent&) { q->select_view_3D("3D"); });
assemble_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this);
assemble_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); });
assemble_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); });
}
if (wxGetApp().is_editor()) {
@ -2512,6 +2532,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
q->Bind(EVT_GLTOOLBAR_SLICE_PLATE, &priv::on_action_slice_plate, this);
q->Bind(EVT_GLTOOLBAR_SLICE_ALL, &priv::on_action_slice_all, this);
q->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this);
q->Bind(EVT_PRINT_FROM_SDCARD_VIEW, &priv::on_action_print_plate_from_sdcard, this);
q->Bind(EVT_GLTOOLBAR_SELECT_SLICED_PLATE, &priv::on_action_select_sliced_plate, this);
q->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
q->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this);
@ -3701,12 +3722,13 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
// update printable state for new volumes on canvas3D
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
Selection& selection = view3D->get_canvas3d()->get_selection();
selection.clear();
for (size_t idx : obj_idxs) {
selection.add_object((unsigned int)idx, false);
if (!load_config) {
Selection& selection = view3D->get_canvas3d()->get_selection();
selection.clear();
for (size_t idx : obj_idxs) {
selection.add_object((unsigned int)idx, false);
}
}
// BBS: update object list selection
this->sidebar->obj_list()->update_selections();
@ -3776,17 +3798,15 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
const double max_ratio = std::max(ratio(0), ratio(1));
if (max_ratio > 10000) {
MessageDialog dlg(q, _L("Your object appears to be too large, Do you want to scale it down to fit the heat bed automatically?"), _L("Object too large"),
wxICON_QUESTION | wxYES_NO);
wxICON_QUESTION | wxYES);
int answer = dlg.ShowModal();
if (answer == wxID_YES) {
// the size of the object is too big -> this could lead to overflow when moving to clipper coordinates,
// so scale down the mesh
object->scale_mesh_after_creation(1. / max_ratio);
object->origin_translation = Vec3d::Zero();
object->center_around_origin();
scaled_down = true;
break;
}
// the size of the object is too big -> this could lead to overflow when moving to clipper coordinates,
// so scale down the mesh
object->scale_mesh_after_creation(1. / max_ratio);
object->origin_translation = Vec3d::Zero();
object->center_around_origin();
scaled_down = true;
break;
}
else if (max_ratio > 10) {
MessageDialog dlg(q, _L("Your object appears to be too large, Do you want to scale it down to fit the heat bed automatically?"), _L("Object too large"),
@ -3836,8 +3856,14 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
for (auto& instance : new_instances) {
auto offset = instance->get_offset();
auto start_point = this->bed.build_volume().bounding_volume2d().center();
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({ start_point(0),start_point(1) });
Vec3d displacement = { empty_cell.x(),empty_cell.y(),offset(2)};
bool plate_empty = partplate_list.get_curr_plate()->empty();
Vec3d displacement;
if (plate_empty)
displacement = {start_point(0), start_point(1), offset(2)};
else {
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
displacement = {empty_cell.x(), empty_cell.y(), offset(2)};
}
instance->set_offset(displacement);
}
#endif
@ -3852,9 +3878,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
//}
notification_manager->close_notification_of_type(NotificationType::UpdatedItemsInfo);
for (const size_t idx : obj_idxs) {
wxGetApp().obj_list()->add_object_to_list(idx);
}
wxGetApp().obj_list()->add_objects_to_list(obj_idxs);
update();
// Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(),
@ -4166,6 +4190,7 @@ void Plater::priv::reset(bool apply_presets_change)
if (view3D->is_layers_editing_enabled())
view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
view3D->get_canvas3d()->reset_all_gizmos();
reset_gcode_toolpaths();
//BBS: update gcode to current partplate's
@ -4185,6 +4210,7 @@ void Plater::priv::reset(bool apply_presets_change)
// Stop and reset the Print content.
this->background_process.reset();
model.clear_objects();
assemble_view->get_canvas3d()->reset_explosion_ratio();
update();
//BBS
@ -4505,13 +4531,13 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
if (invalidated != Print::APPLY_STATUS_UNCHANGED && was_running && ! this->background_process.running() &&
(return_state & UPDATE_BACKGROUND_PROCESS_RESTART) == 0) {
// The background processing was killed and it will not be restarted.
// Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages.
SlicingProcessCompletedEvent evt(EVT_PROCESS_COMPLETED, 0,
SlicingProcessCompletedEvent::Cancelled, nullptr);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%, post an EVT_PROCESS_COMPLETED to main, status %2%")%__LINE__ %evt.status();
wxQueueEvent(q, evt.Clone());
}
// The background processing was killed and it will not be restarted.
// Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages.
SlicingProcessCompletedEvent evt(EVT_PROCESS_COMPLETED, 0,
SlicingProcessCompletedEvent::Cancelled, nullptr);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%, post an EVT_PROCESS_COMPLETED to main, status %2%")%__LINE__ %evt.status();
wxQueueEvent(q, evt.Clone());
}
if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
{
@ -4636,7 +4662,7 @@ void Plater::priv::export_gcode(fs::path output_path, bool output_path_on_remova
if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
return;
show_warning_dialog = false;
show_warning_dialog = true;
if (! output_path.empty()) {
background_process.schedule_export(output_path.string(), output_path_on_removable_media);
notification_manager->push_delayed_notification(NotificationType::ExportOngoing, []() {return true; }, 1000, 0);
@ -4668,7 +4694,7 @@ void Plater::priv::export_gcode(fs::path output_path, bool output_path_on_remova
if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
return;
show_warning_dialog = false;
show_warning_dialog = true;
if (! output_path.empty()) {
background_process.schedule_export(output_path.string(), output_path_on_removable_media);
notification_manager->push_delayed_notification(NotificationType::ExportOngoing, []() {return true; }, 1000, 0);
@ -5103,7 +5129,7 @@ void Plater::priv::reload_from_disk()
if (has_source && old_volume->source.object_idx < int(new_model.objects.size())) {
const ModelObject *obj = new_model.objects[old_volume->source.object_idx];
if (old_volume->source.volume_idx < int(obj->volumes.size())) {
if (obj->volumes[old_volume->source.volume_idx]->name == old_volume->name) {
if (obj->volumes[old_volume->source.volume_idx]->source.input_file == old_volume->source.input_file) {
new_volume_idx = old_volume->source.volume_idx;
new_object_idx = old_volume->source.object_idx;
match_found = true;
@ -5574,15 +5600,16 @@ void Plater::priv::on_select_bed_type(wxCommandEvent &evt)
{
ComboBox* combo = static_cast<ComboBox*>(evt.GetEventObject());
int selection = combo->GetSelection();
wxString bed_type_name = combo->GetString(selection);
std::string bed_type_name = print_config_def.get("curr_bed_type")->enum_values[selection];
PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
DynamicPrintConfig& proj_config = wxGetApp().preset_bundle->project_config;
const t_config_enum_values* keys_map = print_config_def.get("curr_bed_type")->enum_keys_map;
if (keys_map) {
BedType new_bed_type = btCount;
for (auto item : *keys_map) {
if (_L(item.first) == bed_type_name) {
if (item.first == bed_type_name) {
new_bed_type = (BedType)item.second;
break;
}
@ -5924,21 +5951,24 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
// This bool stops showing export finished notification even when process_completed_with_error is false
bool has_error = false;
if (evt.error()) {
std::pair<std::string, size_t> message = evt.format_error_message();
auto message = evt.format_error_message();
if (evt.critical_error()) {
if (q->m_tracking_popup_menu) {
// We don't want to pop-up a message box when tracking a pop-up menu.
// We postpone the error message instead.
q->m_tracking_popup_menu_error_message = message.first;
} else {
show_error(q, message.first, message.second != 0);
show_error(q, message.first, message.second.size() != 0 && message.second[0] != 0);
notification_manager->set_slicing_progress_hidden();
}
} else {
ModelObject const *model_object = nullptr;
const PrintObject *print_object = this->background_process.m_fff_print->get_object(ObjectID(message.second));
if (print_object) model_object = print_object->model_object();
notification_manager->push_slicing_error_notification(message.first, model_object);
std::vector<const ModelObject *> ptrs;
for (auto oid : message.second)
{
const PrintObject *print_object = this->background_process.m_fff_print->get_object(ObjectID(oid));
if (print_object) { ptrs.push_back(print_object->model_object()); }
}
notification_manager->push_slicing_error_notification(message.first, ptrs);
}
if (evt.invalidate_plater())
{
@ -6219,6 +6249,18 @@ void Plater::priv::on_action_print_plate(SimpleEvent&)
m_select_machine_dlg->ShowModal();
}
void Plater::priv::on_action_print_plate_from_sdcard(SimpleEvent&)
{
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received print plate event\n";
}
//BBS
if (!m_select_machine_dlg) m_select_machine_dlg = new SelectMachineDialog(q);
m_select_machine_dlg->prepare(0);
m_select_machine_dlg->ShowModal();
}
void Plater::priv::on_action_send_to_printer(bool isall)
{
@ -7278,18 +7320,19 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name, const UndoRed
tower.rotation = proj_cfg.opt_float("wipe_tower_rotation_angle");
}
}
const GLGizmosManager& gizmos = view3D->get_canvas3d()->get_gizmos_manager();
const GLGizmosManager& gizmos = get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : view3D->get_canvas3d()->get_gizmos_manager();
if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator)
this->undo_redo_stack().clear();
this->undo_redo_stack().take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), partplate_list, snapshot_data);
this->undo_redo_stack().take_snapshot(snapshot_name, model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : view3D->get_canvas3d()->get_selection(), gizmos, partplate_list, snapshot_data);
if (snapshot_type == UndoRedo::SnapshotType::LeavingGizmoWithAction) {
// Filter all but the last UndoRedo::SnapshotType::GizmoAction in a row between the last UndoRedo::SnapshotType::EnteringGizmo and UndoRedo::SnapshotType::LeavingGizmoWithAction.
// The remaining snapshot will be renamed to a more generic name,
// depending on what gizmo is being left.
assert(gizmos.get_current() != nullptr);
std::string new_name = gizmos.get_current()->get_action_snapshot_name();
this->undo_redo_stack().reduce_noisy_snapshots(new_name);
if (gizmos.get_current() != nullptr) {
std::string new_name = gizmos.get_current()->get_action_snapshot_name();
this->undo_redo_stack().reduce_noisy_snapshots(new_name);
}
} else if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) {
// Reset the "dirty project" flag.
m_undo_redo_stack_main.mark_current_as_saved();
@ -7311,6 +7354,13 @@ void Plater::priv::undo()
// BBS: undo-redo until modify record
while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current));
if (it_current == snapshots.begin()) return;
if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
if (it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::GizmoAction &&
it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::EnteringGizmo &&
it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoNoAction &&
it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoWithAction)
return;
}
this->undo_redo_to(it_current);
}
@ -7413,8 +7463,8 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
const UndoRedo::Snapshot snapshot_copy = *it_snapshot;
// Do the jump in time.
if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ?
this->undo_redo_stack().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) :
this->undo_redo_stack().redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) {
this->undo_redo_stack().undo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : this->view3D->get_canvas3d()->get_selection(), get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) :
this->undo_redo_stack().redo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) {
if (printer_technology_changed) {
// Switch to the other printer technology. Switch to the last printer active for that particular technology.
AppConfig *app_config = wxGetApp().app_config;
@ -7491,7 +7541,7 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */)
{
this->view3D->get_canvas3d()->get_selection().clear();
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection().clear() : this->view3D->get_canvas3d()->get_selection().clear();
// Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies).
this->update((unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE | (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE);
// Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot.
@ -7500,8 +7550,12 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo
// triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
this->undo_redo_stack().release_least_recently_used();
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances);
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
assemble_view->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances) :
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances);
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
assemble_view->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot) :
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
wxGetApp().obj_list()->update_after_undo_redo();
@ -7653,6 +7707,7 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString& project_
//get_partplate_list().update_slice_context_to_current_plate(p->background_process);
//p->preview->update_gcode_result(p->partplate_list.get_current_slice_result());
reset(transfer_preset_changes);
reset_project_dirty_after_save();
reset_project_dirty_initial_presets();
wxGetApp().update_saved_preset_from_current_preset();
update_project_dirty_from_presets();
@ -7777,6 +7832,9 @@ void Plater::load_project(wxString const& filename2,
p->camera.requires_zoom_to_plate = REQUIRES_ZOOM_TO_ALL_PLATE;
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
}
else {
p->partplate_list.select_plate_view();
}
if (previous_gcode)
collapse_sidebar(false);
@ -7814,7 +7872,7 @@ int Plater::save_project(bool saveAs)
return wxID_CANCEL;
//BBS export 3mf without gcode
if (export_3mf(into_path(filename), SaveStrategy::SplitModel) < 0) {
if (export_3mf(into_path(filename), SaveStrategy::SplitModel | SaveStrategy::ShareMesh) < 0) {
MessageDialog(this, _L("Failed to save the project.\nPlease check whether the folder exists online or if other programs open the project file."),
_L("Save project"), wxOK | wxICON_WARNING).ShowModal();
return wxID_CANCEL;
@ -7828,7 +7886,7 @@ int Plater::save_project(bool saveAs)
up_to_date(true, true);
wxGetApp().update_saved_preset_from_current_preset();
p->dirty_state.reset_after_save();
reset_project_dirty_after_save();
return wxID_YES;
}
@ -7839,9 +7897,9 @@ void Plater::import_model_id(const std::string& download_info)
std::string filename;
std::string download_origin_url = wxGetApp().url_decode(download_info);
fs::path download_path = fs::path(download_origin_url);
download_url = download_origin_url;
filename = download_path.filename().string();
fs::path download_path = fs::path(download_origin_url);
download_url = download_origin_url;
filename = download_path.filename().string();
bool download_ok = false;
@ -7937,7 +7995,8 @@ void Plater::import_model_id(const std::string& download_info)
}
//target_path /= (boost::format("%1%_%2%.3mf") % filename % unique).str();
target_path /= filename.c_str();
target_path /= fs::path(wxString(filename).wc_str());
fs::path tmp_path = target_path;
tmp_path += format(".%1%", ".download");
@ -8048,11 +8107,11 @@ void Plater::add_model(bool imperial_units/* = false*/, std::string fname/* = "
std::vector<fs::path> paths;
if(fname.empty()){
wxArrayString input_files;
wxArrayString input_files;
wxGetApp().import_model(this, input_files);
if (input_files.empty())
return;
for (const auto &file : input_files)
paths.emplace_back(into_path(file));
}
@ -8659,6 +8718,16 @@ void Plater::load_gcode(const wxString& filename)
}
*current_result = std::move(processor.extract_result());
//current_result->filename = filename;
BedType bed_type = current_result->bed_type;
if (bed_type != BedType::btCount) {
DynamicPrintConfig &proj_config = wxGetApp().preset_bundle->project_config;
proj_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
on_bed_type_change(bed_type);
}
current_print.apply(this->model(), wxGetApp().preset_bundle->full_config());
current_print.set_gcode_file_ready();
// show results
@ -9402,6 +9471,9 @@ bool Plater::is_view3D_shown() const { return p->is_view3D_shown(); }
bool Plater::are_view3D_labels_shown() const { return p->are_view3D_labels_shown(); }
void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); }
bool Plater::is_view3D_overhang_shown() const { return p->is_view3D_overhang_shown(); }
void Plater::show_view3D_overhang(bool show) { p->show_view3D_overhang(show); }
bool Plater::is_sidebar_collapsed() const { return p->is_sidebar_collapsed(); }
void Plater::collapse_sidebar(bool show) { p->collapse_sidebar(show); }
@ -9446,8 +9518,12 @@ int GUI::Plater::close_with_confirm(std::function<bool(bool)> second_check)
wxGetApp().app_config->set("save_project_choise", result == wxID_YES ? "yes" : "no");
if (result == wxID_YES) {
result = save_project();
if (result == wxID_CANCEL)
return result;
if (result == wxID_CANCEL) {
if (choise.empty())
return result;
else
result = wxID_NO;
}
}
}
@ -9938,38 +10014,92 @@ void Plater::export_core_3mf()
export_3mf(path_u8, SaveStrategy::Silence);
}
// Following lambda generates a combined mesh for export with normals pointing outwards.
TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, std::function<void(const std::string&)> notify_func)
{
TriangleMesh mesh;
std::vector<csg::CSGPart> csgmesh;
csgmesh.reserve(2 * mo.volumes.size());
bool has_splitable_volume = csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh),
csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits);
if (csg::check_csgmesh_booleans(Range{ std::begin(csgmesh), std::end(csgmesh) }) == csgmesh.end()) {
try {
MeshBoolean::mcut::McutMeshPtr meshPtr = csg::perform_csgmesh_booleans_mcut(Range{ std::begin(csgmesh), std::end(csgmesh) });
mesh = MeshBoolean::mcut::mcut_to_triangle_mesh(*meshPtr);
}
catch (...) {}
#if 0
// if mcut fails, try again with CGAL
if (mesh.empty()) {
try {
auto meshPtr = csg::perform_csgmesh_booleans(Range{ std::begin(csgmesh), std::end(csgmesh) });
mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*meshPtr);
}
catch (...) {}
}
#endif
}
if (mesh.empty()) {
if (notify_func)
notify_func(_u8L("Unable to perform boolean operation on model meshes. "
"Only positive parts will be exported."));
for (const ModelVolume* v : mo.volumes)
if (v->is_model_part()) {
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix(), true);
mesh.merge(vol_mesh);
}
}
if (instance_id == -1) {
TriangleMesh vols_mesh(mesh);
mesh = TriangleMesh();
for (const ModelInstance* i : mo.instances) {
TriangleMesh m = vols_mesh;
m.transform(i->get_matrix(), true);
mesh.merge(m);
}
}
else if (0 <= instance_id && instance_id < int(mo.instances.size()))
mesh.transform(mo.instances[instance_id]->get_matrix(), true);
return mesh;
}
// BBS export with/without boolean, however, stil merge mesh
#define EXPORT_WITH_BOOLEAN 0
void Plater::export_stl(bool extended, bool selection_only)
{
if (p->model.objects.empty()) { return; }
wxBusyCursor wait;
const auto &selection = p->get_selection();
// BBS support mulity objects
// const auto obj_idx = selection.get_object_idx();
// if (selection_only && (obj_idx == -1 || selection.is_wipe_tower()))
// return;
if (selection_only && selection.is_wipe_tower())
return;
//BBS
if (selection_only) {
// only support selection single full object and mulitiple full object
if (!selection.is_single_full_object() && !selection.is_multiple_full_object())
return;
}
wxString path = p->get_export_file(FT_STL);
if (path.empty()) { return; }
const std::string path_u8 = into_u8(path);
wxBusyCursor wait;
const auto& selection = p->get_selection();
const auto obj_idx = selection.get_object_idx();
#if EXPORT_WITH_BOOLEAN
if (selection_only && (obj_idx == -1 || selection.is_wipe_tower()))
return;
#else
// BBS support selecting multiple objects
if (selection_only && selection.is_wipe_tower()) return;
// BBS
if (selection_only) {
// only support selection single full object and mulitiple full object
if (!selection.is_single_full_object() && !selection.is_multiple_full_object()) return;
}
// Following lambda generates a combined mesh for export with normals pointing outwards.
auto mesh_to_export = [](const ModelObject& mo, int instance_id) {
auto mesh_to_export_fff_no_boolean = [](const ModelObject &mo, int instance_id) {
TriangleMesh mesh;
for (const ModelVolume* v : mo.volumes)
for (const ModelVolume *v : mo.volumes)
if (v->is_model_part()) {
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix(), true);
@ -9978,125 +10108,72 @@ void Plater::export_stl(bool extended, bool selection_only)
if (instance_id == -1) {
TriangleMesh vols_mesh(mesh);
mesh = TriangleMesh();
for (const ModelInstance* i : mo.instances) {
for (const ModelInstance *i : mo.instances) {
TriangleMesh m = vols_mesh;
m.transform(i->get_matrix(), true);
mesh.merge(m);
}
}
else if (0 <= instance_id && instance_id < int(mo.instances.size()))
} else if (0 <= instance_id && instance_id < int(mo.instances.size()))
mesh.transform(mo.instances[instance_id]->get_matrix(), true);
return mesh;
};
#endif
auto mesh_to_export_sla = [&, this](const ModelObject& mo, int instance_id) {
TriangleMesh mesh;
TriangleMesh mesh;
if (p->printer_technology == ptFFF) {
if (selection_only) {
if (selection.is_single_full_object()) {
const auto obj_idx = selection.get_object_idx();
const ModelObject* model_object = p->model.objects[obj_idx];
if (selection.get_mode() == Selection::Instance)
{
mesh = std::move(mesh_to_export(*model_object, ( model_object->instances.size() > 1) ? -1 : selection.get_instance_idx()));
}
else
{
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
mesh = model_object->volumes[volume->volume_idx()]->mesh();
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
}
const SLAPrintObject *object = this->p->sla_print.get_print_object_by_model_object_id(mo.id());
if (model_object->instances.size() == 1)
mesh.translate(-model_object->origin_translation.cast<float>());
}
else if (selection.is_multiple_full_object()) {
const std::set<std::pair<int, int>>& instances_idxs = p->get_selection().get_selected_object_instances();
for (const std::pair<int, int>& i : instances_idxs)
{
ModelObject* object = p->model.objects[i.first];
mesh.merge(mesh_to_export(*object, i.second));
}
}
}
if (auto m = object->get_mesh_to_print(); m.empty())
mesh = combine_mesh_fff(mo, instance_id, [this](const std::string& msg) {return get_notification_manager()->push_plater_error_notification(msg); });
else {
for (const ModelObject *o : p->model.objects)
mesh.merge(mesh_to_export(*o, -1));
}
}
else
{
// This is SLA mode, all objects have only one volume.
// However, we must have a look at the backend to load
// hollowed mesh and/or supports
const auto obj_idx = selection.get_object_idx();
const PrintObjects& objects = p->sla_print.objects();
for (const SLAPrintObject* object : objects)
{
const ModelObject* model_object = object->model_object();
if (selection_only) {
if (model_object->id() != p->model.objects[obj_idx]->id())
continue;
}
Transform3d mesh_trafo_inv = object->trafo().inverse();
bool is_left_handed = object->is_left_handed();
const Transform3d mesh_trafo_inv = object->trafo().inverse();
const bool is_left_handed = object->is_left_handed();
TriangleMesh pad_mesh;
bool has_pad_mesh = extended && object->has_mesh(slaposPad);
if (has_pad_mesh)
{
pad_mesh = object->get_mesh(slaposPad);
pad_mesh.transform(mesh_trafo_inv);
}
auto pad_mesh = extended? object->pad_mesh() : TriangleMesh{};
pad_mesh.transform(mesh_trafo_inv);
auto supports_mesh = extended ? object->support_mesh() : TriangleMesh{};
supports_mesh.transform(mesh_trafo_inv);
TriangleMesh supports_mesh;
bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree);
if (has_supports_mesh)
{
supports_mesh = object->get_mesh(slaposSupportTree);
supports_mesh.transform(mesh_trafo_inv);
}
const std::vector<SLAPrintObject::Instance>& obj_instances = object->instances();
for (const SLAPrintObject::Instance& obj_instance : obj_instances)
{
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
[&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; });
assert(it != model_object->instances.end());
for (const SLAPrintObject::Instance& obj_instance : obj_instances) {
auto it = std::find_if(object->model_object()->instances.begin(), object->model_object()->instances.end(),
[&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; });
assert(it != object->model_object()->instances.end());
if (it != model_object->instances.end())
{
bool one_inst_only = selection_only && ! selection.is_single_full_object();
if (it != object->model_object()->instances.end()) {
const bool one_inst_only = selection_only && ! selection.is_single_full_object();
int instance_idx = it - model_object->instances.begin();
const int instance_idx = it - object->model_object()->instances.begin();
const Transform3d& inst_transform = one_inst_only
? Transform3d::Identity()
: object->model_object()->instances[instance_idx]->get_transformation().get_matrix();
? Transform3d::Identity()
: object->model_object()->instances[instance_idx]->get_transformation().get_matrix();
TriangleMesh inst_mesh;
if (has_pad_mesh)
{
if (!pad_mesh.empty()) {
TriangleMesh inst_pad_mesh = pad_mesh;
inst_pad_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_pad_mesh);
}
if (has_supports_mesh)
{
if (!supports_mesh.empty()) {
TriangleMesh inst_supports_mesh = supports_mesh;
inst_supports_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_supports_mesh);
}
TriangleMesh inst_object_mesh = object->get_mesh_to_slice();
TriangleMesh inst_object_mesh = object->get_mesh_to_print();
inst_object_mesh.transform(mesh_trafo_inv);
inst_object_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_object_mesh);
// ensure that the instance lays on the bed
inst_mesh.translate(0.0f, 0.0f, -inst_mesh.bounding_box().min[2]);
// ensure that the instance lays on the bed
inst_mesh.translate(0.0f, 0.0f, -inst_mesh.bounding_box().min.z());
// merge instance with global mesh
// merge instance with global mesh
mesh.merge(inst_mesh);
if (one_inst_only)
@ -10104,6 +10181,50 @@ void Plater::export_stl(bool extended, bool selection_only)
}
}
}
return mesh;
};
std::function<TriangleMesh(const ModelObject& mo, int instance_id)>
mesh_to_export;
if (p->printer_technology == ptFFF)
#if EXPORT_WITH_BOOLEAN
mesh_to_export = [this](const ModelObject& mo, int instance_id) {return Plater::combine_mesh_fff(mo, instance_id,
[this](const std::string& msg) {return get_notification_manager()->push_plater_error_notification(msg); }); };
#else
mesh_to_export = mesh_to_export_fff_no_boolean;
#endif
else
mesh_to_export = mesh_to_export_sla;
TriangleMesh mesh;
if (selection_only) {
if (selection.is_single_full_object()) {
const auto obj_idx = selection.get_object_idx();
const ModelObject* model_object = p->model.objects[obj_idx];
if (selection.get_mode() == Selection::Instance)
mesh = mesh_to_export(*model_object, (model_object->instances.size() > 1) ? -1 : selection.get_instance_idx());
else {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
mesh = model_object->volumes[volume->volume_idx()]->mesh();
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
}
if (model_object->instances.size() == 1) mesh.translate(-model_object->origin_translation.cast<float>());
}
else if (selection.is_multiple_full_object()) {
const std::set<std::pair<int, int>>& instances_idxs = p->get_selection().get_selected_object_instances();
for (const std::pair<int, int>& i : instances_idxs) {
ModelObject* object = p->model.objects[i.first];
mesh.merge(mesh_to_export(*object, i.second));
}
}
}
else {
for (const ModelObject* o : p->model.objects) {
mesh.merge(mesh_to_export(*o, -1));
}
}
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
@ -11038,7 +11159,7 @@ std::vector<std::string> Plater::get_colors_for_color_print(const GCodeProcessor
return colors;
}
wxString Plater::get_project_filename(const wxString& extension) const
{
return p->get_project_filename(extension);
@ -11469,7 +11590,8 @@ int Plater::select_plate(int plate_index, bool need_slice)
{
if (need_slice) { //from preview's thumbnail
if ((invalidated & PrintBase::APPLY_STATUS_INVALIDATED) || (gcode_result->moves.empty())){
//part_plate->update_slice_result_valid_state(false);
if (invalidated & PrintBase::APPLY_STATUS_INVALIDATED)
part_plate->update_slice_result_valid_state(false);
p->process_completed_with_error = -1;
p->m_slice_all = false;
reset_gcode_toolpaths();
@ -11897,11 +12019,23 @@ void Plater::show_object_info()
{
NotificationManager *notify_manager = get_notification_manager();
const Selection& selection = get_selection();
int selCount = selection.get_volume_idxs().size();
ModelObjectPtrs objects = model().objects;
int obj_idx = selection.get_object_idx();
std::string info_text;
if (objects.empty() || (obj_idx < 0) || (obj_idx >= objects.size()) ||
if (selCount > 1 && !selection.is_single_full_object()) {
notify_manager->bbl_close_objectsinfo_notification();
if (selection.get_mode() == Selection::EMode::Volume) {
info_text += (boost::format(_utf8(L("Number of currently selected parts: %1%\n"))) % selCount).str();
} else if (selection.get_mode() == Selection::EMode::Instance) {
int content_count = selection.get_content().size();
info_text += (boost::format(_utf8(L("Number of currently selected objects: %1%\n"))) % content_count).str();
}
notify_manager->bbl_show_objectsinfo_notification(info_text, false, !(p->current_panel == p->view3D));
return;
}
else if (objects.empty() || (obj_idx < 0) || (obj_idx >= objects.size()) ||
objects[obj_idx]->volumes.empty() ||// hack to avoid crash when deleting the last object on the bed
(selection.is_single_full_object() && objects[obj_idx]->instances.size()> 1) ||
!(selection.is_single_full_instance() || selection.is_single_volume()))
@ -11939,12 +12073,12 @@ void Plater::show_object_info()
size = vol->get_convex_hull().transformed_bounding_box(t).size();
}
else {
int obj_idx, vol_idx;
wxGetApp().obj_list()->get_selected_item_indexes(obj_idx, vol_idx);
if (obj_idx < 0) {
//corner case when merge/split/remove
return;
}
//int obj_idx, vol_idx;
//wxGetApp().obj_list()->get_selected_item_indexes(obj_idx, vol_idx);
//if (obj_idx < 0) {
// //corner case when merge/split/remove
// return;
//}
info_text += (boost::format(_utf8(L("Object name: %1%\n"))) % model_object->name).str();
face_count = static_cast<int>(model_object->facets_count());
size = model_object->instance_convex_hull_bounding_box(inst_idx).size();
@ -12277,7 +12411,8 @@ wxMenu* Plater::default_menu() { return p->menus.default_menu();
wxMenu* Plater::instance_menu() { return p->menus.instance_menu(); }
wxMenu* Plater::layer_menu() { return p->menus.layer_menu(); }
wxMenu* Plater::multi_selection_menu() { return p->menus.multi_selection_menu(); }
int Plater::GetPlateIndexByRightMenuInLeftUI() { return p->m_is_RightClickInLeftUI; }
void Plater::SetPlateIndexByRightMenuInLeftUI(int index) { p->m_is_RightClickInLeftUI = index; }
SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() :
m_was_scheduled(wxGetApp().plater()->is_background_process_update_scheduled())
{

View file

@ -288,6 +288,9 @@ public:
bool are_view3D_labels_shown() const;
void show_view3D_labels(bool show);
bool is_view3D_overhang_shown() const;
void show_view3D_overhang(bool show);
bool is_sidebar_collapsed() const;
void collapse_sidebar(bool show);
@ -332,6 +335,7 @@ public:
void export_gcode_3mf(bool export_all = false);
void send_gcode_finish(wxString name);
void export_core_3mf();
static TriangleMesh combine_mesh_fff(const ModelObject& mo, int instance_id, std::function<void(const std::string&)> notify_func = {});
void export_stl(bool extended = false, bool selection_only = false);
//BBS: remove amf
//void export_amf();
@ -686,7 +690,8 @@ public:
wxMenu* instance_menu();
wxMenu* layer_menu();
wxMenu* multi_selection_menu();
int GetPlateIndexByRightMenuInLeftUI();
void SetPlateIndexByRightMenuInLeftUI(int);
static bool has_illegal_filename_characters(const wxString& name);
static bool has_illegal_filename_characters(const std::string& name);
static void show_illegal_characters_warning(wxWindow* parent);

View file

@ -1961,7 +1961,9 @@ void Selection::update_type()
unsigned int sels_cntr = 0;
for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
{
const ModelObject* model_object = m_model->objects[it->first];
bool is_wipe_tower = it->first >= 1000;
int actual_obj_id = is_wipe_tower ? it->first - 1000 : it->first;
const ModelObject *model_object = m_model->objects[actual_obj_id];
unsigned int volumes_count = (unsigned int)model_object->volumes.size();
unsigned int instances_count = (unsigned int)model_object->instances.size();
sels_cntr += volumes_count * instances_count;
@ -2710,9 +2712,14 @@ void Selection::paste_objects_from_clipboard()
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
}
for (ModelInstance* inst : dst_object->instances)
for (ModelInstance* inst : dst_object->instances) {
inst->set_offset(displacement);
//BBS init asssmble transformation
Geometry::Transformation t = inst->get_transformation();
inst->set_assemble_transformation(t);
}
object_idxs.push_back(m_model->objects.size() - 1);
#ifdef _DEBUG
check_model_ids_validity(*m_model);

View file

@ -362,6 +362,11 @@ public:
bool requires_local_axes() const;
void render_bounding_box(const BoundingBoxf3& box, float* color, float scale) {
m_scale_factor = scale;
render_bounding_box(box, color);
}
//BBS
void cut_to_clipboard();
void copy_to_clipboard();