New icons (#1287)
## Description: Add a new pixi layer for rendering structure icons Add new sprites for structures  ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: Vivacious Box --------- Co-authored-by: evanpelle <evanpelle@gmail.com>
@@ -48,6 +48,7 @@
|
||||
"nanoid": "^3.3.6",
|
||||
"obscenity": "^0.4.3",
|
||||
"pg": "^8.13.3",
|
||||
"pixi.js": "^8.10.1",
|
||||
"prom-client": "^15.1.3",
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
@@ -7944,6 +7945,12 @@
|
||||
"node": "^18.19.0 || >=20.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pixi/colord": {
|
||||
"version": "2.9.6",
|
||||
"resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz",
|
||||
"integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@@ -8995,6 +9002,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/css-font-loading-module": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.12.tgz",
|
||||
"integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/d3": {
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
|
||||
@@ -9279,6 +9292,12 @@
|
||||
"@types/d3-selection": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/earcut": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-3.0.0.tgz",
|
||||
"integrity": "sha512-k/9fOUGO39yd2sCjrbAJvGDEQvRwRnQIZlBz43roGwUZo5SHAmyVvSFyaVVZkicRVCaDXPKlbxrUcBuJoSWunQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
@@ -10388,6 +10407,12 @@
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@webgpu/types": {
|
||||
"version": "0.1.61",
|
||||
"resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.61.tgz",
|
||||
"integrity": "sha512-w2HbBvH+qO19SB5pJOJFKs533CdZqxl3fcGonqL321VHkW7W/iBo6H8bjDy6pr/+pbMwIu5dnuaAxH7NxBqUrQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@webpack-cli/configtest": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz",
|
||||
@@ -10432,6 +10457,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.10",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
|
||||
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
@@ -13026,6 +13060,12 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/earcut": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz",
|
||||
"integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@@ -13697,7 +13737,6 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/events": {
|
||||
@@ -14572,6 +14611,15 @@
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/gifuct-js": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/gifuct-js/-/gifuct-js-2.1.2.tgz",
|
||||
"integrity": "sha512-rI2asw77u0mGgwhV3qA+OEgYqaDn5UNqgs+Bx0FGwSpuqfYn+Ir6RQY5ENNQ8SbIiG/m5gVa7CD5RriO4f4Lsg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-binary-schema-parser": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/gifwrap": {
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
|
||||
@@ -15647,6 +15695,12 @@
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ismobilejs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
|
||||
"integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/isobject": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
@@ -17555,6 +17609,12 @@
|
||||
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/js-binary-schema-parser": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
|
||||
"integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@@ -19228,6 +19288,12 @@
|
||||
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-svg-path": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
|
||||
"integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
|
||||
@@ -19533,6 +19599,28 @@
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pixi.js": {
|
||||
"version": "8.10.1",
|
||||
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.10.1.tgz",
|
||||
"integrity": "sha512-wjKJXawhTUxuyKIuwE3jK05eBh5I4GKy+YrRVniURFRkK7pYEvRvnV41dEqz6owSXav/YMXdG5783YDJeamiow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pixi/colord": "^2.9.6",
|
||||
"@types/css-font-loading-module": "^0.0.12",
|
||||
"@types/earcut": "^3.0.0",
|
||||
"@webgpu/types": "^0.1.40",
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
"earcut": "^3.0.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"gifuct-js": "^2.1.2",
|
||||
"ismobilejs": "^1.1.1",
|
||||
"parse-svg-path": "^0.1.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/pixijs"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
"nanoid": "^3.3.6",
|
||||
"obscenity": "^0.4.3",
|
||||
"pg": "^8.13.3",
|
||||
"pixi.js": "^8.10.1",
|
||||
"prom-client": "^15.1.3",
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
|
||||
|
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 221 B |
@@ -3,8 +3,6 @@
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="800px"
|
||||
height="800px"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -1,5 +1,43 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" fill="#FFF" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M 382.702 195.718 L 384 153.6 L 384 102.4 L 320 153.6 L 269.5 194 L 255.568 194.854 L 256 153.6 L 256 102.4 L 192 153.6 L 143.191 191.818 L 128 191.674 L 128 128 L 128 72.215 L 111.057 51.805 L 64 51.2 L 21.179 51.2 L 0 74.4 L 0 256 L 0 460.8 L 256 460.8 L 512 460.8 L 512 281.6 L 512 102.4 L 448 153.6 L 396.932 194.367 L 382.702 195.718 Z M 179.2 384 L 153.6 384 L 128 384 L 128 345.6 L 128 307.2 C 127.777 306.306 138.701 301.558 144.203 301.359 C 148.36 301.209 154.679 301.411 161.651 301.552 C 168.881 301.698 178.003 306.906 179.2 307.2 L 179.2 345.6 L 179.2 384 Z M 307.2 384 L 281.6 384 L 256 384 L 256 345.6 L 256 307.2 L 271.48 300.354 L 289.861 300.122 L 307.2 307.2 L 307.2 345.6 L 307.2 384 Z M 435.2 384 L 409.6 384 L 384 384 L 384 345.6 L 384 307.2 L 399.183 300.354 L 417.852 300.289 L 435.2 307.2 L 435.2 345.6 L 435.2 384 Z" transform="matrix(1, 0, 0, 1, 6.528259374621939, -25.993545919560574)"/>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 32 32"
|
||||
fill="#ffffff"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="FactoryIconWhite.svg"
|
||||
width="32"
|
||||
height="32"
|
||||
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#5d5d5d"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="6.0390625"
|
||||
inkscape:cx="57.956016"
|
||||
inkscape:cy="54.727038"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<g
|
||||
id="g1">
|
||||
<path
|
||||
d="m 23.203054,12.861316 0.07072,-2.415754 V 7.5088935 l -3.487177,2.9366685 -2.751603,2.317216 -0.759116,0.04898 0.02354,-2.3662 V 7.5088935 l -3.487181,2.9366685 -2.659468,2.192064 -0.8277125,-0.0083 V 8.9772305 5.7775778 L 8.4018789,4.6069268 5.8378723,4.5722089 H 3.504675 L 2.350691,5.9028882 V 16.318899 28.065575 H 16.299415 30.248143 V 17.787234 7.5088935 l -3.487181,2.9366685 -2.782554,2.338265 z M 12.114798,23.660571 H 10.719925 9.3250543 v -2.202501 -2.2025 c -0.012167,-0.05128 0.583066,-0.323608 0.8828537,-0.335023 0.226503,-0.0086 0.57081,0.0029 0.950693,0.01108 0.393944,0.0084 0.890977,0.307088 0.956197,0.323952 v 2.202501 z m 6.974362,0 h -1.394871 -1.394874 v -2.202501 -2.2025 l 0.843464,-0.392665 1.001527,-0.01333 0.944754,0.405974 v 2.202501 z m 6.974365,0 h -1.394873 -1.394874 v -2.202501 -2.2025 l 0.827282,-0.392665 1.017219,-0.0037 0.945246,0.396393 v 2.2025 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.0559037" />
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 310 B |
@@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
height="800px"
|
||||
width="800px"
|
||||
version="1.1"
|
||||
id="Icons"
|
||||
viewBox="0 0 32 32"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="RocketSiloIconWhite.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs13" /><sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.09125"
|
||||
inkscape:cx="178.69416"
|
||||
inkscape:cy="397.70905"
|
||||
inkscape:window-width="3072"
|
||||
inkscape:window-height="1653"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="38"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Icons" />
|
||||
<g
|
||||
id="g8">
|
||||
<path
|
||||
id="path2"
|
||||
style="stroke-width:25"
|
||||
transform="scale(0.04)"
|
||||
d="m 104.49023,583.2168 c -0.0475,0.005 -0.0898,0.0209 -0.125,0.0469 -0.0897,0.0662 -0.1134,0.22145 -0.0859,0.44531 0.0945,-0.16261 0.18903,-0.32383 0.2832,-0.48632 -0.024,-0.001 -0.0506,-0.008 -0.0723,-0.006 z" />
|
||||
<path
|
||||
id="path4"
|
||||
style="stroke-width:25"
|
||||
transform="scale(0.04)"
|
||||
d="m 398.75,48.75 c -8.125,0 -16.25,3.75 -21.25,11.25 l -50,75 c 0,5 -2.5,10 -2.5,15 v 167.5 l -72.5,120 c -5,7.5 -5,17.5 0,25 5,7.5 12.5,12.5 22.5,12.5 h 250 c 10,0 17.5,-5 22.5,-12.5 5,-7.5 5,-17.5 0,-25 L 475,317.5 V 150 c 0,-5 -2.5,-10 -5,-15 L 420,60 C 415,52.5 406.875,48.75 398.75,48.75 Z" />
|
||||
<path
|
||||
id="path6"
|
||||
style="stroke-width:25"
|
||||
transform="scale(0.04)"
|
||||
d="m 400,500 c -15,0 -25,10 -25,25 v 75 c 0,15 10,25 25,25 15,0 25,-10 25,-25 v -75 c 0,-15 -10,-25 -25,-25 z" />
|
||||
</g>
|
||||
<ellipse
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke-width:0.04"
|
||||
id="path1551"
|
||||
cx="16.057112"
|
||||
cy="27.825054"
|
||||
rx="12.692628"
|
||||
ry="1.9371578" /><ellipse
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke-width:0.04"
|
||||
id="path1553"
|
||||
cx="22.051313"
|
||||
cy="29.516819"
|
||||
rx="0.53854793"
|
||||
ry="0.019182237" /><path
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.91638"
|
||||
d="m 336.31157,742.57746 c -64.10675,-2.73184 -96.35975,-5.10869 -135.62428,-9.99467 -65.84565,-8.19368 -108.369339,-20.55125 -115.027982,-33.42765 -9.213823,-17.81757 52.596912,-35.62711 155.348712,-44.76066 48.06575,-4.27253 78.28696,-5.61411 140.20618,-6.224 88.15143,-0.86828 156.77477,2.44417 223.5968,10.79301 71.65567,8.95277 116.73192,24.08998 113.2343,38.02562 -5.44535,21.696 -102.07526,39.68224 -243.23455,45.27454 -20.17937,0.79944 -121.7049,1.02948 -138.49918,0.31381 z"
|
||||
id="path1672"
|
||||
transform="scale(0.04)" /><path
|
||||
style="fill:#ffffff;stroke-width:0.91638"
|
||||
d="m 316.1512,741.30843 c -50.59618,-2.71561 -71.33695,-4.25003 -99.42726,-7.3557 C 138.8581,725.34385 89.219492,711.32972 85.606719,696.93529 81.493809,680.54815 143.8897,663.72225 241.9244,654.78211 c 54.02316,-4.92657 98.75384,-6.34315 180.06253,-5.70242 69.63124,0.54871 91.66091,1.45537 139.296,5.73293 83.98725,7.54194 144.60633,21.76524 154.80219,36.32187 12.95197,18.49152 -57.41631,37.71396 -170.38065,46.54273 -46.47603,3.63235 -56.00093,3.92443 -135.62429,4.15884 -43.84879,0.1291 -86.11684,-0.10834 -93.92898,-0.52763 z"
|
||||
id="path1748"
|
||||
transform="scale(0.04)" /><path
|
||||
style="fill:#ffffff;stroke-width:0.91638"
|
||||
d="m 395.4181,624.03958 c -8.54628,-1.74507 -14.15841,-5.98769 -17.54748,-13.26544 l -2.13679,-4.58857 -0.009,-43.18376 c -0.01,-46.57633 0.0787,-47.54106 4.93893,-53.91311 1.18953,-1.55955 4.37731,-4.05284 7.08397,-5.54065 4.29402,-2.36035 5.85547,-2.7051 12.25223,-2.7051 6.39676,0 7.95821,0.34475 12.25223,2.7051 2.70666,1.48781 5.89444,3.9811 7.08397,5.54065 4.8602,6.37205 4.94858,7.33678 4.93893,53.91311 l -0.009,43.18376 -2.1573,4.63286 c -4.50315,9.67058 -16.0552,15.39283 -26.69077,13.22115 z"
|
||||
id="path1787"
|
||||
transform="scale(0.04)" /><path
|
||||
style="fill:#ffffff;stroke-width:0.91638"
|
||||
d="m 267.74187,473.33145 c -14.07258,-4.41441 -22.07846,-19.50972 -16.66853,-31.42897 0.9777,-2.1541 18.08205,-30.88885 38.00965,-63.85502 l 36.23202,-59.93847 0.0313,-85.05678 c 0.0289,-78.40313 0.15927,-85.59443 1.66727,-91.92964 1.54167,-6.47669 3.12153,-9.09962 27.40785,-45.50342 16.49492,-24.724954 26.94454,-39.525002 29.0296,-41.115363 9.88792,-7.541884 24.92944,-6.440366 33.16408,2.428667 4.11259,4.429421 52.40823,77.221396 55.24103,83.260156 l 2.37067,5.05367 0.24734,86.46152 0.24733,86.46153 36.23928,59.95051 c 19.93161,32.97277 37.08285,61.85753 38.11388,64.18833 4.58482,10.36476 -1.20515,23.65555 -12.78176,29.34034 l -5.25049,2.57829 -129.66781,0.1742 c -107.00742,0.14375 -130.3607,-0.0432 -133.6327,-1.06955 z"
|
||||
id="path1826"
|
||||
transform="scale(0.04)" /><path
|
||||
style="fill:#ffffff;stroke-width:0.91638"
|
||||
d="m 306.52921,740.81162 c -87.19059,-4.45544 -154.17018,-13.39697 -191.52348,-25.56769 -16.873321,-5.49779 -29.782362,-13.67791 -29.782362,-18.8723 0,-10.70958 23.369172,-20.94319 67.691822,-29.64297 36.72878,-7.20924 87.73185,-12.78609 149.03212,-16.29568 28.05995,-1.60649 170.34184,-1.59744 198.85452,0.0127 41.28348,2.33126 79.77543,5.77849 110.42383,9.88924 54.44397,7.30236 94.73314,18.84269 103.92658,29.76847 3.65577,4.34464 3.19598,7.70457 -1.69574,12.39166 -18.84113,18.05298 -99.16958,32.16166 -218.61114,38.39627 -33.70301,1.75923 -153.32023,1.70864 -188.31615,-0.0796 z"
|
||||
id="path1902"
|
||||
transform="scale(0.04)" /></svg>
|
||||
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 266 B |
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" viewBox="0 0 24 24">
|
||||
<!-- Generator: Adobe Illustrator 29.3.1, SVG Export Plug-In . SVG Version: 2.1.0 Build 151) -->
|
||||
<defs>
|
||||
<style>
|
||||
.st0 {
|
||||
fill: #333;
|
||||
}
|
||||
|
||||
.st0, .st1 {
|
||||
fill-opacity: 0;
|
||||
}
|
||||
|
||||
.st1 {
|
||||
fill: #ececec;
|
||||
}
|
||||
|
||||
.st2 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<sodipodi:namedview id="namedview6" bordercolor="#666666" borderopacity="1.0" inkscape:current-layer="svg4" inkscape:cx="11.986254" inkscape:cy="11.931271" inkscape:pagecheckerboard="0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="1653" inkscape:window-maximized="1" inkscape:window-width="3072" inkscape:window-x="0" inkscape:window-y="38" inkscape:zoom="36.375" pagecolor="#ffffff" showgrid="false"/>
|
||||
<path id="path2" d="M12,0c-3.4,2.9-5.5,3-9,3v11.5c0,4.6,3.2,5.8,9,9.5,5.8-3.7,9-4.9,9-9.5V3c-3.5,0-5.6,0-9-3ZM12,2.5c2.5,1.8,4.6,2.3,7,2.4v9.6c0,3-1.7,3.8-7,7.1-5.3-3.3-7-4.1-7-7.1V5c2.4,0,4.5-.6,7-2.4h0ZM13.2,6.1h0ZM16.6,7.1h0ZM16.9,13.8h0ZM13.5,14h0Z"/>
|
||||
<path id="path862" class="st1" d="M12,0l-.4.3c-2.1,1.7-3.7,2.4-6.1,2.6h-2.5v12.6c.4,2.2,1.4,3.5,4.2,5.3.7.4,1,.6,2.8,1.8.6.4,1.3.8,1.6,1s.4.2.4.2c0,0,.3-.2.6-.3.3-.2,1.1-.7,1.7-1.1,3-1.8,3.8-2.4,4.7-3.3s1.6-2.1,1.9-3.6V3h-.7c-1.9,0-2.7,0-3.6-.4-1.4-.4-2.7-1-4.3-2.3l-.4-.4h.1ZM12,2.5l.3.2c1.5,1,2.9,1.7,4.5,2,.7,0,1,.2,2,.2h.2v10.7c-.3,1.5-1.1,2.4-3.8,4.1-.4.2-1.2.8-1.9,1.2-.7.4-1.3.8-1.3.8,0,0-2.8-1.7-3.3-2-2.5-1.6-3.3-2.5-3.6-4V5h.6c.3,0,1.1,0,1.4-.2,1.7-.3,3.1-.9,4.6-1.9l.4-.3h0Z"/>
|
||||
<path id="path1012" class="st0" d="M12,0l-.4.3c-2.1,1.7-3.7,2.4-6.1,2.6h-2.5v12.6c.4,2.2,1.4,3.5,4.2,5.3.7.4,1,.6,2.8,1.8.6.4,1.3.8,1.6,1s.4.2.4.2c0,0,.3-.2.6-.3.3-.2,1.1-.7,1.7-1.1,3-1.8,3.8-2.4,4.7-3.3s1.6-2.1,1.9-3.6V3h-.7c-1.9,0-2.7,0-3.6-.4-1.4-.4-2.7-1-4.3-2.3l-.4-.4h.1ZM12,2.5l.3.2c1.5,1,2.9,1.7,4.5,2,.7,0,1,.2,2,.2h.2v10.7c-.3,1.5-1.1,2.4-3.8,4.1-.4.2-1.2.8-1.9,1.2-.7.4-1.3.8-1.3.8,0,0-2.8-1.7-3.3-2-2.5-1.6-3.3-2.5-3.6-4V5h.6c.3,0,1.1,0,1.4-.2,1.7-.3,3.1-.9,4.6-1.9l.4-.3h0Z"/>
|
||||
<path id="path1162" class="st0" d="M12,0l-.4.3c-2.1,1.7-3.7,2.4-6.1,2.6h-2.5v12.6c.4,2.2,1.4,3.5,4.2,5.3.7.4,1,.6,2.8,1.8.6.4,1.3.8,1.6,1s.4.2.4.2c0,0,.3-.2.6-.3.3-.2,1.1-.7,1.7-1.1,3-1.8,3.8-2.4,4.7-3.3s1.6-2.1,1.9-3.6V3h-.7c-1.9,0-2.7,0-3.6-.4-1.4-.4-2.7-1-4.3-2.3l-.4-.4h.1ZM12,2.5l.3.2c1.5,1,2.9,1.7,4.5,2,.7,0,1,.2,2,.2h.2v10.7c-.3,1.5-1.1,2.4-3.8,4.1-.4.2-1.2.8-1.9,1.2-.7.4-1.3.8-1.3.8,0,0-2.8-1.7-3.3-2-2.5-1.6-3.3-2.5-3.6-4V5h.6c.3,0,1.1,0,1.4-.2,1.7-.3,3.1-.9,4.6-1.9l.4-.3h0Z"/>
|
||||
<path id="path1201" d="M12,0l-.4.3c-2.1,1.7-3.7,2.4-6.1,2.6h-2.5v12.6c.4,2.2,1.4,3.5,4.2,5.3.7.4,1,.6,2.8,1.8.6.4,1.3.8,1.6,1s.4.2.4.2c0,0,.3-.2.6-.3.3-.2,1.1-.7,1.7-1.1,3-1.8,3.8-2.4,4.7-3.3s1.6-2.1,1.9-3.6V3h-.7c-1.9,0-2.7,0-3.6-.4-1.4-.4-2.7-1-4.3-2.3l-.4-.4h.1ZM12,2.5l.3.2c1.5,1,2.9,1.7,4.5,2,.7,0,1,.2,2,.2h.2v10.7c-.3,1.5-1.1,2.4-3.8,4.1-.4.2-1.2.8-1.9,1.2-.7.4-1.3.8-1.3.8,0,0-2.8-1.7-3.3-2-2.5-1.6-3.3-2.5-3.6-4V5h.6c.3,0,1.1,0,1.4-.2,1.7-.3,3.1-.9,4.6-1.9l.4-.3h0Z"/>
|
||||
<path id="path3032" class="st2" d="M12,0l-.4.3c-2.1,1.7-3.7,2.4-6.1,2.6h-2.5v12.2c0,.4,0,.8.2,1.2.4,1.7,1.5,3,4,4.6.7.4.9.6,3.3,2,.6.4,1.2.8,1.3.8h.2c0,.1.2,0,.5-.2.3-.2.9-.6,1.5-.9,3.4-2.1,4.2-2.6,5.2-3.6s1.7-2.4,1.9-4V3h-2.5c-2.4-.2-4-.9-6.1-2.6l-.4-.3h-.1ZM12,2.5l.4.3c1.8,1.2,3.4,1.8,5.5,2.1h1.1v10.7c-.2,1.2-.9,2.1-2.3,3.1-.6.5-1.5,1-3.6,2.3-.6.3-1,.6-1,.6,0,0-1.7-1-2.5-1.5-1.7-1.1-2.6-1.7-3.2-2.3-.7-.7-1.1-1.3-1.3-2.3V4.8h.4c2.5-.2,4.2-.8,6.2-2.1l.4-.3h-.1Z"/>
|
||||
<path id="path1787" class="st2" d="M8.6,17.8c-.2-.1-.2-.3-.2-.5h0c0-.1.5-1,.5-1,.5-1,.6-1,.7-1h.5c.1,0,.2,0,.2.2v.2q0,.2-.5,1.2l-.5.9h0c-.2.2-.5.2-.7,0h0Z"/>
|
||||
<path id="path1826" class="st2" d="M7.7,13.2c-.2-.3-.2-.7,0-.8,0,0,.7-.4,1.5-.9l1.4-.8,1-1.7c.9-1.6,1-1.8,1.1-1.9s.2-.2,1.1-.6c.6-.3,1-.5,1.1-.5.3,0,.6.2.7.4,0,0,.2,2.2.2,2.4h0c0,.1-1,1.9-1,1.9l-1,1.8v3.5c0,.3-.3.5-.6.5h-.1l-2.7-1.5-2.7-1.8Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 361 B |
|
Before Width: | Height: | Size: 126 B After Width: | Height: | Size: 238 B |
@@ -1,7 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 176 B |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 587 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 551 B |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
version="1.1"
|
||||
id="Icons"
|
||||
viewBox="0 0 32 32"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="MissileSiloIconWhite.svg"
|
||||
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs13"><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect4"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.98396776,0,1 @ F,0,0,1,0,0.90902474,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3-5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3-7"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /></defs><sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#999999"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.1825"
|
||||
inkscape:cx="-105.38373"
|
||||
inkscape:cy="0.68728522"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Icons"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
|
||||
<path
|
||||
id="path2"
|
||||
style="fill:#ffffff;stroke-width:0.677186"
|
||||
d="m 25.898883,7.6636543 c -0.04144,0.04884 -3.863384,-3.2777509 -3.863384,-3.2777509 1.46078,-1.721777 3.509825,-2.3838038 4.576668,-1.4786782 1.066845,0.9051262 0.747497,3.0346514 -0.713284,4.7564291 z"
|
||||
sodipodi:nodetypes="ccsc" /><path
|
||||
id="rect3"
|
||||
style="fill:#ffffff;stroke-width:1.1798"
|
||||
d="m 12.748325,7.3692592 h 6.599784 v 9.7262258 a 0.98396776,0.98396776 135 0 1 -0.983968,0.983968 H 13.65735 a 0.90902474,0.90902474 45 0 1 -0.909025,-0.909025 z"
|
||||
inkscape:path-effect="#path-effect4"
|
||||
inkscape:original-d="m 12.748325,7.3692592 h 6.599784 V 18.079453 h -6.599784 z"
|
||||
transform="matrix(0.58656255,0.49764806,-0.57368061,0.67617979,18.00944,-6.0548174)" /><path
|
||||
style="fill:#ffffff"
|
||||
d="M 12.316287,10.791417 12.02519,14.786754 9.5403643,15.849128 A 0.64473841,0.64473841 33.887593 0 1 8.6422492,15.245902 l 0.010113,-0.626994 a 1.8979735,1.8979735 116.0463 0 1 0.7076373,-1.447901 z"
|
||||
id="path3"
|
||||
inkscape:path-effect="#path-effect3"
|
||||
inkscape:original-d="m 12.316287,10.791417 -0.291097,3.995337 -3.3989742,1.453213 0.040499,-2.510918 z"
|
||||
transform="matrix(0.57903787,0.50638361,-0.89799211,1.0268331,20.723968,-10.08514)"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="fill:#ffffff"
|
||||
d="M 12.316287,10.791417 12.02519,14.786754 9.5403643,15.849128 A 0.64473841,0.64473841 33.887593 0 1 8.6422492,15.245902 l 0.010113,-0.626994 a 1.8979735,1.8979735 116.0463 0 1 0.7076373,-1.447901 z"
|
||||
id="path3-1"
|
||||
inkscape:path-effect="#path-effect3-7"
|
||||
inkscape:original-d="m 12.316287,10.791417 -0.291097,3.995337 -3.3989742,1.453213 0.040499,-2.510918 z"
|
||||
transform="matrix(-0.59419498,-0.4885095,-0.86629519,1.0537118,40.501308,6.456681)"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="fill:#ffffff;stroke-width:1.06472"
|
||||
d="m 13.737178,16.80511 c 0,0 -9.3199199,7.391956 -7.1372902,13.873745 l 5.2775782,0.03513 c -2.0517202,-5.22962 3.28918,-12.748302 3.28918,-12.748302 z"
|
||||
id="path4"
|
||||
sodipodi:nodetypes="ccccc" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5"
|
||||
cx="3.7514319"
|
||||
cy="29.066437"
|
||||
r="0.88774341" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5-4"
|
||||
cx="12.046965"
|
||||
cy="29.945017"
|
||||
r="0.88774341" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:1.33861"
|
||||
id="path5-3"
|
||||
cx="11.284078"
|
||||
cy="27.854525"
|
||||
rx="1.1741122"
|
||||
ry="1.2027493" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5-2"
|
||||
cx="6.2749138"
|
||||
cy="27.315006"
|
||||
r="0.88774341" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:2.01452"
|
||||
id="path5-6"
|
||||
cx="5.9450173"
|
||||
cy="29.290951"
|
||||
rx="1.8613975"
|
||||
ry="1.7182131" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:0.807137"
|
||||
id="path5-6-9"
|
||||
cx="2.4461236"
|
||||
cy="26.341803"
|
||||
rx="0.70718539"
|
||||
ry="0.7259956" /><circle
|
||||
style="fill:#ffffff;stroke-width:0.806452"
|
||||
id="path5-5"
|
||||
cx="14.434135"
|
||||
cy="28.200459"
|
||||
r="0.71592212" /><circle
|
||||
style="fill:#ffffff;stroke-width:1.29032"
|
||||
id="path5-61"
|
||||
cx="4.2863698"
|
||||
cy="23.691866"
|
||||
r="1.1454754" /></svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,221 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg4"
|
||||
version="1.1"
|
||||
viewBox="0 0 24 24"
|
||||
sodipodi:docname="SamLauncherIconWhite.svg"
|
||||
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<!-- Generator: Adobe Illustrator 29.3.1, SVG Export Plug-In . SVG Version: 2.1.0 Build 151) -->
|
||||
<defs
|
||||
id="defs1">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect11"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.31531758,0,1 @ F,0,0,1,0,0.056759862,0,1 @ F,0,0,1,0,0.16487468,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.19973466,0,1 @ F,0,0,1,0,0.075242437,0,1 @ F,0,0,1,0,0.3011792,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect10"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect9"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49680354,0,1 @ F,0,0,1,0,0.46383368,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect8"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.20544103,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect6"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.6771002,0,1 @ F,0,0,1,0,0.21443289,0,1 @ F,0,0,1,0,0.20068725,0,1 @ F,0,0,1,0,0.61305832,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<style
|
||||
id="style1">
|
||||
.st0 {
|
||||
fill: #333;
|
||||
}
|
||||
|
||||
.st0, .st1 {
|
||||
fill-opacity: 0;
|
||||
}
|
||||
|
||||
.st1 {
|
||||
fill: #ececec;
|
||||
}
|
||||
|
||||
.st2 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect6-9"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.6771002,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.21443289,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:cx="-1.3745704"
|
||||
inkscape:cy="8.2199313"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:zoom="18.1875"
|
||||
pagecolor="#828282"
|
||||
showgrid="false"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:1.32815"
|
||||
d="m 17.680103,4.3837562 1.471937,2.3505899 c 0,0 1.557345,-0.6986001 0.828902,-1.8430742 -0.709885,-1.115248 -2.300839,-0.5075157 -2.300839,-0.5075157 z"
|
||||
id="path3"
|
||||
sodipodi:nodetypes="ccsc" />
|
||||
<path
|
||||
id="rect4"
|
||||
style="fill:#ffffff;stroke-width:1.06832"
|
||||
d="m 7.412439,8.3385684 c 2.2265471,0.022033 5.06556,-0.00697 7.576035,-0.0086 0.118341,-7.68e-5 0.214275,0.095934 0.214275,0.2143622 l 0,2.2790372 a 0.20068725,0.20068725 135 0 1 -0.200687,0.200687 H 7.3484537 A 0.61305832,0.61305832 45 0 1 6.7353954,10.410996 V 9.0069971 c 0,-0.3739521 0.3031104,-0.672129 0.6770436,-0.6684287 z"
|
||||
inkscape:path-effect="#path-effect6"
|
||||
inkscape:original-d="m 6.7353954,8.3298969 c 2.3661435,0.038026 5.6449026,0 8.4673536,0 V 11.024054 H 6.7353954 Z"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(1.3871173,-0.56218381,0.7027184,1.1097117,-10.354938,3.8136388)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:1.32815"
|
||||
d="m 17.46913,1.7477688 0.735969,1.1752951 c 0,0 0.998735,-0.2087137 1.51062,0.2066682 0.110775,-0.097941 0.30661,-0.5279917 0.05425,-0.8744476 -0.813874,-1.0688142 -2.30084,-0.5075157 -2.30084,-0.5075157 z"
|
||||
id="path3-8"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="rect4-8"
|
||||
style="fill:#ffffff;stroke-width:1.48584"
|
||||
d="M 16.185391,1.9343439 C 12.701012,3.3485891 8.7751898,4.9780406 5.6675841,6.2067613 5.1462949,6.4128743 4.9569987,6.9059035 5.2454361,7.3098295 l 0.3037033,0.425192 11.6233046,-4.9169042 -0.5456,-0.776552 C 16.540403,1.9185247 16.342728,1.8704833 16.185391,1.9343439 Z"
|
||||
sodipodi:nodetypes="cscccc" />
|
||||
<path
|
||||
id="rect6"
|
||||
style="fill:#ffffff"
|
||||
d="m 9.9518898,14.020619 2.9965632,-1.457045 v 1.949931 a 0.4923079,0.4923079 135.26041 0 1 -0.496783,0.492288 l -2.063457,-0.01876 a 0.45488806,0.45488806 46.078703 0 1 -0.4505676,-0.46786 z"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:path-effect="#path-effect9"
|
||||
inkscape:original-d="m 9.9518898,14.020619 2.9965632,-1.457045 v 2.446735 l -3.0240546,-0.02749 z"
|
||||
transform="matrix(1.5549622,0,0,1.2439898,-5.3629748,-5.3468075)" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:1.27479"
|
||||
id="rect7"
|
||||
width="2.9068708"
|
||||
height="3.1029518"
|
||||
x="11.007972"
|
||||
y="14.623526" />
|
||||
<path
|
||||
id="rect8"
|
||||
style="fill:#ffffff;stroke-width:1.80595"
|
||||
d="m 6.3154251,19.421168 v 0.803136 a 0.10556598,0.10575084 0 0 1 -0.102369,0.105707 l -1.2284353,0.03728 a 0.30883774,0.30937857 0 0 0 -0.2994769,0.307034 l -0.012108,1.703993 15.9080751,-0.01409 0.003,-1.626855 a 0.37070023,0.37134941 0 0 0 -0.359663,-0.371867 l -1.146325,-0.03449 a 0.13990479,0.14014979 0 0 1 -0.135706,-0.140085 v -0.795287 a 0.54344015,0.54439183 0 0 0 -0.543439,-0.544393 l -11.5146875,-1.7e-5 a 0.56894912,0.56994548 0 0 0 -0.5688864,0.569952 z"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
version="1.1"
|
||||
id="Icons"
|
||||
viewBox="0 0 32 32"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="MissileSiloIconWhite.svg"
|
||||
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs13"><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect4"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.98396776,0,1 @ F,0,0,1,0,0.90902474,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3-5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /><inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect3-7"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.99419457,0,1 @ F,0,0,1,0,0.88997446,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" /></defs><sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#999999"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.1825"
|
||||
inkscape:cx="-105.38373"
|
||||
inkscape:cy="0.68728522"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Icons"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
|
||||
<path
|
||||
id="path2"
|
||||
style="fill:#ffffff;stroke-width:0.677186"
|
||||
d="m 25.898883,7.6636543 c -0.04144,0.04884 -3.863384,-3.2777509 -3.863384,-3.2777509 1.46078,-1.721777 3.509825,-2.3838038 4.576668,-1.4786782 1.066845,0.9051262 0.747497,3.0346514 -0.713284,4.7564291 z"
|
||||
sodipodi:nodetypes="ccsc" /><path
|
||||
id="rect3"
|
||||
style="fill:#ffffff;stroke-width:1.1798"
|
||||
d="m 12.748325,7.3692592 h 6.599784 v 9.7262258 a 0.98396776,0.98396776 135 0 1 -0.983968,0.983968 H 13.65735 a 0.90902474,0.90902474 45 0 1 -0.909025,-0.909025 z"
|
||||
inkscape:path-effect="#path-effect4"
|
||||
inkscape:original-d="m 12.748325,7.3692592 h 6.599784 V 18.079453 h -6.599784 z"
|
||||
transform="matrix(0.58656255,0.49764806,-0.57368061,0.67617979,18.00944,-6.0548174)" /><path
|
||||
style="fill:#ffffff"
|
||||
d="M 12.316287,10.791417 12.02519,14.786754 9.5403643,15.849128 A 0.64473841,0.64473841 33.887593 0 1 8.6422492,15.245902 l 0.010113,-0.626994 a 1.8979735,1.8979735 116.0463 0 1 0.7076373,-1.447901 z"
|
||||
id="path3"
|
||||
inkscape:path-effect="#path-effect3"
|
||||
inkscape:original-d="m 12.316287,10.791417 -0.291097,3.995337 -3.3989742,1.453213 0.040499,-2.510918 z"
|
||||
transform="matrix(0.57903787,0.50638361,-0.89799211,1.0268331,20.723968,-10.08514)"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="fill:#ffffff"
|
||||
d="M 12.316287,10.791417 12.02519,14.786754 9.5403643,15.849128 A 0.64473841,0.64473841 33.887593 0 1 8.6422492,15.245902 l 0.010113,-0.626994 a 1.8979735,1.8979735 116.0463 0 1 0.7076373,-1.447901 z"
|
||||
id="path3-1"
|
||||
inkscape:path-effect="#path-effect3-7"
|
||||
inkscape:original-d="m 12.316287,10.791417 -0.291097,3.995337 -3.3989742,1.453213 0.040499,-2.510918 z"
|
||||
transform="matrix(-0.59419498,-0.4885095,-0.86629519,1.0537118,40.501308,6.456681)"
|
||||
sodipodi:nodetypes="ccccc" /><path
|
||||
style="fill:#ffffff;stroke-width:1.06472"
|
||||
d="m 13.737178,16.80511 c 0,0 -9.3199199,7.391956 -7.1372902,13.873745 l 5.2775782,0.03513 c -2.0517202,-5.22962 3.28918,-12.748302 3.28918,-12.748302 z"
|
||||
id="path4"
|
||||
sodipodi:nodetypes="ccccc" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5"
|
||||
cx="3.7514319"
|
||||
cy="29.066437"
|
||||
r="0.88774341" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5-4"
|
||||
cx="12.046965"
|
||||
cy="29.945017"
|
||||
r="0.88774341" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:1.33861"
|
||||
id="path5-3"
|
||||
cx="11.284078"
|
||||
cy="27.854525"
|
||||
rx="1.1741122"
|
||||
ry="1.2027493" /><circle
|
||||
style="fill:#ffffff"
|
||||
id="path5-2"
|
||||
cx="6.2749138"
|
||||
cy="27.315006"
|
||||
r="0.88774341" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:2.01452"
|
||||
id="path5-6"
|
||||
cx="5.9450173"
|
||||
cy="29.290951"
|
||||
rx="1.8613975"
|
||||
ry="1.7182131" /><ellipse
|
||||
style="fill:#ffffff;stroke-width:0.807137"
|
||||
id="path5-6-9"
|
||||
cx="2.4461236"
|
||||
cy="26.341803"
|
||||
rx="0.70718539"
|
||||
ry="0.7259956" /><circle
|
||||
style="fill:#ffffff;stroke-width:0.806452"
|
||||
id="path5-5"
|
||||
cx="14.434135"
|
||||
cy="28.200459"
|
||||
r="0.71592212" /><circle
|
||||
style="fill:#ffffff;stroke-width:1.29032"
|
||||
id="path5-61"
|
||||
cx="4.2863698"
|
||||
cy="23.691866"
|
||||
r="1.1454754" /></svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,221 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="svg4"
|
||||
version="1.1"
|
||||
viewBox="0 0 24 24"
|
||||
sodipodi:docname="SamLauncherIconWhite.svg"
|
||||
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<!-- Generator: Adobe Illustrator 29.3.1, SVG Export Plug-In . SVG Version: 2.1.0 Build 151) -->
|
||||
<defs
|
||||
id="defs1">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect11"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.31531758,0,1 @ F,0,0,1,0,0.056759862,0,1 @ F,0,0,1,0,0.16487468,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.19973466,0,1 @ F,0,0,1,0,0.075242437,0,1 @ F,0,0,1,0,0.3011792,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect10"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect9"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.49680354,0,1 @ F,0,0,1,0,0.46383368,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect8"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.20544103,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect6"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.6771002,0,1 @ F,0,0,1,0,0.21443289,0,1 @ F,0,0,1,0,0.20068725,0,1 @ F,0,0,1,0,0.61305832,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect5"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<style
|
||||
id="style1">
|
||||
.st0 {
|
||||
fill: #333;
|
||||
}
|
||||
|
||||
.st0, .st1 {
|
||||
fill-opacity: 0;
|
||||
}
|
||||
|
||||
.st1 {
|
||||
fill: #ececec;
|
||||
}
|
||||
|
||||
.st2 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect6-9"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0.6771002,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0.21443289,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:cx="-1.3745704"
|
||||
inkscape:cy="8.2199313"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:zoom="18.1875"
|
||||
pagecolor="#828282"
|
||||
showgrid="false"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:1.32815"
|
||||
d="m 17.680103,4.3837562 1.471937,2.3505899 c 0,0 1.557345,-0.6986001 0.828902,-1.8430742 -0.709885,-1.115248 -2.300839,-0.5075157 -2.300839,-0.5075157 z"
|
||||
id="path3"
|
||||
sodipodi:nodetypes="ccsc" />
|
||||
<path
|
||||
id="rect4"
|
||||
style="fill:#ffffff;stroke-width:1.06832"
|
||||
d="m 7.412439,8.3385684 c 2.2265471,0.022033 5.06556,-0.00697 7.576035,-0.0086 0.118341,-7.68e-5 0.214275,0.095934 0.214275,0.2143622 l 0,2.2790372 a 0.20068725,0.20068725 135 0 1 -0.200687,0.200687 H 7.3484537 A 0.61305832,0.61305832 45 0 1 6.7353954,10.410996 V 9.0069971 c 0,-0.3739521 0.3031104,-0.672129 0.6770436,-0.6684287 z"
|
||||
inkscape:path-effect="#path-effect6"
|
||||
inkscape:original-d="m 6.7353954,8.3298969 c 2.3661435,0.038026 5.6449026,0 8.4673536,0 V 11.024054 H 6.7353954 Z"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
transform="matrix(1.3871173,-0.56218381,0.7027184,1.1097117,-10.354938,3.8136388)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:1.32815"
|
||||
d="m 17.46913,1.7477688 0.735969,1.1752951 c 0,0 0.998735,-0.2087137 1.51062,0.2066682 0.110775,-0.097941 0.30661,-0.5279917 0.05425,-0.8744476 -0.813874,-1.0688142 -2.30084,-0.5075157 -2.30084,-0.5075157 z"
|
||||
id="path3-8"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="rect4-8"
|
||||
style="fill:#ffffff;stroke-width:1.48584"
|
||||
d="M 16.185391,1.9343439 C 12.701012,3.3485891 8.7751898,4.9780406 5.6675841,6.2067613 5.1462949,6.4128743 4.9569987,6.9059035 5.2454361,7.3098295 l 0.3037033,0.425192 11.6233046,-4.9169042 -0.5456,-0.776552 C 16.540403,1.9185247 16.342728,1.8704833 16.185391,1.9343439 Z"
|
||||
sodipodi:nodetypes="cscccc" />
|
||||
<path
|
||||
id="rect6"
|
||||
style="fill:#ffffff"
|
||||
d="m 9.9518898,14.020619 2.9965632,-1.457045 v 1.949931 a 0.4923079,0.4923079 135.26041 0 1 -0.496783,0.492288 l -2.063457,-0.01876 a 0.45488806,0.45488806 46.078703 0 1 -0.4505676,-0.46786 z"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:path-effect="#path-effect9"
|
||||
inkscape:original-d="m 9.9518898,14.020619 2.9965632,-1.457045 v 2.446735 l -3.0240546,-0.02749 z"
|
||||
transform="matrix(1.5549622,0,0,1.2439898,-5.3629748,-5.3468075)" />
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:1.27479"
|
||||
id="rect7"
|
||||
width="2.9068708"
|
||||
height="3.1029518"
|
||||
x="11.007972"
|
||||
y="14.623526" />
|
||||
<path
|
||||
id="rect8"
|
||||
style="fill:#ffffff;stroke-width:1.80595"
|
||||
d="m 6.3154251,19.421168 v 0.803136 a 0.10556598,0.10575084 0 0 1 -0.102369,0.105707 l -1.2284353,0.03728 a 0.30883774,0.30937857 0 0 0 -0.2994769,0.307034 l -0.012108,1.703993 15.9080751,-0.01409 0.003,-1.626855 a 0.37070023,0.37134941 0 0 0 -0.359663,-0.371867 l -1.146325,-0.03449 a 0.13990479,0.14014979 0 0 1 -0.135706,-0.140085 v -0.795287 a 0.54344015,0.54439183 0 0 0 -0.543439,-0.544393 l -11.5146875,-1.7e-5 a 0.56894912,0.56994548 0 0 0 -0.5688864,0.569952 z"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
@@ -28,6 +28,7 @@ import { RailroadLayer } from "./layers/RailroadLayer";
|
||||
import { ReplayPanel } from "./layers/ReplayPanel";
|
||||
import { SpawnAd } from "./layers/SpawnAd";
|
||||
import { SpawnTimer } from "./layers/SpawnTimer";
|
||||
import { StructureIconsLayer } from "./layers/StructureIconsLayer";
|
||||
import { StructureLayer } from "./layers/StructureLayer";
|
||||
import { TeamStats } from "./layers/TeamStats";
|
||||
import { TerrainLayer } from "./layers/TerrainLayer";
|
||||
@@ -227,6 +228,7 @@ export function createRenderer(
|
||||
new TerritoryLayer(game, eventBus, transformHandler, userSettings),
|
||||
new RailroadLayer(game),
|
||||
structureLayer,
|
||||
new StructureIconsLayer(game, transformHandler),
|
||||
new UnitLayer(game, eventBus, transformHandler),
|
||||
new FxLayer(game),
|
||||
new UILayer(game, eventBus, transformHandler),
|
||||
@@ -312,6 +314,7 @@ export class GameRenderer {
|
||||
resizeCanvas() {
|
||||
this.canvas.width = window.innerWidth;
|
||||
this.canvas.height = window.innerHeight;
|
||||
this.transformHandler.updateCanvasBoundingRect();
|
||||
//this.redraw()
|
||||
}
|
||||
|
||||
@@ -325,24 +328,33 @@ export class GameRenderer {
|
||||
.toHex();
|
||||
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
// Save the current context state
|
||||
this.context.save();
|
||||
|
||||
this.transformHandler.handleTransform(this.context);
|
||||
|
||||
this.layers.forEach((l) => {
|
||||
if (l.shouldTransform?.()) {
|
||||
l.renderLayer?.(this.context);
|
||||
const handleTransformState = (
|
||||
needsTransform: boolean,
|
||||
active: boolean,
|
||||
): boolean => {
|
||||
if (needsTransform && !active) {
|
||||
this.context.save();
|
||||
this.transformHandler.handleTransform(this.context);
|
||||
return true;
|
||||
} else if (!needsTransform && active) {
|
||||
this.context.restore();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return active;
|
||||
};
|
||||
|
||||
this.context.restore();
|
||||
let isTransformActive = false;
|
||||
|
||||
this.layers.forEach((l) => {
|
||||
if (!l.shouldTransform?.()) {
|
||||
l.renderLayer?.(this.context);
|
||||
}
|
||||
});
|
||||
for (const layer of this.layers) {
|
||||
const needsTransform = layer.shouldTransform?.() ?? false;
|
||||
isTransformActive = handleTransformState(
|
||||
needsTransform,
|
||||
isTransformActive,
|
||||
);
|
||||
layer.renderLayer?.(this.context);
|
||||
}
|
||||
handleTransformState(false, isTransformActive); // Ensure context is clean after rendering
|
||||
this.transformHandler.resetChanged();
|
||||
|
||||
requestAnimationFrame(() => this.renderGame());
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export const CAMERA_SMOOTHING = 0.03;
|
||||
|
||||
export class TransformHandler {
|
||||
public scale: number = 1.8;
|
||||
private _boundingRect: DOMRect;
|
||||
private offsetX: number = -350;
|
||||
private offsetY: number = -200;
|
||||
private lastGoToCallTime: number | null = null;
|
||||
@@ -27,6 +28,7 @@ export class TransformHandler {
|
||||
private eventBus: EventBus,
|
||||
private canvas: HTMLCanvasElement,
|
||||
) {
|
||||
this._boundingRect = this.canvas.getBoundingClientRect();
|
||||
this.eventBus.on(ZoomEvent, (e) => this.onZoom(e));
|
||||
this.eventBus.on(DragEvent, (e) => this.onMove(e));
|
||||
this.eventBus.on(GoToPlayerEvent, (e) => this.onGoToPlayer(e));
|
||||
@@ -35,8 +37,12 @@ export class TransformHandler {
|
||||
this.eventBus.on(CenterCameraEvent, () => this.centerCamera());
|
||||
}
|
||||
|
||||
public updateCanvasBoundingRect() {
|
||||
this._boundingRect = this.canvas.getBoundingClientRect();
|
||||
}
|
||||
|
||||
boundingRect(): DOMRect {
|
||||
return this.canvas.getBoundingClientRect();
|
||||
return this._boundingRect;
|
||||
}
|
||||
|
||||
width(): number {
|
||||
@@ -45,6 +51,9 @@ export class TransformHandler {
|
||||
hasChanged(): boolean {
|
||||
return this.changed;
|
||||
}
|
||||
resetChanged() {
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
handleTransform(context: CanvasRenderingContext2D) {
|
||||
// Disable image smoothing for pixelated effect
|
||||
@@ -59,7 +68,6 @@ export class TransformHandler {
|
||||
this.game.width() / 2 - this.offsetX * this.scale,
|
||||
this.game.height() / 2 - this.offsetY * this.scale,
|
||||
);
|
||||
this.changed = false;
|
||||
}
|
||||
|
||||
worldToScreenCoordinates(cell: Cell): { x: number; y: number } {
|
||||
|
||||
@@ -5,12 +5,12 @@ import cityIcon from "../../../../resources/images/CityIconWhite.svg";
|
||||
import factoryIcon from "../../../../resources/images/FactoryIconWhite.svg";
|
||||
import goldCoinIcon from "../../../../resources/images/GoldCoinIcon.svg";
|
||||
import mirvIcon from "../../../../resources/images/MIRVIcon.svg";
|
||||
import missileSiloIcon from "../../../../resources/images/MissileSiloIconWhite.svg";
|
||||
import hydrogenBombIcon from "../../../../resources/images/MushroomCloudIconWhite.svg";
|
||||
import atomBombIcon from "../../../../resources/images/NukeIconWhite.svg";
|
||||
import portIcon from "../../../../resources/images/PortIcon.svg";
|
||||
import samlauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
|
||||
import shieldIcon from "../../../../resources/images/ShieldIconWhite.svg";
|
||||
import missileSiloIcon from "../../../../resources/non-commercial/svg/MissileSiloIconWhite.svg";
|
||||
import samlauncherIcon from "../../../../resources/non-commercial/svg/SamLauncherIconWhite.svg";
|
||||
import { translateText } from "../../../client/Utils";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { Cell, Gold, PlayerActions, UnitType } from "../../../core/game/Game";
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
import * as PIXI from "pixi.js";
|
||||
import anchorIcon from "../../../../resources/images/AnchorIcon.png";
|
||||
import cityIcon from "../../../../resources/images/CityIcon.png";
|
||||
import factoryIcon from "../../../../resources/images/FactoryUnit.png";
|
||||
import missileSiloIcon from "../../../../resources/images/MissileSiloUnit.png";
|
||||
import SAMMissileIcon from "../../../../resources/images/SamLauncherUnit.png";
|
||||
import shieldIcon from "../../../../resources/images/ShieldIcon.png";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { Cell, PlayerID, UnitType } from "../../../core/game/Game";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
import { TransformHandler } from "../TransformHandler";
|
||||
import { Layer } from "./Layer";
|
||||
|
||||
class StructureRenderInfo {
|
||||
public isOnScreen: boolean = false;
|
||||
constructor(
|
||||
public unit: UnitView,
|
||||
public owner: PlayerID,
|
||||
public pixiSprite: PIXI.Sprite,
|
||||
) {}
|
||||
}
|
||||
const ZOOM_THRESHOLD = 2.8; // below this zoom level, structures are not rendered
|
||||
const ICON_SIZE = 24;
|
||||
const OFFSET_ZOOM_Y = 15; // offset for the y position of the icon to avoid hiding the structure beneath
|
||||
|
||||
export class StructureIconsLayer implements Layer {
|
||||
private pixicanvas: HTMLCanvasElement;
|
||||
private stage: PIXI.Container;
|
||||
private shouldRedraw: boolean = true;
|
||||
private textureCache: Map<string, PIXI.Texture> = new Map();
|
||||
private theme: Theme;
|
||||
private renderer: PIXI.Renderer;
|
||||
private renders: StructureRenderInfo[] = [];
|
||||
private seenUnits: Set<UnitView> = new Set();
|
||||
private structures: Map<
|
||||
UnitType,
|
||||
{ iconPath: string; image: HTMLImageElement | null }
|
||||
> = new Map([
|
||||
[UnitType.City, { iconPath: cityIcon, image: null }],
|
||||
[UnitType.Factory, { iconPath: factoryIcon, image: null }],
|
||||
[UnitType.DefensePost, { iconPath: shieldIcon, image: null }],
|
||||
[UnitType.Port, { iconPath: anchorIcon, image: null }],
|
||||
[UnitType.MissileSilo, { iconPath: missileSiloIcon, image: null }],
|
||||
[UnitType.SAMLauncher, { iconPath: SAMMissileIcon, image: null }],
|
||||
]);
|
||||
|
||||
constructor(
|
||||
private game: GameView,
|
||||
private transformHandler: TransformHandler,
|
||||
) {
|
||||
this.theme = game.config().theme();
|
||||
this.structures.forEach((u, unitType) => this.loadIcon(u, unitType));
|
||||
}
|
||||
|
||||
async setupRenderer() {
|
||||
this.renderer = new PIXI.WebGLRenderer();
|
||||
this.pixicanvas = document.createElement("canvas");
|
||||
this.pixicanvas.width = window.innerWidth;
|
||||
this.pixicanvas.height = window.innerHeight;
|
||||
this.stage = new PIXI.Container();
|
||||
this.stage.position.set(0, 0);
|
||||
this.stage.width = this.pixicanvas.width;
|
||||
this.stage.height = this.pixicanvas.height;
|
||||
await this.renderer.init({
|
||||
canvas: this.pixicanvas,
|
||||
resolution: 1,
|
||||
width: this.pixicanvas.width,
|
||||
height: this.pixicanvas.height,
|
||||
clearBeforeRender: true,
|
||||
backgroundAlpha: 0,
|
||||
backgroundColor: 0x00000000,
|
||||
});
|
||||
}
|
||||
|
||||
private loadIcon(
|
||||
unitInfo: {
|
||||
iconPath: string;
|
||||
image: HTMLImageElement | null;
|
||||
},
|
||||
unitType: UnitType,
|
||||
) {
|
||||
const image = new Image();
|
||||
image.src = unitInfo.iconPath;
|
||||
image.onload = () => {
|
||||
unitInfo.image = image;
|
||||
};
|
||||
image.onerror = () => {
|
||||
console.error(
|
||||
`Failed to load icon for ${unitType}: ${unitInfo.iconPath}`,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
shouldTransform(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async init() {
|
||||
window.addEventListener("resize", () => this.resizeCanvas());
|
||||
await this.setupRenderer();
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
resizeCanvas() {
|
||||
if (this.renderer.view) {
|
||||
this.pixicanvas.width = window.innerWidth;
|
||||
this.pixicanvas.height = window.innerHeight;
|
||||
this.renderer.resize(innerWidth, innerHeight, 1);
|
||||
this.shouldRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
public tick() {
|
||||
this.game
|
||||
.updatesSinceLastTick()
|
||||
?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id))
|
||||
?.forEach((unitView) => {
|
||||
if (unitView === undefined) return;
|
||||
|
||||
if (unitView.isActive()) {
|
||||
if (this.seenUnits.has(unitView)) {
|
||||
// check if owner has changed
|
||||
const render = this.renders.find(
|
||||
(r) => r.unit.id() === unitView.id(),
|
||||
);
|
||||
if (render) {
|
||||
this.ownerChangeCheck(render, unitView);
|
||||
}
|
||||
} else if (this.structures.has(unitView.type())) {
|
||||
// new unit, create render info
|
||||
this.seenUnits.add(unitView);
|
||||
const render = new StructureRenderInfo(
|
||||
unitView,
|
||||
unitView.owner().id(),
|
||||
this.createPixiSprite(unitView),
|
||||
);
|
||||
this.renders.push(render);
|
||||
this.computeNewLocation(render);
|
||||
this.shouldRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unitView.isActive() && this.seenUnits.has(unitView)) {
|
||||
const render = this.renders.find(
|
||||
(r) => r.unit.id() === unitView.id(),
|
||||
);
|
||||
if (render) {
|
||||
this.deleteStructure(render);
|
||||
}
|
||||
this.shouldRedraw = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
redraw() {
|
||||
this.resizeCanvas();
|
||||
}
|
||||
|
||||
renderLayer(mainContext: CanvasRenderingContext2D) {
|
||||
if (!this.renderer || this.transformHandler.scale > ZOOM_THRESHOLD) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transformHandler.hasChanged()) {
|
||||
for (const render of this.renders) {
|
||||
this.computeNewLocation(render);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.transformHandler.hasChanged() || this.shouldRedraw) {
|
||||
this.renderer.render(this.stage);
|
||||
this.shouldRedraw = false;
|
||||
}
|
||||
mainContext.drawImage(this.renderer.canvas, 0, 0);
|
||||
}
|
||||
|
||||
private ownerChangeCheck(render: StructureRenderInfo, unit: UnitView) {
|
||||
if (render.owner !== unit.owner().id()) {
|
||||
render.owner = unit.owner().id();
|
||||
render.pixiSprite?.destroy();
|
||||
render.pixiSprite = this.createPixiSprite(unit);
|
||||
this.shouldRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
private createTexture(unit: UnitView): PIXI.Texture {
|
||||
const cacheKey = `${unit.owner().id()}-${unit.type()}`;
|
||||
if (this.textureCache.has(cacheKey)) {
|
||||
return this.textureCache.get(cacheKey)!;
|
||||
}
|
||||
const structureCanvas = document.createElement("canvas");
|
||||
structureCanvas.width = ICON_SIZE;
|
||||
structureCanvas.height = ICON_SIZE;
|
||||
const context = structureCanvas.getContext("2d")!;
|
||||
context.fillStyle = this.theme
|
||||
.territoryColor(unit.owner())
|
||||
.lighten(0.1)
|
||||
.toRgbString();
|
||||
const borderColor = this.theme
|
||||
.borderColor(unit.owner())
|
||||
.darken(0.2)
|
||||
.toRgbString();
|
||||
context.strokeStyle = borderColor;
|
||||
context.beginPath();
|
||||
context.arc(
|
||||
ICON_SIZE / 2,
|
||||
ICON_SIZE / 2,
|
||||
ICON_SIZE / 2 - 1,
|
||||
0,
|
||||
Math.PI * 2,
|
||||
);
|
||||
context.fill();
|
||||
context.lineWidth = 1;
|
||||
context.stroke();
|
||||
const structureInfo = this.structures.get(unit.type());
|
||||
if (!structureInfo?.image) {
|
||||
console.warn(`Image not loaded for unit type: ${unit.type()}`);
|
||||
return PIXI.Texture.from(structureCanvas);
|
||||
}
|
||||
context.drawImage(
|
||||
this.getImageColored(structureInfo.image, borderColor),
|
||||
4,
|
||||
4,
|
||||
);
|
||||
const texture = PIXI.Texture.from(structureCanvas);
|
||||
this.textureCache.set(cacheKey, texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
private createPixiSprite(unit: UnitView): PIXI.Sprite {
|
||||
const sprite = new PIXI.Sprite(this.createTexture(unit));
|
||||
sprite.anchor.set(0.5, 0.5);
|
||||
const tile = unit.tile();
|
||||
const worldX = this.game.x(tile);
|
||||
const worldY = this.game.y(tile);
|
||||
const screenPos = this.transformHandler.worldToScreenCoordinates(
|
||||
new Cell(worldX, worldY),
|
||||
);
|
||||
sprite.x = screenPos.x;
|
||||
sprite.y = screenPos.y - this.transformHandler.scale * OFFSET_ZOOM_Y;
|
||||
sprite.scale.set(Math.min(1, this.transformHandler.scale));
|
||||
this.stage.addChild(sprite);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
private getImageColored(
|
||||
image: HTMLImageElement,
|
||||
color: string,
|
||||
): HTMLCanvasElement {
|
||||
const imageCanvas = document.createElement("canvas");
|
||||
imageCanvas.width = image.width;
|
||||
imageCanvas.height = image.height;
|
||||
const ctx = imageCanvas.getContext("2d")!;
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(0, 0, imageCanvas.width, imageCanvas.height);
|
||||
ctx.globalCompositeOperation = "destination-in";
|
||||
ctx.drawImage(image, 0, 0);
|
||||
return imageCanvas;
|
||||
}
|
||||
|
||||
private computeNewLocation(render: StructureRenderInfo) {
|
||||
const tile = render.unit.tile();
|
||||
const worldX = this.game.x(tile);
|
||||
const worldY = this.game.y(tile);
|
||||
const screenPos = this.transformHandler.worldToScreenCoordinates(
|
||||
new Cell(worldX, worldY),
|
||||
);
|
||||
screenPos.x = Math.round(screenPos.x);
|
||||
screenPos.y = Math.round(
|
||||
screenPos.y - this.transformHandler.scale * OFFSET_ZOOM_Y,
|
||||
);
|
||||
|
||||
// Check if the sprite is on screen (with margin for partial visibility)
|
||||
const margin = ICON_SIZE;
|
||||
const onScreen =
|
||||
screenPos.x + margin > 0 &&
|
||||
screenPos.x - margin < this.pixicanvas.width &&
|
||||
screenPos.y + margin > 0 &&
|
||||
screenPos.y - margin < this.pixicanvas.height;
|
||||
|
||||
if (onScreen) {
|
||||
render.pixiSprite.x = screenPos.x;
|
||||
render.pixiSprite.y = screenPos.y;
|
||||
render.pixiSprite.scale.set(Math.min(1, this.transformHandler.scale));
|
||||
}
|
||||
if (render.isOnScreen !== onScreen) {
|
||||
// prevent unnecessary updates
|
||||
render.isOnScreen = onScreen;
|
||||
render.pixiSprite.visible = onScreen;
|
||||
}
|
||||
}
|
||||
|
||||
private deleteStructure(render: StructureRenderInfo) {
|
||||
render.pixiSprite?.destroy();
|
||||
this.renders = this.renders.filter((r) => r.unit !== render.unit);
|
||||
this.seenUnits.delete(render.unit);
|
||||
}
|
||||
}
|
||||
@@ -6,26 +6,18 @@ import { TransformHandler } from "../TransformHandler";
|
||||
import { Layer } from "./Layer";
|
||||
import { UnitInfoModal } from "./UnitInfoModal";
|
||||
|
||||
import cityIcon from "../../../../resources/images/buildings/cityAlt1.png";
|
||||
import factoryIcon from "../../../../resources/images/buildings/factoryAlt1.png";
|
||||
import shieldIcon from "../../../../resources/images/buildings/fortAlt2.png";
|
||||
import anchorIcon from "../../../../resources/images/buildings/port1.png";
|
||||
import MissileSiloReloadingIcon from "../../../../resources/images/buildings/silo1-reloading.png";
|
||||
import missileSiloIcon from "../../../../resources/images/buildings/silo1.png";
|
||||
import SAMMissileReloadingIcon from "../../../../resources/images/buildings/silo4-reloading.png";
|
||||
import SAMMissileIcon from "../../../../resources/images/buildings/silo4.png";
|
||||
import cityIcon from "../../../../resources/non-commercial/images/buildings/cityAlt1.png";
|
||||
import factoryIcon from "../../../../resources/non-commercial/images/buildings/factoryAlt1.png";
|
||||
import shieldIcon from "../../../../resources/non-commercial/images/buildings/fortAlt3.png";
|
||||
import anchorIcon from "../../../../resources/non-commercial/images/buildings/port1.png";
|
||||
import missileSiloIcon from "../../../../resources/non-commercial/images/buildings/silo1.png";
|
||||
import SAMMissileIcon from "../../../../resources/non-commercial/images/buildings/silo4.png";
|
||||
import { Cell, UnitType } from "../../../core/game/Game";
|
||||
import {
|
||||
euclDistFN,
|
||||
hexDistFN,
|
||||
manhattanDistFN,
|
||||
rectDistFN,
|
||||
} from "../../../core/game/GameMap";
|
||||
import { euclDistFN, isometricDistFN } from "../../../core/game/GameMap";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameView, UnitView } from "../../../core/game/GameView";
|
||||
|
||||
const underConstructionColor = colord({ r: 150, g: 150, b: 150 });
|
||||
const reloadingColor = colord({ r: 255, g: 0, b: 0 });
|
||||
const selectedUnitColor = colord({ r: 0, g: 255, b: 255 });
|
||||
|
||||
// Base radius values and scaling factor for unit borders and territories
|
||||
@@ -33,20 +25,10 @@ const BASE_BORDER_RADIUS = 16.5;
|
||||
const BASE_TERRITORY_RADIUS = 13.5;
|
||||
const RADIUS_SCALE_FACTOR = 0.5;
|
||||
|
||||
type DistanceFunction = typeof euclDistFN;
|
||||
|
||||
enum UnitBorderType {
|
||||
Round,
|
||||
Diamond,
|
||||
Square,
|
||||
Hexagon,
|
||||
}
|
||||
|
||||
interface UnitRenderConfig {
|
||||
icon: string;
|
||||
borderRadius: number;
|
||||
territoryRadius: number;
|
||||
borderType: UnitBorderType;
|
||||
}
|
||||
|
||||
export class StructureLayer implements Layer {
|
||||
@@ -65,37 +47,31 @@ export class StructureLayer implements Layer {
|
||||
icon: anchorIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Round,
|
||||
},
|
||||
[UnitType.City]: {
|
||||
icon: cityIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Round,
|
||||
},
|
||||
[UnitType.Factory]: {
|
||||
icon: factoryIcon,
|
||||
borderRadius: 8.525,
|
||||
territoryRadius: 6.525,
|
||||
borderType: UnitBorderType.Round,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
},
|
||||
[UnitType.MissileSilo]: {
|
||||
icon: missileSiloIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Square,
|
||||
},
|
||||
[UnitType.DefensePost]: {
|
||||
icon: shieldIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Hexagon,
|
||||
},
|
||||
[UnitType.SAMLauncher]: {
|
||||
icon: SAMMissileIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Square,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -117,18 +93,6 @@ export class StructureLayer implements Layer {
|
||||
if (tempContext === null) throw new Error("2d context not supported");
|
||||
this.tempContext = tempContext;
|
||||
this.loadIconData();
|
||||
this.loadIcon("reloadingSam", {
|
||||
icon: SAMMissileReloadingIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Square,
|
||||
});
|
||||
this.loadIcon("reloadingSilo", {
|
||||
icon: MissileSiloReloadingIcon,
|
||||
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
|
||||
borderType: UnitBorderType.Square,
|
||||
});
|
||||
}
|
||||
|
||||
private loadIcon(unitType: string, config: UnitRenderConfig) {
|
||||
@@ -204,12 +168,11 @@ export class StructureLayer implements Layer {
|
||||
unit: UnitView,
|
||||
borderColor: Colord,
|
||||
config: UnitRenderConfig,
|
||||
distanceFN: DistanceFunction,
|
||||
) {
|
||||
// Draw border and territory
|
||||
for (const tile of this.game.bfs(
|
||||
unit.tile(),
|
||||
distanceFN(unit.tile(), config.borderRadius, true),
|
||||
isometricDistFN(unit.tile(), config.borderRadius, true),
|
||||
)) {
|
||||
this.paintCell(
|
||||
new Cell(this.game.x(tile), this.game.y(tile)),
|
||||
@@ -220,7 +183,7 @@ export class StructureLayer implements Layer {
|
||||
|
||||
for (const tile of this.game.bfs(
|
||||
unit.tile(),
|
||||
distanceFN(unit.tile(), config.territoryRadius, true),
|
||||
isometricDistFN(unit.tile(), config.territoryRadius, true),
|
||||
)) {
|
||||
this.paintCell(
|
||||
new Cell(this.game.x(tile), this.game.y(tile)),
|
||||
@@ -232,19 +195,6 @@ export class StructureLayer implements Layer {
|
||||
}
|
||||
}
|
||||
|
||||
private getDrawFN(type: UnitBorderType) {
|
||||
switch (type) {
|
||||
case UnitBorderType.Round:
|
||||
return euclDistFN;
|
||||
case UnitBorderType.Diamond:
|
||||
return manhattanDistFN;
|
||||
case UnitBorderType.Square:
|
||||
return rectDistFN;
|
||||
case UnitBorderType.Hexagon:
|
||||
return hexDistFN;
|
||||
}
|
||||
}
|
||||
|
||||
private handleUnitRendering(unit: UnitView) {
|
||||
const unitType = unit.constructionType() ?? unit.type();
|
||||
const iconType = unitType;
|
||||
@@ -255,13 +205,7 @@ export class StructureLayer implements Layer {
|
||||
let borderColor = this.theme.borderColor(unit.owner());
|
||||
|
||||
// Handle cooldown states and special icons
|
||||
if (unitType === UnitType.SAMLauncher && unit.isInCooldown()) {
|
||||
icon = this.unitIcons.get("reloadingSam");
|
||||
borderColor = reloadingColor;
|
||||
} else if (unitType === UnitType.MissileSilo && unit.isInCooldown()) {
|
||||
icon = this.unitIcons.get("reloadingSilo");
|
||||
borderColor = reloadingColor;
|
||||
} else if (unit.type() === UnitType.Construction) {
|
||||
if (unit.type() === UnitType.Construction) {
|
||||
icon = this.unitIcons.get(iconType);
|
||||
borderColor = underConstructionColor;
|
||||
} else {
|
||||
@@ -270,11 +214,10 @@ export class StructureLayer implements Layer {
|
||||
|
||||
if (!config || !icon) return;
|
||||
|
||||
const drawFunction = this.getDrawFN(config.borderType);
|
||||
// Clear previous rendering
|
||||
for (const tile of this.game.bfs(
|
||||
unit.tile(),
|
||||
drawFunction(unit.tile(), config.borderRadius, true),
|
||||
euclDistFN(unit.tile(), config.borderRadius + 1, true),
|
||||
)) {
|
||||
this.clearCell(new Cell(this.game.x(tile), this.game.y(tile)));
|
||||
}
|
||||
@@ -284,8 +227,7 @@ export class StructureLayer implements Layer {
|
||||
if (this.selectedStructureUnit === unit) {
|
||||
borderColor = selectedUnitColor;
|
||||
}
|
||||
|
||||
this.drawBorder(unit, borderColor, config, drawFunction);
|
||||
this.drawBorder(unit, borderColor, config);
|
||||
|
||||
// Render icon at 1/2 scale for better quality
|
||||
const scaledWidth = icon.width >> 1;
|
||||
@@ -293,7 +235,7 @@ export class StructureLayer implements Layer {
|
||||
const startX = this.game.x(unit.tile()) - (scaledWidth >> 1);
|
||||
const startY = this.game.y(unit.tile()) - (scaledHeight >> 1);
|
||||
|
||||
this.renderIcon(icon, startX, startY, scaledWidth, scaledHeight, unit);
|
||||
this.renderIcon(icon, startX, startY - 4, scaledWidth, scaledHeight, unit);
|
||||
}
|
||||
|
||||
private renderIcon(
|
||||
@@ -320,11 +262,6 @@ export class StructureLayer implements Layer {
|
||||
// Draw the image at final size with high quality scaling
|
||||
this.tempContext.drawImage(image, 0, 0, width * 2, height * 2);
|
||||
|
||||
// Apply color tinting using multiply blend mode
|
||||
this.tempContext.globalCompositeOperation = "multiply";
|
||||
this.tempContext.fillStyle = color.toRgbString();
|
||||
this.tempContext.fillRect(0, 0, width * 2, height * 2);
|
||||
|
||||
// Restore the alpha channel
|
||||
this.tempContext.globalCompositeOperation = "destination-in";
|
||||
this.tempContext.drawImage(image, 0, 0, width * 2, height * 2);
|
||||
|
||||
@@ -19,7 +19,7 @@ const COLOR_PROGRESSION = [
|
||||
"rgb(44, 239, 18)",
|
||||
];
|
||||
const HEALTHBAR_WIDTH = 11; // Width of the health bar
|
||||
const LOADINGBAR_WIDTH = 18; // Width of the loading bar
|
||||
const LOADINGBAR_WIDTH = 14; // Width of the loading bar
|
||||
const PROGRESSBAR_HEIGHT = 3; // Height of a bar
|
||||
|
||||
/**
|
||||
@@ -378,8 +378,8 @@ export class UILayer implements Layer {
|
||||
const progressBar = new ProgressBar(
|
||||
COLOR_PROGRESSION,
|
||||
this.context,
|
||||
this.game.x(unit.tile()) - 8,
|
||||
this.game.y(unit.tile()) - 10,
|
||||
this.game.x(unit.tile()) - 6,
|
||||
this.game.y(unit.tile()) + 6,
|
||||
LOADINGBAR_WIDTH,
|
||||
PROGRESSBAR_HEIGHT,
|
||||
0,
|
||||
|
||||
@@ -376,13 +376,13 @@ label.option-card:hover {
|
||||
}
|
||||
|
||||
#helpModal .missile-silo-icon {
|
||||
mask: url("../../resources/images/MissileSiloIconWhite.svg") no-repeat
|
||||
center / cover;
|
||||
mask: url("../../resources/non-commercial/svg/MissileSiloIconWhite.svg")
|
||||
no-repeat center / cover;
|
||||
}
|
||||
|
||||
#helpModal .sam-launcher-icon {
|
||||
mask: url("../../resources/images/SamLauncherIconWhite.svg") no-repeat
|
||||
center / cover;
|
||||
mask: url("../../resources/non-commercial/svg/SamLauncherIconWhite.svg")
|
||||
no-repeat center / cover;
|
||||
}
|
||||
|
||||
#helpModal .atom-bomb-icon {
|
||||
|
||||
@@ -401,6 +401,39 @@ export function rectDistFN(
|
||||
}
|
||||
}
|
||||
|
||||
function isInIsometricTile(
|
||||
center: { x: number; y: number },
|
||||
tile: { x: number; y: number },
|
||||
yOffset: number,
|
||||
distance: number,
|
||||
): boolean {
|
||||
const dx = Math.abs(tile.x - center.x);
|
||||
const dy = Math.abs(tile.y - (center.y + yOffset));
|
||||
return dx + dy * 2 <= distance + 1;
|
||||
}
|
||||
|
||||
export function isometricDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
if (!center) {
|
||||
return (gm: GameMap, n: TileRef) => gm.manhattanDist(root, n) <= dist;
|
||||
} else {
|
||||
return (gm: GameMap, n: TileRef) => {
|
||||
const rootX = gm.x(root) - 0.5;
|
||||
const rootY = gm.y(root) - 0.5;
|
||||
|
||||
return isInIsometricTile(
|
||||
{ x: rootX, y: rootY },
|
||||
{ x: gm.x(n), y: gm.y(n) },
|
||||
0,
|
||||
dist,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function hexDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
|
||||