mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/Slic3r
This commit is contained in:
		
						commit
						022e325a60
					
				
					 21 changed files with 546 additions and 75 deletions
				
			
		
							
								
								
									
										37
									
								
								resources/icons/copy.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								resources/icons/copy.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <g id="copy"> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#ED6B21" d="M115.76,51.2l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.17,118.23,53.67,115.76,51.2z M111.42,54.04h-6.57 | ||||||
|  | 			v-6.57L111.42,54.04z M115.01,112.47c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.42 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54 | ||||||
|  | 			V112.47z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M53.97,59.13h35.72c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H53.97c-1.4,0-2.54,1.14-2.54,2.54 | ||||||
|  | 			S52.56,59.13,53.97,59.13z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,69.29H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,69.29,104.93,69.29z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,84.53H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,84.53,104.93,84.53z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,99.77H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,99.77,104.93,99.77z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#FFFFFF" d="M85.27,20.71l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h17.78c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H15.94c-1.4,0-2.54-1.14-2.54-2.54V15.94 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46V26.1c0,1.4,1.14,2.54,2.54,2.54h12.45c0.16,0.49,0.25,0.93,0.25,1.27 | ||||||
|  | 			v3.81c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54v-3.81C89.61,27.14,87.75,23.19,85.27,20.71z M74.37,16.99l6.57,6.57 | ||||||
|  | 			h-6.57V16.99z"/> | ||||||
|  | 		<path fill="#FFFFFF" d="M59.21,23.56H23.48c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h35.72c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S60.61,23.56,59.21,23.56z"/> | ||||||
|  | 		<path fill="#FFFFFF" d="M28.73,38.8h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,38.8,28.73,38.8z"/> | ||||||
|  | 		<path fill="#FFFFFF" d="M28.73,54.04h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,54.04,28.73,54.04z"/> | ||||||
|  | 		<path fill="#FFFFFF" d="M28.73,69.29h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,69.29,28.73,69.29z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.6 KiB | 
							
								
								
									
										37
									
								
								resources/icons/copy_menu.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								resources/icons/copy_menu.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <g id="copy"> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#ED6B21" d="M115.76,51.2l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.17,118.23,53.67,115.76,51.2z M111.42,54.04h-6.57 | ||||||
|  | 			v-6.57L111.42,54.04z M115.01,112.47c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.42 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54 | ||||||
|  | 			V112.47z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M53.97,59.13h35.72c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H53.97c-1.4,0-2.54,1.14-2.54,2.54 | ||||||
|  | 			S52.56,59.13,53.97,59.13z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,69.29H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,69.29,104.93,69.29z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,84.53H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,84.53,104.93,84.53z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,99.77H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,99.77,104.93,99.77z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#808080" d="M85.27,20.71l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h17.78c1.4,0,2.54-1.14,2.54-2.54s-1.14-2.54-2.54-2.54H15.94c-1.4,0-2.54-1.14-2.54-2.54V15.94 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46V26.1c0,1.4,1.14,2.54,2.54,2.54h12.45c0.16,0.49,0.25,0.93,0.25,1.27 | ||||||
|  | 			v3.81c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54v-3.81C89.61,27.14,87.75,23.19,85.27,20.71z M74.37,16.99l6.57,6.57 | ||||||
|  | 			h-6.57V16.99z"/> | ||||||
|  | 		<path fill="#808080" d="M59.21,23.56H23.48c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h35.72c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S60.61,23.56,59.21,23.56z"/> | ||||||
|  | 		<path fill="#808080" d="M28.73,38.8h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,38.8,28.73,38.8z"/> | ||||||
|  | 		<path fill="#808080" d="M28.73,54.04h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,54.04,28.73,54.04z"/> | ||||||
|  | 		<path fill="#808080" d="M28.73,69.29h-5.24c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h5.24c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S30.13,69.29,28.73,69.29z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.6 KiB | 
							
								
								
									
										31
									
								
								resources/icons/delete_all_menu.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								resources/icons/delete_all_menu.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <g id="DELETE_ALL_1_"> | ||||||
|  | 	<path fill="#808080" d="M103.52,43.87l-13.31,69.97H37.79L24.48,43.87H103.52 M108.77,37.87H19.23c-1.1,0-1.83,0.88-1.63,1.96 | ||||||
|  | 		l14.84,78.04c0.21,1.08,1.27,1.96,2.37,1.96h58.36c1.1,0,2.17-0.88,2.37-1.96l14.84-78.04C110.6,38.75,109.87,37.87,108.77,37.87 | ||||||
|  | 		L108.77,37.87z"/> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#ED6B21" d="M89.38,22.97c-1.1,0-2-0.9-2-2v-10.9c0-1.1-0.9-2-2-2H42.62c-1.1,0-2,0.9-2,2v10.9c0,1.1-0.9,2-2,2H19.23 | ||||||
|  | 			c-1.1,0-2,0.9-2,2v3.45c0,1.1,0.9,2,2,2h89.54c1.1,0,2-0.9,2-2v-3.45c0-1.1-0.9-2-2-2H89.38z M79.59,20.97c0,1.1-0.9,2-2,2H50.41 | ||||||
|  | 			c-1.1,0-2-0.9-2-2v-3.45c0-1.1,0.9-2,2-2h27.18c1.1,0,2,0.9,2,2V20.97z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#808080" d="M93.17,73.5H34.83c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h58.34c0.83,0,1.5,0.67,1.5,1.5 | ||||||
|  | 			S94,73.5,93.17,73.5z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#808080" d="M90.14,89.45H37.96c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h52.18c0.83,0,1.5,0.67,1.5,1.5 | ||||||
|  | 			S90.97,89.45,90.14,89.45z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#808080" d="M87.1,105.4H40.9c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h46.2c0.83,0,1.5,0.67,1.5,1.5 | ||||||
|  | 			S87.93,105.4,87.1,105.4z"/> | ||||||
|  | 	</g> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#808080" d="M96.2,57.56H31.8c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h64.4c0.83,0,1.5,0.67,1.5,1.5 | ||||||
|  | 			S97.03,57.56,96.2,57.56z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										27
									
								
								resources/icons/paste.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								resources/icons/paste.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <g id="paste"> | ||||||
|  | 	<path fill="#FFFFFF" d="M33.73,107.03H15.94c-1.4,0-2.54-1.14-2.54-2.54V23.52c0-1.4,1.14-2.54,2.54-2.54h7.62v5.08 | ||||||
|  | 		c0,1.4,1.14,2.54,2.54,2.54h45.72c1.4,0,2.54-1.14,2.54-2.54v-5.08h7.62c1.4,0,2.54,1.14,2.54,2.54v10.16 | ||||||
|  | 		c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54V23.52c0-4.2-3.42-7.62-7.62-7.62h-7.62v-5.08c0-1.4-1.14-2.54-2.54-2.54 | ||||||
|  | 		H26.11c-1.4,0-2.54,1.14-2.54,2.54v5.08h-7.62c-4.2,0-7.62,3.42-7.62,7.62v80.97c0,4.2,3.42,7.62,7.62,7.62h17.78 | ||||||
|  | 		c1.4,0,2.54-1.14,2.54-2.54C36.27,108.16,35.13,107.03,33.73,107.03z M28.65,13.36h40.64v10.16H28.65V13.36z"/> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#ED6B21" d="M53.97,59.08h35.72c1.4,0,2.54-1.14,2.54-2.54c0-1.4-1.14-2.54-2.54-2.54H53.97 | ||||||
|  | 			c-1.4,0-2.54,1.14-2.54,2.54C51.43,57.94,52.56,59.08,53.97,59.08z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,69.24H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96 | ||||||
|  | 			c1.4,0,2.54-1.14,2.54-2.54C107.47,70.38,106.33,69.24,104.93,69.24z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,99.72H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,99.72,104.93,99.72z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M115.75,51.15l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.12,118.23,53.62,115.75,51.15z M104.85,47.43 | ||||||
|  | 			l6.57,6.57h-6.57V47.43z M115.01,112.42c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.38 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54 | ||||||
|  | 			V112.42z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,84.48H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96 | ||||||
|  | 			c1.4,0,2.54-1.14,2.54-2.54C107.47,85.62,106.33,84.48,104.93,84.48z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										27
									
								
								resources/icons/paste_menu.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								resources/icons/paste_menu.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <g id="paste"> | ||||||
|  | 	<path fill="#808080" d="M33.73,107.03H15.94c-1.4,0-2.54-1.14-2.54-2.54V23.52c0-1.4,1.14-2.54,2.54-2.54h7.62v5.08 | ||||||
|  | 		c0,1.4,1.14,2.54,2.54,2.54h45.72c1.4,0,2.54-1.14,2.54-2.54v-5.08h7.62c1.4,0,2.54,1.14,2.54,2.54v10.16 | ||||||
|  | 		c0,1.4,1.14,2.54,2.54,2.54c1.4,0,2.54-1.14,2.54-2.54V23.52c0-4.2-3.42-7.62-7.62-7.62h-7.62v-5.08c0-1.4-1.14-2.54-2.54-2.54 | ||||||
|  | 		H26.11c-1.4,0-2.54,1.14-2.54,2.54v5.08h-7.62c-4.2,0-7.62,3.42-7.62,7.62v80.97c0,4.2,3.42,7.62,7.62,7.62h17.78 | ||||||
|  | 		c1.4,0,2.54-1.14,2.54-2.54C36.27,108.16,35.13,107.03,33.73,107.03z M28.65,13.36h40.64v10.16H28.65V13.36z"/> | ||||||
|  | 	<g> | ||||||
|  | 		<path fill="#ED6B21" d="M53.97,59.08h35.72c1.4,0,2.54-1.14,2.54-2.54c0-1.4-1.14-2.54-2.54-2.54H53.97 | ||||||
|  | 			c-1.4,0-2.54,1.14-2.54,2.54C51.43,57.94,52.56,59.08,53.97,59.08z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,69.24H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96 | ||||||
|  | 			c1.4,0,2.54-1.14,2.54-2.54C107.47,70.38,106.33,69.24,104.93,69.24z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,99.72H53.97c-1.4,0-2.54,1.14-2.54,2.54s1.14,2.54,2.54,2.54h50.96c1.4,0,2.54-1.14,2.54-2.54 | ||||||
|  | 			S106.33,99.72,104.93,99.72z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M115.75,51.15l-8.06-8.06c-2.47-2.47-6.97-4.34-10.47-4.34h-50.8c-4.2,0-7.62,3.42-7.62,7.62v66.04 | ||||||
|  | 			c0,4.2,3.42,7.62,7.62,7.62h66.04c4.2,0,7.62-3.42,7.62-7.62v-50.8C120.09,58.12,118.23,53.62,115.75,51.15z M104.85,47.43 | ||||||
|  | 			l6.57,6.57h-6.57V47.43z M115.01,112.42c0,1.4-1.14,2.54-2.54,2.54H46.43c-1.4,0-2.54-1.14-2.54-2.54V46.38 | ||||||
|  | 			c0-1.4,1.14-2.54,2.54-2.54h50.8c0.74,0,1.63,0.18,2.54,0.46v12.24c0,1.4,1.14,2.54,2.54,2.54h12.24c0.28,0.91,0.46,1.8,0.46,2.54 | ||||||
|  | 			V112.42z"/> | ||||||
|  | 		<path fill="#ED6B21" d="M104.93,84.48H53.97c-1.4,0-2.54,1.14-2.54,2.54c0,1.4,1.14,2.54,2.54,2.54h50.96 | ||||||
|  | 			c1.4,0,2.54-1.14,2.54-2.54C107.47,85.62,106.33,84.48,104.93,84.48z"/> | ||||||
|  | 	</g> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										44
									
								
								resources/icons/remove_menu.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								resources/icons/remove_menu.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||||
|  | <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||||
|  | 	 viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve"> | ||||||
|  | <path fill="#808080" d="M38.11,44.25H25.75c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72H38.1c0.95,0,1.72-0.77,1.72-1.72 | ||||||
|  | 	C39.83,45.02,39.06,44.25,38.11,44.25z M45.89,45.97c0,0.95,0.77,1.72,1.72,1.72h12.35c0.95,0,1.72-0.77,1.72-1.72 | ||||||
|  | 	s-0.77-1.72-1.72-1.72H47.61C46.66,44.25,45.89,45.02,45.89,45.97z M68.11,43.6c-0.33,0.28-0.52,0.65-0.59,1.04 | ||||||
|  | 	c-0.59,0.27-1,0.87-1,1.56v5.6c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-5.34c0.12-0.06,0.24-0.13,0.35-0.22 | ||||||
|  | 	c0.13-0.11,0.25-0.23,0.36-0.34l8.27-8.77c0.65-0.69,0.62-1.78-0.07-2.43s-1.78-0.62-2.43,0.07l-8.27,8.78 | ||||||
|  | 	C68.16,43.56,68.14,43.58,68.11,43.6z M68.25,76.84c-0.95,0-1.72,0.77-1.72,1.72V89.1c0,0.95,0.77,1.72,1.72,1.72 | ||||||
|  | 	c0.95,0,1.72-0.77,1.72-1.72V78.56C69.97,77.61,69.2,76.84,68.25,76.84z M69.97,59.91c0-0.95-0.77-1.72-1.72-1.72 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72v10.54c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72V59.91z M88.92,56.35 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72v3.4c0,0.34-0.02,0.63-0.04,0.85c-0.51,0.55-0.62,1.38-0.22,2.06c0.32,0.54,0.89,0.84,1.48,0.84 | ||||||
|  | 	c0.3,0,0.6-0.08,0.88-0.24l0.25-0.15c0.67-0.4,1.09-1.1,1.09-3.35v-3.4C90.64,57.12,89.87,56.35,88.92,56.35z M41.81,26.17h11.3 | ||||||
|  | 	c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3c-0.95,0-1.72,0.77-1.72,1.72S40.86,26.17,41.81,26.17z M87.2,22.73h-5.39 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h2.75l-1.58,1.68c-0.65,0.69-0.62,1.78,0.07,2.43c0.33,0.31,0.76,0.47,1.18,0.47 | ||||||
|  | 	c0.46,0,0.91-0.18,1.25-0.54l1.72-1.82v0.99c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-3.21 | ||||||
|  | 	C90.64,24.27,89.09,22.73,87.2,22.73z M61.81,26.17h11.3c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72S60.86,26.17,61.81,26.17z M9.71,67.54c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72 | ||||||
|  | 	s-1.72,0.77-1.72,1.72v11.3C7.99,66.77,8.76,67.54,9.71,67.54z M24.65,33.86c0.42,0,0.84-0.15,1.17-0.46l7.04-6.52 | ||||||
|  | 	c0.14-0.13,0.46-0.34,0.9-0.51c0.89-0.34,1.34-1.33,1-2.22s-1.33-1.34-2.22-1c-0.8,0.3-1.52,0.73-2.03,1.2l-7.04,6.52 | ||||||
|  | 	c-0.7,0.65-0.74,1.74-0.09,2.43C23.73,33.68,24.19,33.86,24.65,33.86z M70.35,99.28l-0.37,0.36v-2.43c0-0.95-0.77-1.72-1.72-1.72 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72v4.72H61.3c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h5.23c1.4,0,3.15-0.7,4.16-1.66l2.03-1.94 | ||||||
|  | 	c0.69-0.66,0.71-1.75,0.06-2.43C72.13,98.65,71.03,98.63,70.35,99.28z M52.6,101.93H41.3c-0.95,0-1.72,0.77-1.72,1.72 | ||||||
|  | 	s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S53.55,101.93,52.6,101.93z M88.92,36.35c-0.95,0-1.72,0.77-1.72,1.72v11.3 | ||||||
|  | 	c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-11.3C90.64,37.12,89.87,36.35,88.92,36.35z M32.61,101.93H21.3 | ||||||
|  | 	c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S33.56,101.93,32.61,101.93z M9.71,87.54 | ||||||
|  | 	c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v11.3C7.99,86.77,8.76,87.54,9.71,87.54z | ||||||
|  | 	 M12.61,101.93h-1.18v-7.42c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v7.42c0,1.9,1.54,3.44,3.44,3.44h1.18 | ||||||
|  | 	c0.95,0,1.72-0.77,1.72-1.72S13.56,101.93,12.61,101.93z M19.53,36.88c-0.65-0.7-1.74-0.74-2.43-0.09l-7.3,6.76 | ||||||
|  | 	c-0.55,0.51-0.93,1.15-1.16,1.6C8.22,46,8.56,47.03,9.41,47.46c0.25,0.12,0.51,0.18,0.77,0.18h0.01c0.14,0.04,0.29,0.07,0.45,0.07 | ||||||
|  | 	h5.6c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-2.13l5.33-4.94C20.14,38.66,20.18,37.57,19.53,36.88z M80.7,89.4l-4.05,3.86 | ||||||
|  | 	c-0.69,0.66-0.71,1.75-0.06,2.43c0.34,0.35,0.79,0.53,1.25,0.53c0.43,0,0.86-0.16,1.19-0.48l4.05-3.86 | ||||||
|  | 	c0.69-0.66,0.71-1.75,0.06-2.43C82.48,88.77,81.39,88.75,80.7,89.4z"/> | ||||||
|  | <g> | ||||||
|  | 	<path fill="#ED6B21" d="M98.82,101.06c-11.63,0-21.09-9.46-21.09-21.09s9.46-21.09,21.09-21.09s21.09,9.46,21.09,21.09 | ||||||
|  | 		S110.45,101.06,98.82,101.06z M98.82,62.32c-9.73,0-17.65,7.92-17.65,17.65s7.92,17.65,17.65,17.65s17.65-7.92,17.65-17.65 | ||||||
|  | 		S108.55,62.32,98.82,62.32z"/> | ||||||
|  | </g> | ||||||
|  | <g> | ||||||
|  | 	<path fill="#ED6B21" d="M110.44,81.84c0,1.1-0.9,2-2,2H89.2c-1.1,0-2-0.9-2-2v-3.75c0-1.1,0.9-2,2-2h19.25c1.1,0,2,0.9,2,2 | ||||||
|  | 		L110.44,81.84L110.44,81.84z"/> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 4.2 KiB | 
|  | @ -721,32 +721,37 @@ int GLVolumeCollection::load_wipe_tower_preview( | ||||||
|     return int(this->volumes.size() - 1); |     return int(this->volumes.size() - 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| typedef std::pair<GLVolume*, double> GLVolumeWithZ; | GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) | ||||||
| typedef std::vector<GLVolumeWithZ> GLVolumesWithZList; |  | ||||||
| static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) |  | ||||||
| { | { | ||||||
|     GLVolumesWithZList list; |     GLVolumeWithIdAndZList list; | ||||||
|     list.reserve(volumes.size()); |     list.reserve(volumes.size()); | ||||||
| 
 | 
 | ||||||
|     for (GLVolume* volume : volumes) |     for (unsigned int i = 0; i < (unsigned int)volumes.size(); ++i) | ||||||
|     { |     { | ||||||
|  |         GLVolume* volume = volumes[i]; | ||||||
|         bool is_transparent = (volume->render_color[3] < 1.0f); |         bool is_transparent = (volume->render_color[3] < 1.0f); | ||||||
|         if ((((type == GLVolumeCollection::Opaque) && !is_transparent) || |         if ((((type == GLVolumeCollection::Opaque) && !is_transparent) || | ||||||
|              ((type == GLVolumeCollection::Transparent) && is_transparent) || |              ((type == GLVolumeCollection::Transparent) && is_transparent) || | ||||||
|              (type == GLVolumeCollection::All)) && |              (type == GLVolumeCollection::All)) && | ||||||
|             (! filter_func || filter_func(*volume))) |             (! filter_func || filter_func(*volume))) | ||||||
|             list.emplace_back(std::make_pair(volume, 0.0)); |             list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) |     if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) | ||||||
|     { |     { | ||||||
|         for (GLVolumeWithZ& volume : list) |         for (GLVolumeWithIdAndZ& volume : list) | ||||||
|         { |         { | ||||||
|             volume.second = volume.first->bounding_box.transformed(view_matrix * volume.first->world_matrix()).max(2); |             volume.second.second = volume.first->bounding_box.transformed(view_matrix * volume.first->world_matrix()).max(2); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         std::sort(list.begin(), list.end(), |         std::sort(list.begin(), list.end(), | ||||||
|             [](const GLVolumeWithZ& v1, const GLVolumeWithZ& v2) -> bool { return v1.second < v2.second; } |             [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.second.second < v2.second.second; } | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |     else if ((type == GLVolumeCollection::Opaque) && (list.size() > 1)) | ||||||
|  |     { | ||||||
|  |         std::sort(list.begin(), list.end(), | ||||||
|  |             [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.first->selected && !v2.first->selected; } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -788,9 +793,8 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool | ||||||
|     if (clipping_plane_id != -1) |     if (clipping_plane_id != -1) | ||||||
|         glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)clipping_plane)); |         glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)clipping_plane)); | ||||||
| 
 | 
 | ||||||
|     GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); |     GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); | ||||||
| 
 |     for (GLVolumeWithIdAndZ& volume : to_render) { | ||||||
|     for (GLVolumeWithZ& volume : to_render) { |  | ||||||
|         volume.first->set_render_color(); |         volume.first->set_render_color(); | ||||||
|         volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); |         volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); | ||||||
|     } |     } | ||||||
|  | @ -819,8 +823,8 @@ void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface, | ||||||
|     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); |     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); | ||||||
|     glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); |     glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); | ||||||
|   |   | ||||||
|     GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); |     GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); | ||||||
|     for (GLVolumeWithZ& volume : to_render) |     for (GLVolumeWithIdAndZ& volume : to_render) | ||||||
|     { |     { | ||||||
|         volume.first->set_render_color(); |         volume.first->set_render_color(); | ||||||
|         volume.first->render_legacy(); |         volume.first->render_legacy(); | ||||||
|  |  | ||||||
|  | @ -412,6 +412,8 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef std::vector<GLVolume*> GLVolumePtrs; | typedef std::vector<GLVolume*> GLVolumePtrs; | ||||||
|  | typedef std::pair<GLVolume*, std::pair<unsigned int, double>> GLVolumeWithIdAndZ; | ||||||
|  | typedef std::vector<GLVolumeWithIdAndZ> GLVolumeWithIdAndZList; | ||||||
| 
 | 
 | ||||||
| class GLVolumeCollection | class GLVolumeCollection | ||||||
| { | { | ||||||
|  | @ -509,6 +511,8 @@ private: | ||||||
|     GLVolumeCollection& operator=(const GLVolumeCollection &); |     GLVolumeCollection& operator=(const GLVolumeCollection &); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func = nullptr); | ||||||
|  | 
 | ||||||
| class GLModel | class GLModel | ||||||
| { | { | ||||||
| protected: | protected: | ||||||
|  |  | ||||||
|  | @ -3232,12 +3232,37 @@ bool GLCanvas3D::_init_toolbar() | ||||||
|     if (!m_toolbar.add_separator()) |     if (!m_toolbar.add_separator()) | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|  |     item.name = "copy"; | ||||||
|  | #if ENABLE_SVG_ICONS | ||||||
|  |     item.icon_filename = "copy.svg"; | ||||||
|  | #endif // ENABLE_SVG_ICONS
 | ||||||
|  |     item.tooltip = GUI::L_str("Copy") + " [" + GUI::shortkey_ctrl_prefix() + "C]"; | ||||||
|  |     item.sprite_id = 4; | ||||||
|  |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); }; | ||||||
|  |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_copy(); }; | ||||||
|  |     if (!m_toolbar.add_item(item)) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     item.name = "paste"; | ||||||
|  | #if ENABLE_SVG_ICONS | ||||||
|  |     item.icon_filename = "paste.svg"; | ||||||
|  | #endif // ENABLE_SVG_ICONS
 | ||||||
|  |     item.tooltip = GUI::L_str("Paste") + " [" + GUI::shortkey_ctrl_prefix() + "V]"; | ||||||
|  |     item.sprite_id = 5; | ||||||
|  |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); }; | ||||||
|  |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_paste(); }; | ||||||
|  |     if (!m_toolbar.add_item(item)) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     if (!m_toolbar.add_separator()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|     item.name = "more"; |     item.name = "more"; | ||||||
| #if ENABLE_SVG_ICONS | #if ENABLE_SVG_ICONS | ||||||
|     item.icon_filename = "instance_add.svg"; |     item.icon_filename = "instance_add.svg"; | ||||||
| #endif // ENABLE_SVG_ICONS
 | #endif // ENABLE_SVG_ICONS
 | ||||||
|     item.tooltip = GUI::L_str("Add instance [+]"); |     item.tooltip = GUI::L_str("Add instance [+]"); | ||||||
|     item.sprite_id = 4; |     item.sprite_id = 6; | ||||||
|     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); }; |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); }; | ||||||
|     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; |     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; | ||||||
|     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); }; |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); }; | ||||||
|  | @ -3249,7 +3274,7 @@ bool GLCanvas3D::_init_toolbar() | ||||||
|     item.icon_filename = "instance_remove.svg"; |     item.icon_filename = "instance_remove.svg"; | ||||||
| #endif // ENABLE_SVG_ICONS
 | #endif // ENABLE_SVG_ICONS
 | ||||||
|     item.tooltip = GUI::L_str("Remove instance [-]"); |     item.tooltip = GUI::L_str("Remove instance [-]"); | ||||||
|     item.sprite_id = 5; |     item.sprite_id = 7; | ||||||
|     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); }; |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); }; | ||||||
|     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; |     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; | ||||||
|     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); }; |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); }; | ||||||
|  | @ -3264,7 +3289,7 @@ bool GLCanvas3D::_init_toolbar() | ||||||
|     item.icon_filename = "split_objects.svg"; |     item.icon_filename = "split_objects.svg"; | ||||||
| #endif // ENABLE_SVG_ICONS
 | #endif // ENABLE_SVG_ICONS
 | ||||||
|     item.tooltip = GUI::L_str("Split to objects"); |     item.tooltip = GUI::L_str("Split to objects"); | ||||||
|     item.sprite_id = 6; |     item.sprite_id = 8; | ||||||
|     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); }; |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); }; | ||||||
|     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback; |     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback; | ||||||
|     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); }; |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); }; | ||||||
|  | @ -3276,7 +3301,7 @@ bool GLCanvas3D::_init_toolbar() | ||||||
|     item.icon_filename = "split_parts.svg"; |     item.icon_filename = "split_parts.svg"; | ||||||
| #endif // ENABLE_SVG_ICONS
 | #endif // ENABLE_SVG_ICONS
 | ||||||
|     item.tooltip = GUI::L_str("Split to parts"); |     item.tooltip = GUI::L_str("Split to parts"); | ||||||
|     item.sprite_id = 7; |     item.sprite_id = 9; | ||||||
|     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); }; |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); }; | ||||||
|     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; |     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; }; | ||||||
|     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); }; |     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); }; | ||||||
|  | @ -3291,7 +3316,7 @@ bool GLCanvas3D::_init_toolbar() | ||||||
|     item.icon_filename = "layers.svg"; |     item.icon_filename = "layers.svg"; | ||||||
| #endif // ENABLE_SVG_ICONS
 | #endif // ENABLE_SVG_ICONS
 | ||||||
|     item.tooltip = GUI::L_str("Layers editing"); |     item.tooltip = GUI::L_str("Layers editing"); | ||||||
|     item.sprite_id = 8; |     item.sprite_id = 10; | ||||||
|     item.is_toggable = true; |     item.is_toggable = true; | ||||||
|     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); }; |     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); }; | ||||||
|     item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; }; |     item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; }; | ||||||
|  | @ -3501,7 +3526,7 @@ void GLCanvas3D::_picking_pass() const | ||||||
|             ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); |             ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); | ||||||
|             ::glEnable(GL_CLIP_PLANE0); |             ::glEnable(GL_CLIP_PLANE0); | ||||||
|         } |         } | ||||||
|         _render_volumes(true); |         _render_volumes_for_picking(); | ||||||
|         if (! m_use_VBOs) |         if (! m_use_VBOs) | ||||||
|             ::glDisable(GL_CLIP_PLANE0); |             ::glDisable(GL_CLIP_PLANE0); | ||||||
| 
 | 
 | ||||||
|  | @ -3702,13 +3727,10 @@ void GLCanvas3D::_render_legend_texture() const | ||||||
|     m_legend_texture.render(*this); |     m_legend_texture.render(*this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GLCanvas3D::_render_volumes(bool fake_colors) const | void GLCanvas3D::_render_volumes_for_picking() const | ||||||
| { | { | ||||||
|     static const GLfloat INV_255 = 1.0f / 255.0f; |     static const GLfloat INV_255 = 1.0f / 255.0f; | ||||||
| 
 | 
 | ||||||
|     if (!fake_colors) |  | ||||||
|         glsafe(::glEnable(GL_LIGHTING)); |  | ||||||
| 
 |  | ||||||
|     // do not cull backfaces to show broken geometry, if any
 |     // do not cull backfaces to show broken geometry, if any
 | ||||||
|     glsafe(::glDisable(GL_CULL_FACE)); |     glsafe(::glDisable(GL_CULL_FACE)); | ||||||
| 
 | 
 | ||||||
|  | @ -3718,27 +3740,31 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const | ||||||
|     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); |     glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); | ||||||
|     glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); |     glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); | ||||||
| 
 | 
 | ||||||
|     unsigned int volume_id = 0; |     const Transform3d& view_matrix = m_camera.get_view_matrix(); | ||||||
|     for (GLVolume* vol : m_volumes.volumes) |     GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Opaque, view_matrix); | ||||||
|  |     for (const GLVolumeWithIdAndZ& volume : to_render) | ||||||
|     { |     { | ||||||
|         if (fake_colors) |         // Object picking mode. Render the object with a color encoding the object index.
 | ||||||
|         { |         unsigned int r = (volume.second.first & 0x000000FF) >> 0; | ||||||
|             // Object picking mode. Render the object with a color encoding the object index.
 |         unsigned int g = (volume.second.first & 0x0000FF00) >> 8; | ||||||
|             unsigned int r = (volume_id & 0x000000FF) >> 0; |         unsigned int b = (volume.second.first & 0x00FF0000) >> 16; | ||||||
|             unsigned int g = (volume_id & 0x0000FF00) >> 8; |         glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); | ||||||
|             unsigned int b = (volume_id & 0x00FF0000) >> 16; |  | ||||||
|             glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             vol->set_render_color(); |  | ||||||
|             glsafe(::glColor4fv(vol->render_color)); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         if ((!fake_colors || !vol->disabled) && (vol->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) |         if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) | ||||||
|             vol->render(); |             volume.first->render(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         ++volume_id; |     to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Transparent, view_matrix); | ||||||
|  |     for (const GLVolumeWithIdAndZ& volume : to_render) | ||||||
|  |     { | ||||||
|  |         // Object picking mode. Render the object with a color encoding the object index.
 | ||||||
|  |         unsigned int r = (volume.second.first & 0x000000FF) >> 0; | ||||||
|  |         unsigned int g = (volume.second.first & 0x0000FF00) >> 8; | ||||||
|  |         unsigned int b = (volume.second.first & 0x00FF0000) >> 16; | ||||||
|  |         glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); | ||||||
|  | 
 | ||||||
|  |         if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) | ||||||
|  |             volume.first->render(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); |     glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); | ||||||
|  | @ -3746,9 +3772,6 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const | ||||||
|     glsafe(::glDisable(GL_BLEND)); |     glsafe(::glDisable(GL_BLEND)); | ||||||
| 
 | 
 | ||||||
|     glsafe(::glEnable(GL_CULL_FACE)); |     glsafe(::glEnable(GL_CULL_FACE)); | ||||||
| 
 |  | ||||||
|     if (!fake_colors) |  | ||||||
|         glsafe(::glDisable(GL_LIGHTING)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GLCanvas3D::_render_current_gizmo() const | void GLCanvas3D::_render_current_gizmo() const | ||||||
|  | @ -4026,15 +4049,9 @@ void GLCanvas3D::_update_volumes_hover_state() const | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     GLVolume* volume = m_volumes.volumes[m_hover_volume_id]; |     GLVolume* volume = m_volumes.volumes[m_hover_volume_id]; | ||||||
| 
 |     if (volume->is_modifier) | ||||||
|     switch (m_selection.get_mode()) |  | ||||||
|     { |  | ||||||
|     case Selection::Volume: |  | ||||||
|     { |  | ||||||
|         volume->hover = true; |         volume->hover = true; | ||||||
|         break; |     else | ||||||
|     } |  | ||||||
|     case Selection::Instance: |  | ||||||
|     { |     { | ||||||
|         int object_idx = volume->object_idx(); |         int object_idx = volume->object_idx(); | ||||||
|         int instance_idx = volume->instance_idx(); |         int instance_idx = volume->instance_idx(); | ||||||
|  | @ -4044,9 +4061,6 @@ void GLCanvas3D::_update_volumes_hover_state() const | ||||||
|             if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) |             if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) | ||||||
|                 v->hover = true; |                 v->hover = true; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -609,7 +609,7 @@ private: | ||||||
| #endif // ENABLE_RENDER_SELECTION_CENTER
 | #endif // ENABLE_RENDER_SELECTION_CENTER
 | ||||||
|     void _render_warning_texture() const; |     void _render_warning_texture() const; | ||||||
|     void _render_legend_texture() const; |     void _render_legend_texture() const; | ||||||
|     void _render_volumes(bool fake_colors) const; |     void _render_volumes_for_picking() const; | ||||||
|     void _render_current_gizmo() const; |     void _render_current_gizmo() const; | ||||||
|     void _render_gizmos_overlay() const; |     void _render_gizmos_overlay() const; | ||||||
|     void _render_toolbar() const; |     void _render_toolbar() const; | ||||||
|  |  | ||||||
|  | @ -21,6 +21,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); | ||||||
|  | wxDEFINE_EVENT(EVT_GLTOOLBAR_COPY, SimpleEvent); | ||||||
|  | wxDEFINE_EVENT(EVT_GLTOOLBAR_PASTE, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); | ||||||
| wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); | wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); | ||||||
|  |  | ||||||
|  | @ -20,6 +20,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); | ||||||
|  | wxDECLARE_EVENT(EVT_GLTOOLBAR_COPY, SimpleEvent); | ||||||
|  | wxDECLARE_EVENT(EVT_GLTOOLBAR_PASTE, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); | ||||||
| wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); | wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); | ||||||
|  |  | ||||||
|  | @ -439,6 +439,66 @@ void ObjectList::selection_changed() | ||||||
|     part_selection_changed(); |     part_selection_changed(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes) | ||||||
|  | { | ||||||
|  |     if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (volumes.empty()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     ModelObject& model_object = *(*m_objects)[obj_idx]; | ||||||
|  |     const auto object_item = m_objects_model->GetItemById(obj_idx); | ||||||
|  | 
 | ||||||
|  |     wxDataViewItemArray items; | ||||||
|  | 
 | ||||||
|  |     for (const ModelVolume* volume : volumes) | ||||||
|  |     { | ||||||
|  |         auto vol_item = m_objects_model->AddVolumeChild(object_item, volume->name, volume->type(), | ||||||
|  |             volume->config.has("extruder") ? volume->config.option<ConfigOptionInt>("extruder")->value : 0); | ||||||
|  |         auto opt_keys = volume->config.keys(); | ||||||
|  |         if (!opt_keys.empty() && !((opt_keys.size() == 1) && (opt_keys[0] == "extruder"))) | ||||||
|  |             select_item(m_objects_model->AddSettingsChild(vol_item)); | ||||||
|  | 
 | ||||||
|  |         items.Add(vol_item); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     m_parts_changed = true; | ||||||
|  |     parts_changed(obj_idx); | ||||||
|  | 
 | ||||||
|  |     if (items.size() > 1) | ||||||
|  |     { | ||||||
|  |         m_selection_mode = smVolume; | ||||||
|  |         m_last_selected_item = wxDataViewItem(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     select_items(items); | ||||||
|  | #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||||
|  |     selection_changed(); | ||||||
|  | #endif //no __WXOSX__ //__WXMSW__
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ObjectList::paste_objects_into_list(const std::vector<size_t>& object_idxs) | ||||||
|  | { | ||||||
|  |     if (object_idxs.empty()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     wxDataViewItemArray items; | ||||||
|  |     for (const size_t object : object_idxs) | ||||||
|  |     { | ||||||
|  |         add_object_to_list(object); | ||||||
|  |         m_parts_changed = true; | ||||||
|  |         parts_changed(object); | ||||||
|  | 
 | ||||||
|  |         items.Add(m_objects_model->GetItemById(object)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     select_items(items); | ||||||
|  | #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
 | ||||||
|  |     selection_changed(); | ||||||
|  | #endif //no __WXOSX__ //__WXMSW__
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ObjectList::OnChar(wxKeyEvent& event) | void ObjectList::OnChar(wxKeyEvent& event) | ||||||
| { | { | ||||||
|     if (event.GetKeyCode() == WXK_BACK){ |     if (event.GetKeyCode() == WXK_BACK){ | ||||||
|  | @ -1576,11 +1636,11 @@ void ObjectList::split() | ||||||
| 
 | 
 | ||||||
|     for (auto id = 0; id < model_object->volumes.size(); id++) { |     for (auto id = 0; id < model_object->volumes.size(); id++) { | ||||||
|         const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name), |         const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name), | ||||||
|                                             model_object->volumes[id]->is_modifier() ?  |             model_object->volumes[id]->is_modifier() ? | ||||||
|                                                 ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, |             ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, | ||||||
|                                             model_object->volumes[id]->config.has("extruder") ? |             model_object->volumes[id]->config.has("extruder") ? | ||||||
|                                                 model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0, |             model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0, | ||||||
|                                             false); |             false); | ||||||
|         // add settings to the part, if it has those
 |         // add settings to the part, if it has those
 | ||||||
|         auto opt_keys = model_object->volumes[id]->config.keys(); |         auto opt_keys = model_object->volumes[id]->config.keys(); | ||||||
|         if ( !(opt_keys.size() == 1 && opt_keys[0] == "extruder") ) { |         if ( !(opt_keys.size() == 1 && opt_keys[0] == "extruder") ) { | ||||||
|  | @ -2135,6 +2195,7 @@ void ObjectList::update_selections_on_canvas() | ||||||
|         add_to_selection(item, selection, instance_idx, false); |         add_to_selection(item, selection, instance_idx, false); | ||||||
| 
 | 
 | ||||||
|     wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state(); |     wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state(); | ||||||
|  |     wxGetApp().plater()->canvas3D()->render(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ObjectList::select_item(const wxDataViewItem& item) | void ObjectList::select_item(const wxDataViewItem& item) | ||||||
|  |  | ||||||
|  | @ -31,6 +31,8 @@ typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle; | ||||||
| //				  category ->		vector 			 ( option	;  label )
 | //				  category ->		vector 			 ( option	;  label )
 | ||||||
| typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy; | typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy; | ||||||
| 
 | 
 | ||||||
|  | typedef std::vector<ModelVolume*> ModelVolumePtrs; | ||||||
|  | 
 | ||||||
| namespace GUI { | namespace GUI { | ||||||
| 
 | 
 | ||||||
| wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); | wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); | ||||||
|  | @ -285,6 +287,10 @@ public: | ||||||
|     void rename_item(); |     void rename_item(); | ||||||
|     void fix_through_netfabb() const; |     void fix_through_netfabb() const; | ||||||
|     void update_item_error_icon(const int obj_idx, int vol_idx) const ; |     void update_item_error_icon(const int obj_idx, int vol_idx) const ; | ||||||
|  | 
 | ||||||
|  |     void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); | ||||||
|  |     void paste_objects_into_list(const std::vector<size_t>& object_idxs); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     void OnChar(wxKeyEvent& event); |     void OnChar(wxKeyEvent& event); | ||||||
|     void OnContextMenu(wxDataViewEvent &event); |     void OnContextMenu(wxDataViewEvent &event); | ||||||
|  |  | ||||||
|  | @ -375,13 +375,22 @@ void MainFrame::init_menubar() | ||||||
|             [this](wxCommandEvent&) { m_plater->select_all(); }, ""); |             [this](wxCommandEvent&) { m_plater->select_all(); }, ""); | ||||||
|         editMenu->AppendSeparator(); |         editMenu->AppendSeparator(); | ||||||
|         wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, _(L("Deletes the current selection")), |         wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, _(L("Deletes the current selection")), | ||||||
|             [this](wxCommandEvent&) { m_plater->remove_selected(); }, ""); |             [this](wxCommandEvent&) { m_plater->remove_selected(); }, "remove_menu"); | ||||||
|         wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")), |         wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")), | ||||||
|             [this](wxCommandEvent&) { m_plater->reset(); }, ""); |             [this](wxCommandEvent&) { m_plater->reset(); }, "delete_all_menu"); | ||||||
|  | 
 | ||||||
|  |         editMenu->AppendSeparator(); | ||||||
|  | 
 | ||||||
|  |         wxMenuItem* item_copy = append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + "\tCtrl+C", _(L("Copy selection to clipboard")), | ||||||
|  |             [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, "copy_menu"); | ||||||
|  |         wxMenuItem* item_paste = append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + "\tCtrl+V", _(L("Paste clipboard")), | ||||||
|  |             [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, "paste_menu"); | ||||||
| 
 | 
 | ||||||
|         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); |         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); | ||||||
|         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId()); |         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId()); | ||||||
|         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId()); |         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId()); | ||||||
|  |         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_copy()); }, item_copy->GetId()); | ||||||
|  |         Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_paste()); }, item_paste->GetId()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Window menu
 |     // Window menu
 | ||||||
|  |  | ||||||
|  | @ -1405,6 +1405,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); }); |     view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); }); | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); |     view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); |     view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); | ||||||
|  |     view3D_canvas->Bind(EVT_GLTOOLBAR_COPY, [q](SimpleEvent&) { q->copy_selection_to_clipboard(); }); | ||||||
|  |     view3D_canvas->Bind(EVT_GLTOOLBAR_PASTE, [q](SimpleEvent&) { q->paste_from_clipboard(); }); | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); |     view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); |     view3D_canvas->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); | ||||||
|     view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this); |     view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this); | ||||||
|  | @ -3699,6 +3701,34 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) | ||||||
| 
 | 
 | ||||||
| void Plater::update_object_menu() { p->update_object_menu(); } | void Plater::update_object_menu() { p->update_object_menu(); } | ||||||
| 
 | 
 | ||||||
|  | void Plater::copy_selection_to_clipboard() | ||||||
|  | { | ||||||
|  |     p->view3D->get_canvas3d()->get_selection().copy_to_clipboard(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Plater::paste_from_clipboard() | ||||||
|  | { | ||||||
|  |     p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Plater::can_paste_from_clipboard() const | ||||||
|  | { | ||||||
|  |     const Selection& selection = p->view3D->get_canvas3d()->get_selection(); | ||||||
|  |     const Selection::Clipboard& clipboard = selection.get_clipboard(); | ||||||
|  |     Selection::EMode mode = clipboard.get_mode(); | ||||||
|  | 
 | ||||||
|  |     if (clipboard.is_empty()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     if ((mode == Selection::Volume) && !selection.is_from_single_instance()) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     if ((mode == Selection::Instance) && (selection.get_mode() != Selection::Instance)) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool Plater::can_delete() const { return p->can_delete(); } | bool Plater::can_delete() const { return p->can_delete(); } | ||||||
| bool Plater::can_delete_all() const { return p->can_delete_all(); } | bool Plater::can_delete_all() const { return p->can_delete_all(); } | ||||||
| bool Plater::can_increase_instances() const { return p->can_increase_instances(); } | bool Plater::can_increase_instances() const { return p->can_increase_instances(); } | ||||||
|  | @ -3707,5 +3737,7 @@ bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); } | ||||||
| bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } | bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } | ||||||
| bool Plater::can_arrange() const { return p->can_arrange(); } | bool Plater::can_arrange() const { return p->can_arrange(); } | ||||||
| bool Plater::can_layers_editing() const { return p->can_layers_editing(); } | bool Plater::can_layers_editing() const { return p->can_layers_editing(); } | ||||||
|  | bool Plater::can_copy() const { return !is_selection_empty(); } | ||||||
|  | bool Plater::can_paste() const { return can_paste_from_clipboard(); } | ||||||
| 
 | 
 | ||||||
| }}    // namespace Slic3r::GUI
 | }}    // namespace Slic3r::GUI
 | ||||||
|  |  | ||||||
|  | @ -182,6 +182,10 @@ public: | ||||||
|     PrinterTechnology   printer_technology() const; |     PrinterTechnology   printer_technology() const; | ||||||
|     void                set_printer_technology(PrinterTechnology printer_technology); |     void                set_printer_technology(PrinterTechnology printer_technology); | ||||||
| 
 | 
 | ||||||
|  |     void copy_selection_to_clipboard(); | ||||||
|  |     void paste_from_clipboard(); | ||||||
|  |     bool can_paste_from_clipboard() const; | ||||||
|  | 
 | ||||||
|     bool can_delete() const; |     bool can_delete() const; | ||||||
|     bool can_delete_all() const; |     bool can_delete_all() const; | ||||||
|     bool can_increase_instances() const; |     bool can_increase_instances() const; | ||||||
|  | @ -190,6 +194,8 @@ public: | ||||||
|     bool can_split_to_volumes() const; |     bool can_split_to_volumes() const; | ||||||
|     bool can_arrange() const; |     bool can_arrange() const; | ||||||
|     bool can_layers_editing() const; |     bool can_layers_editing() const; | ||||||
|  |     bool can_copy() const; | ||||||
|  |     bool can_paste() const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     struct priv; |     struct priv; | ||||||
|  |  | ||||||
|  | @ -1022,6 +1022,70 @@ bool Selection::requires_local_axes() const | ||||||
|     return (m_mode == Volume) && is_from_single_instance(); |     return (m_mode == Volume) && is_from_single_instance(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Selection::copy_to_clipboard() | ||||||
|  | { | ||||||
|  |     if (!m_valid) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     m_clipboard.reset(); | ||||||
|  | 
 | ||||||
|  |     for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) | ||||||
|  |     { | ||||||
|  |         ModelObject* src_object = m_model->objects[object.first]; | ||||||
|  |         ModelObject* dst_object = m_clipboard.add_object(); | ||||||
|  |         dst_object->name = src_object->name; | ||||||
|  |         dst_object->input_file = src_object->input_file; | ||||||
|  |         dst_object->config = src_object->config; | ||||||
|  | 
 | ||||||
|  |         for (int i : object.second) | ||||||
|  |         { | ||||||
|  |             dst_object->add_instance(*src_object->instances[i]); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (unsigned int i : m_list) | ||||||
|  |         { | ||||||
|  |             const GLVolume* volume = (*m_volumes)[i]; | ||||||
|  |             if ((volume->object_idx() == object.first) && (volume->instance_idx() == *object.second.begin())) | ||||||
|  |             { | ||||||
|  |                 int volume_idx = volume->volume_idx(); | ||||||
|  |                 if ((0 <= volume_idx) && (volume_idx < (int)src_object->volumes.size())) | ||||||
|  |                 { | ||||||
|  |                     ModelVolume* src_volume = src_object->volumes[volume_idx]; | ||||||
|  |                     ModelVolume* dst_volume = dst_object->add_volume(*src_volume); | ||||||
|  |                     dst_volume->set_new_unique_id(); | ||||||
|  |                     dst_volume->config = src_volume->config; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     m_clipboard.set_mode(m_mode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Selection::paste_from_clipboard() | ||||||
|  | { | ||||||
|  |     if (!m_valid || m_clipboard.is_empty()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     switch (m_clipboard.get_mode()) | ||||||
|  |     { | ||||||
|  |     case Volume: | ||||||
|  |     { | ||||||
|  |         if (is_from_single_instance()) | ||||||
|  |             paste_volumes_from_clipboard(); | ||||||
|  | 
 | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     case Instance: | ||||||
|  |     { | ||||||
|  |         if (m_mode == Instance) | ||||||
|  |             paste_objects_from_clipboard(); | ||||||
|  | 
 | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Selection::update_valid() | void Selection::update_valid() | ||||||
| { | { | ||||||
|     m_valid = (m_volumes != nullptr) && (m_model != nullptr); |     m_valid = (m_volumes != nullptr) && (m_model != nullptr); | ||||||
|  | @ -1697,5 +1761,43 @@ bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const | ||||||
|     return count == (unsigned int)m_model->objects[object_idx]->volumes.size(); |     return count == (unsigned int)m_model->objects[object_idx]->volumes.size(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Selection::paste_volumes_from_clipboard() | ||||||
|  | { | ||||||
|  |     int obj_idx = get_object_idx(); | ||||||
|  |     if ((obj_idx < 0) || ((int)m_model->objects.size() <= obj_idx)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     ModelObject* src_object = m_clipboard.get_object(0); | ||||||
|  |     if (src_object != nullptr) | ||||||
|  |     { | ||||||
|  |         ModelObject* dst_object = m_model->objects[obj_idx]; | ||||||
|  | 
 | ||||||
|  |         ModelVolumePtrs volumes; | ||||||
|  |         for (ModelVolume* src_volume : src_object->volumes) | ||||||
|  |         { | ||||||
|  |             ModelVolume* dst_volume = dst_object->add_volume(*src_volume); | ||||||
|  |             dst_volume->config = src_volume->config; | ||||||
|  |             dst_volume->set_new_unique_id(); | ||||||
|  |             dst_volume->translate(10.0, 10.0, 0.0); | ||||||
|  |             volumes.push_back(dst_volume); | ||||||
|  |         } | ||||||
|  |         wxGetApp().obj_list()->paste_volumes_into_list(obj_idx, volumes); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Selection::paste_objects_from_clipboard() | ||||||
|  | { | ||||||
|  |     std::vector<size_t> object_idxs; | ||||||
|  |     const ModelObjectPtrs& src_objects = m_clipboard.get_objects(); | ||||||
|  |     for (const ModelObject* src_object : src_objects) | ||||||
|  |     { | ||||||
|  |         ModelObject* dst_object = m_model->add_object(*src_object); | ||||||
|  |         dst_object->translate(10.0, 10.0, 0.0); | ||||||
|  |         object_idxs.push_back(m_model->objects.size() - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     wxGetApp().obj_list()->paste_objects_into_list(object_idxs); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace GUI
 | } // namespace GUI
 | ||||||
| } // namespace Slic3r
 | } // namespace Slic3r
 | ||||||
|  |  | ||||||
|  | @ -138,6 +138,23 @@ public: | ||||||
|     typedef std::set<int> InstanceIdxsList; |     typedef std::set<int> InstanceIdxsList; | ||||||
|     typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap; |     typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap; | ||||||
| 
 | 
 | ||||||
|  |     class Clipboard | ||||||
|  |     { | ||||||
|  |         Model m_model; | ||||||
|  |         Selection::EMode m_mode; | ||||||
|  | 
 | ||||||
|  |     public: | ||||||
|  |         void reset() { m_model.clear_objects(); } | ||||||
|  |         bool is_empty() const { return m_model.objects.empty(); } | ||||||
|  | 
 | ||||||
|  |         ModelObject* add_object() { return m_model.add_object(); } | ||||||
|  |         ModelObject* get_object(unsigned int id) { return (id < (unsigned int)m_model.objects.size()) ? m_model.objects[id] : nullptr; } | ||||||
|  |         const ModelObjectPtrs& get_objects() const { return m_model.objects; } | ||||||
|  | 
 | ||||||
|  |         Selection::EMode get_mode() const { return m_mode; } | ||||||
|  |         void set_mode(Selection::EMode mode) { m_mode = mode; } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     struct Cache |     struct Cache | ||||||
|     { |     { | ||||||
|  | @ -163,6 +180,7 @@ private: | ||||||
|     // set of indices to m_volumes
 |     // set of indices to m_volumes
 | ||||||
|     IndicesList m_list; |     IndicesList m_list; | ||||||
|     Cache m_cache; |     Cache m_cache; | ||||||
|  |     Clipboard m_clipboard; | ||||||
|     mutable BoundingBoxf3 m_bounding_box; |     mutable BoundingBoxf3 m_bounding_box; | ||||||
|     mutable bool m_bounding_box_dirty; |     mutable bool m_bounding_box_dirty; | ||||||
| 
 | 
 | ||||||
|  | @ -267,6 +285,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     bool requires_local_axes() const; |     bool requires_local_axes() const; | ||||||
| 
 | 
 | ||||||
|  |     void copy_to_clipboard(); | ||||||
|  |     void paste_from_clipboard(); | ||||||
|  | 
 | ||||||
|  |     const Clipboard& get_clipboard() const { return m_clipboard; } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     void update_valid(); |     void update_valid(); | ||||||
|     void update_type(); |     void update_type(); | ||||||
|  | @ -301,6 +324,9 @@ private: | ||||||
|     void synchronize_unselected_volumes(); |     void synchronize_unselected_volumes(); | ||||||
|     void ensure_on_bed(); |     void ensure_on_bed(); | ||||||
|     bool is_from_fully_selected_instance(unsigned int volume_idx) const; |     bool is_from_fully_selected_instance(unsigned int volume_idx) const; | ||||||
|  | 
 | ||||||
|  |     void paste_volumes_from_clipboard(); | ||||||
|  |     void paste_objects_from_clipboard(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace GUI
 | } // namespace GUI
 | ||||||
|  |  | ||||||
|  | @ -529,10 +529,10 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int ext | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, | wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, | ||||||
| 													const wxString &name, |     const wxString &name, | ||||||
|                                                     const Slic3r::ModelVolumeType volume_type, |     const Slic3r::ModelVolumeType volume_type, | ||||||
|                                                     const int extruder/* = 0*/, |     const int extruder/* = 0*/, | ||||||
|                                                     const bool create_frst_child/* = true*/) |     const bool create_frst_child/* = true*/) | ||||||
| { | { | ||||||
| 	PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); | 	PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); | ||||||
| 	if (!root) return wxDataViewItem(0); | 	if (!root) return wxDataViewItem(0); | ||||||
|  | @ -545,7 +545,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &pa | ||||||
|         insert_position = -1; |         insert_position = -1; | ||||||
| 
 | 
 | ||||||
|     if (create_frst_child && root->m_volumes_cnt == 0) |     if (create_frst_child && root->m_volumes_cnt == 0) | ||||||
| 	{ |     { | ||||||
| 		const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, *m_volume_bmps[0], extruder_str, 0); | 		const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, *m_volume_bmps[0], extruder_str, 0); | ||||||
|         insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); |         insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); | ||||||
| 		// notify control
 | 		// notify control
 | ||||||
|  |  | ||||||
|  | @ -454,12 +454,12 @@ public: | ||||||
|     ~PrusaObjectDataViewModel(); |     ~PrusaObjectDataViewModel(); | ||||||
| 
 | 
 | ||||||
| 	wxDataViewItem Add(const wxString &name, const int extruder); | 	wxDataViewItem Add(const wxString &name, const int extruder); | ||||||
| 	wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item,  |     wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, | ||||||
| 							const wxString &name,  |         const wxString &name, | ||||||
|                             const Slic3r::ModelVolumeType volume_type, |         const Slic3r::ModelVolumeType volume_type, | ||||||
|                             const int extruder = 0, |         const int extruder = 0, | ||||||
|                             const bool create_frst_child = true); |         const bool create_frst_child = true); | ||||||
| 	wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); |     wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); | ||||||
|     wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); |     wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); | ||||||
| 	wxDataViewItem Delete(const wxDataViewItem &item); | 	wxDataViewItem Delete(const wxDataViewItem &item); | ||||||
| 	wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); | 	wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv