Merge branch 'main' into battery-ui
This commit is contained in:
commit
b3b0bfb725
15 changed files with 1296 additions and 38 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
|||
/target
|
||||
*.nix
|
||||
.vscode/
|
305
Cargo.lock
generated
305
Cargo.lock
generated
|
@ -136,6 +136,12 @@ version = "0.12.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
|
@ -207,6 +213,12 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bimap"
|
||||
version = "0.6.3"
|
||||
|
@ -478,8 +490,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "comfy"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e8ff7c66a696e9a9e5523d0c4a6306711acb7f6d490d9c412b044a8c95f17f4"
|
||||
source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c"
|
||||
dependencies = [
|
||||
"comfy-core",
|
||||
"comfy-wgpu",
|
||||
|
@ -499,8 +510,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "comfy-core"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "398260ce649e9d35adc3ae75565406aab9b360c1e892a48ae3606e3138df150b"
|
||||
source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
@ -558,8 +568,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "comfy-wgpu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6118f09fd99577503ba6861dac53840bae6cf202d70f97042f5cdf43c222e39a"
|
||||
source = "git+https://github.com/Plonq/comfy/?branch=101-fix-keyboard-events#6293590aec51875e9832ef05a670149d371f849c"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"comfy-core",
|
||||
|
@ -800,6 +809,12 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
|
||||
|
||||
[[package]]
|
||||
name = "data-url"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -1030,6 +1045,12 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.0"
|
||||
|
@ -1039,6 +1060,29 @@ dependencies = [
|
|||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fontconfig-parser"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d"
|
||||
dependencies = [
|
||||
"roxmltree 0.19.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fontdb"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770"
|
||||
dependencies = [
|
||||
"fontconfig-parser",
|
||||
"log",
|
||||
"memmap2",
|
||||
"slotmap",
|
||||
"tinyvec",
|
||||
"ttf-parser 0.21.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fontdue"
|
||||
version = "0.7.3"
|
||||
|
@ -1134,6 +1178,16 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.28.1"
|
||||
|
@ -1289,6 +1343,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hecs"
|
||||
version = "0.10.5"
|
||||
|
@ -1381,6 +1441,12 @@ dependencies = [
|
|||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imagesize"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
|
@ -1548,6 +1614,16 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kurbo"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e5aa9f0f96a938266bdb12928a67169e8d22c6a786fda8ed984b85e6ba93c3c"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
@ -1995,6 +2071,12 @@ version = "2.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
|
@ -2046,7 +2128,9 @@ name = "powercreep"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"comfy",
|
||||
"heck",
|
||||
"log",
|
||||
"resvg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2227,6 +2311,31 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||
|
||||
[[package]]
|
||||
name = "resvg"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051"
|
||||
dependencies = [
|
||||
"gif",
|
||||
"jpeg-decoder",
|
||||
"log",
|
||||
"pico-args",
|
||||
"rgb",
|
||||
"svgtypes",
|
||||
"tiny-skia",
|
||||
"usvg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ringbuf"
|
||||
version = "0.3.3"
|
||||
|
@ -2236,6 +2345,18 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
|
@ -2261,6 +2382,22 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustybuzz"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bytemuck",
|
||||
"smallvec",
|
||||
"ttf-parser 0.21.1",
|
||||
"unicode-bidi-mirroring",
|
||||
"unicode-ccc",
|
||||
"unicode-properties",
|
||||
"unicode-script",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
|
@ -2326,6 +2463,21 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "832ddd7df0d98d6fd93b973c330b7c8e0742d5cb8f1afc7dea89dba4d2531aa1"
|
||||
|
||||
[[package]]
|
||||
name = "simplecss"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -2417,12 +2569,31 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strict-num"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||
dependencies = [
|
||||
"float-cmp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "svg_fmt"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca"
|
||||
|
||||
[[package]]
|
||||
name = "svgtypes"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fae3064df9b89391c9a76a0425a69d124aee9c5c28455204709e72c39868a43c"
|
||||
dependencies = [
|
||||
"kurbo",
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia"
|
||||
version = "0.5.4"
|
||||
|
@ -2575,6 +2746,47 @@ version = "0.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e170f93360bf9ae6fe3c31116bbf27adb1d054cedd6bc3d7857e34f2d98d0b"
|
||||
|
||||
[[package]]
|
||||
name = "tiny-skia"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
"log",
|
||||
"png",
|
||||
"tiny-skia-path",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-skia-path"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"bytemuck",
|
||||
"strict-num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.6"
|
||||
|
@ -2614,6 +2826,12 @@ version = "0.15.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.24.0"
|
||||
|
@ -2629,18 +2847,54 @@ dependencies = [
|
|||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi-mirroring"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ccc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-properties"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-script"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-vo"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.13"
|
||||
|
@ -2653,6 +2907,33 @@ version = "0.2.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "usvg"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"data-url",
|
||||
"flate2",
|
||||
"fontdb",
|
||||
"imagesize",
|
||||
"kurbo",
|
||||
"log",
|
||||
"pico-args",
|
||||
"roxmltree 0.20.0",
|
||||
"rustybuzz",
|
||||
"simplecss",
|
||||
"siphasher",
|
||||
"strict-num",
|
||||
"svgtypes",
|
||||
"tiny-skia-path",
|
||||
"unicode-bidi",
|
||||
"unicode-script",
|
||||
"unicode-vo",
|
||||
"xmlwriter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
@ -2869,6 +3150,12 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "0.19.4"
|
||||
|
@ -3385,6 +3672,12 @@ version = "0.8.20"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"
|
||||
|
||||
[[package]]
|
||||
name = "xmlwriter"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
|
|
|
@ -17,3 +17,12 @@ opt-level = 3
|
|||
[dependencies]
|
||||
comfy = { version = "0.4.0", features = ["wayland"] }
|
||||
log = "0.4.22"
|
||||
|
||||
[build-dependencies]
|
||||
heck = "0.5"
|
||||
resvg = "0.42"
|
||||
|
||||
[patch.crates-io]
|
||||
# https://github.com/darthdeus/comfy/issues/101
|
||||
# https://github.com/darthdeus/comfy/pull/102
|
||||
comfy = { git = "https://github.com/Plonq/comfy/", branch = "101-fix-keyboard-events" }
|
||||
|
|
220
build.rs
Normal file
220
build.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
use heck::ToSnakeCase as _;
|
||||
use resvg::{tiny_skia, usvg};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
env,
|
||||
fs::{self, File},
|
||||
hash::{DefaultHasher, Hash, Hasher},
|
||||
io::{self, Write as _},
|
||||
path::{Path, PathBuf}
|
||||
};
|
||||
|
||||
const TILE_SIZE: u32 = 64;
|
||||
|
||||
#[derive(Default)]
|
||||
struct Assets {
|
||||
/// Assets directly contained within this asset group, mapping their name to the name
|
||||
/// of the constant storing their png.
|
||||
assets: BTreeMap<String, String>,
|
||||
|
||||
/// Asset groups contained within this asset group, mapping their name to the assets
|
||||
/// that group contains.
|
||||
groups: BTreeMap<String, Box<Assets>>
|
||||
}
|
||||
|
||||
struct AssetsWriter {
|
||||
file: File,
|
||||
root: Assets
|
||||
}
|
||||
|
||||
impl AssetsWriter {
|
||||
fn new<P: AsRef<Path>>(path: P) -> Self {
|
||||
let mut file = File::create(path).expect("Failed to create assets file");
|
||||
writeln!(file, "// @generated").unwrap();
|
||||
Self {
|
||||
file,
|
||||
root: Assets::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_png<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
canonical_path: P,
|
||||
png: tiny_skia::Pixmap
|
||||
) -> String {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
canonical_path.as_ref().hash(&mut hasher);
|
||||
let hash = hasher.finish();
|
||||
let const_name = format!("ASSET_{hash:X}");
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let out_dir: PathBuf = out_dir.into();
|
||||
png.save_png(out_dir.join(format!("{const_name}.png")))
|
||||
.expect("Failed to save png");
|
||||
|
||||
writeln!(self.file, "// {}", canonical_path.as_ref().display()).unwrap();
|
||||
writeln!(
|
||||
self.file,
|
||||
"const {const_name}: &[u8] = include_bytes!(\"{const_name}.png\");"
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
const_name
|
||||
}
|
||||
|
||||
fn finish(mut self) {
|
||||
fn write_assets_struct(
|
||||
file: &mut File,
|
||||
root: &Assets,
|
||||
indent: &str
|
||||
) -> io::Result<()> {
|
||||
for (group_name, group) in &root.groups {
|
||||
writeln!(file, "{indent}mod {group_name} {{")?;
|
||||
writeln!(file, "{indent}\t#[allow(clippy::wildcard_imports)]")?;
|
||||
writeln!(file, "{indent}\tuse super::*;")?;
|
||||
write_assets_struct(file, group, &format!("{indent}\t"))?;
|
||||
writeln!(file, "}}")?;
|
||||
}
|
||||
|
||||
writeln!(file, "{indent}#[allow(dead_code)]")?;
|
||||
writeln!(file, "{indent}pub struct Assets {{")?;
|
||||
for asset_name in root.assets.keys() {
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}\tpub {}: comfy::TextureHandle,",
|
||||
asset_name.to_snake_case()
|
||||
)?;
|
||||
}
|
||||
for group_name in root.groups.keys() {
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}\tpub {group_name}: &'static {group_name}::Assets,"
|
||||
)?;
|
||||
}
|
||||
writeln!(file, "{indent}}}")?;
|
||||
|
||||
writeln!(file, "{indent}impl Assets {{")?;
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}\tpub fn load(c: &mut comfy::EngineContext<'_>) {{"
|
||||
)?;
|
||||
for asset_const_name in root.assets.values() {
|
||||
writeln!(file, "{indent}\t\tc.load_texture_from_bytes({asset_const_name:?}, {asset_const_name});")?;
|
||||
}
|
||||
for group_name in root.groups.keys() {
|
||||
writeln!(file, "{indent}\t\t{group_name}::Assets::load(c);")?;
|
||||
}
|
||||
writeln!(file, "{indent}\t}}")?;
|
||||
writeln!(file, "{indent}}}")?;
|
||||
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}pub static ASSETS: comfy::Lazy<Assets> = comfy::Lazy::new(|| Assets {{"
|
||||
)?;
|
||||
for (asset_name, asset_const_name) in &root.assets {
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}\t{}: comfy::texture_id({asset_const_name:?}),",
|
||||
asset_name.to_snake_case()
|
||||
)?;
|
||||
}
|
||||
for group_name in root.groups.keys() {
|
||||
writeln!(
|
||||
file,
|
||||
"{indent}\t{group_name}: comfy::Lazy::force(&{group_name}::ASSETS),"
|
||||
)?;
|
||||
}
|
||||
writeln!(file, "{indent}}});")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
write_assets_struct(&mut self.file, &self.root, "").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
println!("cargo::rerun-if-changed=assets/");
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let assets = PathBuf::from(out_dir).join("assets.rs");
|
||||
println!("cargo::warning=Writing assets to {}", assets.display());
|
||||
println!("cargo::rustc-env=ASSETS_RS={}", assets.display());
|
||||
let mut writer = AssetsWriter::new(assets);
|
||||
process_dir("assets", &mut writer, &mut Vec::new());
|
||||
writer.finish();
|
||||
}
|
||||
|
||||
fn process_dir<P: AsRef<Path> + Copy>(
|
||||
dir: P,
|
||||
writer: &mut AssetsWriter,
|
||||
groups: &mut Vec<String>
|
||||
) {
|
||||
for entry in fs::read_dir(dir).expect("Cannot read dir") {
|
||||
let entry = entry.expect("Cannot read dir entry");
|
||||
let path = entry.path();
|
||||
if entry
|
||||
.metadata()
|
||||
.expect("Cannot read dir entry metadata")
|
||||
.is_dir()
|
||||
{
|
||||
groups.push(
|
||||
path.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.expect("Non-UTF8 file names aren't allowed")
|
||||
.into()
|
||||
);
|
||||
process_dir(&path, writer, groups);
|
||||
groups.pop();
|
||||
} else if path.extension().map(|ext| ext == "svg").unwrap_or(false) {
|
||||
process_svg(&path, dir, writer, groups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_svg<P: AsRef<Path> + Copy, Q: AsRef<Path>>(
|
||||
file: P,
|
||||
dir: Q,
|
||||
writer: &mut AssetsWriter,
|
||||
groups: &[String]
|
||||
) {
|
||||
let bytes = fs::read(file).expect("Cannot read svg file");
|
||||
let tree = usvg::Tree::from_data(&bytes, &usvg::Options {
|
||||
resources_dir: Some(dir.as_ref().to_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("Cannot parse svg file {}: {err}", file.as_ref().display())
|
||||
});
|
||||
let mut pixmap = tiny_skia::Pixmap::new(TILE_SIZE, TILE_SIZE).unwrap();
|
||||
let transform = tiny_skia::Transform::from_scale(
|
||||
TILE_SIZE as f32 / tree.size().width(),
|
||||
TILE_SIZE as f32 / tree.size().height()
|
||||
);
|
||||
resvg::render(&tree, transform, &mut pixmap.as_mut());
|
||||
|
||||
let const_name = writer.add_png(
|
||||
file.as_ref()
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize"),
|
||||
pixmap
|
||||
);
|
||||
let mut group = &mut writer.root;
|
||||
for group_name in groups {
|
||||
if !group.groups.contains_key(group_name) {
|
||||
group.groups.insert(group_name.to_owned(), Box::default());
|
||||
}
|
||||
group = group.groups.get_mut(group_name).unwrap();
|
||||
}
|
||||
group.assets.insert(
|
||||
file.as_ref()
|
||||
.file_stem()
|
||||
.expect("File doesn't have a stem")
|
||||
.to_str()
|
||||
.expect("Non-UTF8 file names aren't allowed")
|
||||
.into(),
|
||||
const_name
|
||||
);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use comfy::*;
|
||||
|
||||
pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) {
|
||||
draw_circle(vec2(0.0, 0.0), 0.5, RED, 0);
|
||||
}
|
||||
|
||||
pub fn update(_state: &mut crate::State, _engine: &mut comfy::EngineContext) {}
|
69
src/activities/house/grid.rs
Normal file
69
src/activities/house/grid.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use comfy::{draw_circle, draw_line, error, vec2, Vec2, BLUE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Grid {
|
||||
pub nodes: Vec<Vec2>,
|
||||
pub connections: Vec<(usize, usize)>
|
||||
}
|
||||
|
||||
impl Default for Grid {
|
||||
fn default() -> Self {
|
||||
Grid::load() //Just for testing purposes
|
||||
}
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn load() -> Self {
|
||||
let mut grid = Self {
|
||||
nodes: vec![
|
||||
vec2(10.0, 0.0),
|
||||
vec2(0.0, 0.0),
|
||||
vec2(0.0, 10.0),
|
||||
vec2(-10.0, 0.0),
|
||||
vec2(10.0, 10.0),
|
||||
],
|
||||
connections: vec![(0, 1), (1, 2), (1, 3), (0, 4), (0, 5), (5, 1), (6, 7)]
|
||||
};
|
||||
|
||||
grid.sanitize();
|
||||
|
||||
grid
|
||||
}
|
||||
|
||||
fn sanitize(&mut self) {
|
||||
let mut len = self.nodes.len();
|
||||
let connections = self
|
||||
.connections
|
||||
.iter()
|
||||
.filter(|(conn_i1, conn_i2)| {
|
||||
if conn_i1 >= &mut len || conn_i2 >= &mut len {
|
||||
error!("Connection in grid not possible {:?}", (conn_i1, conn_i2));
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|(conn_i1, conn_i2)| (*conn_i1, *conn_i2))
|
||||
.collect();
|
||||
|
||||
self.connections = connections;
|
||||
}
|
||||
|
||||
pub fn draw(&self) {
|
||||
//Draw Grid
|
||||
for node in &self.nodes {
|
||||
draw_circle(*node, 0.25, BLUE, 0);
|
||||
}
|
||||
for (conn_i1, conn_i2) in &self.connections {
|
||||
let node_1 = self.nodes.get(*conn_i1);
|
||||
let node_2 = self.nodes.get(*conn_i2);
|
||||
|
||||
if node_1.is_none() || node_2.is_none() {
|
||||
error!("Connection in grid not available {:?}", (conn_i1, conn_i2));
|
||||
continue;
|
||||
}
|
||||
|
||||
draw_line(*node_1.unwrap(), *node_2.unwrap(), 0.1, BLUE, 0);
|
||||
}
|
||||
}
|
||||
}
|
23
src/activities/house/mod.rs
Normal file
23
src/activities/house/mod.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
mod grid;
|
||||
mod player;
|
||||
|
||||
use grid::Grid;
|
||||
use player::Player;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct HouseState {
|
||||
grid: Grid,
|
||||
player: Player
|
||||
}
|
||||
|
||||
pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) {
|
||||
//Draw Grid
|
||||
state.house.grid.draw();
|
||||
|
||||
//Draw Player
|
||||
state.house.player.draw();
|
||||
}
|
||||
|
||||
pub fn update(state: &mut crate::State, _engine: &mut comfy::EngineContext<'_>) {
|
||||
state.house.player.update(&state.house.grid);
|
||||
}
|
268
src/activities/house/player.rs
Normal file
268
src/activities/house/player.rs
Normal file
|
@ -0,0 +1,268 @@
|
|||
use super::Grid;
|
||||
use comfy::{delta, draw_circle, is_key_down, vec2, KeyCode, Vec2, RED};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Player {
|
||||
position: Vec2,
|
||||
speed: f32,
|
||||
connection: usize,
|
||||
next_connections: Vec<usize>
|
||||
}
|
||||
|
||||
impl Default for Player {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
position: Default::default(),
|
||||
speed: 10.0,
|
||||
connection: 0,
|
||||
next_connections: vec![1, 2, 3]
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Player {
|
||||
pub fn draw(&self) {
|
||||
draw_circle(self.position, 0.5, RED, 0);
|
||||
}
|
||||
pub fn update(&mut self, grid: &Grid) {
|
||||
let allowed_movement = get_allowed_movement(self, grid);
|
||||
|
||||
move_player(self, allowed_movement);
|
||||
|
||||
if !on_current_connection(self, grid) && !update_connections(self, grid) {
|
||||
snap_to_closest_node(self, grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_player(player: &mut Player, allowed_movement: (bool, bool, bool, bool)) {
|
||||
let (
|
||||
allow_up_movement,
|
||||
allow_down_movement,
|
||||
allow_left_movement,
|
||||
allow_right_movement
|
||||
) = allowed_movement;
|
||||
|
||||
if allow_up_movement && is_key_down(KeyCode::Up) {
|
||||
player.position += vec2(0.0, player.speed) * delta();
|
||||
}
|
||||
|
||||
if allow_down_movement && is_key_down(KeyCode::Down) {
|
||||
player.position += vec2(0.0, -player.speed) * delta();
|
||||
}
|
||||
|
||||
if allow_right_movement && is_key_down(KeyCode::Right) {
|
||||
player.position += vec2(player.speed, 0.0) * delta();
|
||||
}
|
||||
|
||||
if allow_left_movement && is_key_down(KeyCode::Left) {
|
||||
player.position += vec2(-player.speed, 0.0) * delta();
|
||||
}
|
||||
}
|
||||
|
||||
//(UP, DOWN, LEFT, RIGHT)
|
||||
fn get_allowed_movement(player: &Player, grid: &Grid) -> (bool, bool, bool, bool) {
|
||||
let (conn_i1, conn_i2) = grid.connections.get(player.connection).unwrap();
|
||||
let node_1 = grid.nodes.get(*conn_i1).unwrap();
|
||||
let node_2 = grid.nodes.get(*conn_i2).unwrap();
|
||||
|
||||
let range = 0.25;
|
||||
|
||||
if in_node_range(&player.position, node_1, range)
|
||||
|| in_node_range(&player.position, node_2, range)
|
||||
{
|
||||
(true, true, true, true)
|
||||
} else {
|
||||
let (
|
||||
mut allow_up_movement,
|
||||
mut allow_down_movement,
|
||||
mut allow_left_movement,
|
||||
mut allow_right_movement
|
||||
) = get_allowed_connection_movement(&player.position, node_1, node_2);
|
||||
|
||||
for conn in &player.next_connections {
|
||||
let (next_conn_i1, next_conn_i2) = grid.connections.get(*conn).unwrap();
|
||||
let next_node_1 = grid.nodes.get(*next_conn_i1).unwrap();
|
||||
let next_node_2 = grid.nodes.get(*next_conn_i2).unwrap();
|
||||
|
||||
let (
|
||||
next_allow_up_movement,
|
||||
next_allow_down_movement,
|
||||
next_allow_left_movement,
|
||||
next_allow_right_movement
|
||||
) = get_allowed_connection_movement(&player.position, next_node_1, next_node_2);
|
||||
|
||||
(
|
||||
allow_up_movement,
|
||||
allow_down_movement,
|
||||
allow_left_movement,
|
||||
allow_right_movement
|
||||
) = (
|
||||
allow_up_movement || next_allow_up_movement,
|
||||
allow_down_movement || next_allow_down_movement,
|
||||
allow_left_movement || next_allow_left_movement,
|
||||
allow_right_movement || next_allow_right_movement
|
||||
);
|
||||
}
|
||||
(
|
||||
allow_up_movement,
|
||||
allow_down_movement,
|
||||
allow_left_movement,
|
||||
allow_right_movement
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//(UP, DOWN, LEFT, RIGHT)
|
||||
fn get_allowed_connection_movement(
|
||||
player_position: &Vec2,
|
||||
node_1: &Vec2,
|
||||
node_2: &Vec2
|
||||
) -> (bool, bool, bool, bool) {
|
||||
let allow_left_movement = {
|
||||
if node_1.x <= node_2.x {
|
||||
node_1.x < player_position.x
|
||||
&& player_position.x <= node_2.x
|
||||
&& player_position.y == node_1.y
|
||||
} else {
|
||||
node_2.x < player_position.x
|
||||
&& player_position.x <= node_1.x
|
||||
&& player_position.y == node_1.y
|
||||
}
|
||||
};
|
||||
|
||||
let allow_right_movement = {
|
||||
if node_1.x <= node_2.x {
|
||||
node_1.x <= player_position.x
|
||||
&& player_position.x < node_2.x
|
||||
&& player_position.y == node_1.y
|
||||
} else {
|
||||
node_2.x <= player_position.x
|
||||
&& player_position.x < node_1.x
|
||||
&& player_position.y == node_1.y
|
||||
}
|
||||
};
|
||||
|
||||
let allow_up_movement = {
|
||||
if node_1.y <= node_2.y {
|
||||
node_1.y <= player_position.y
|
||||
&& player_position.y < node_2.y
|
||||
&& player_position.x == node_1.x
|
||||
} else {
|
||||
node_2.y <= player_position.y
|
||||
&& player_position.y < node_1.y
|
||||
&& player_position.x == node_1.x
|
||||
}
|
||||
};
|
||||
|
||||
let allow_down_movement = {
|
||||
if node_1.y <= node_2.y {
|
||||
node_1.y < player_position.y
|
||||
&& player_position.y <= node_2.y
|
||||
&& player_position.x == node_1.x
|
||||
} else {
|
||||
node_2.y < player_position.y
|
||||
&& player_position.y <= node_1.y
|
||||
&& player_position.x == node_1.x
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
allow_up_movement,
|
||||
allow_down_movement,
|
||||
allow_left_movement,
|
||||
allow_right_movement
|
||||
)
|
||||
}
|
||||
|
||||
fn on_current_connection(player: &Player, grid: &Grid) -> bool {
|
||||
let (conn_i1, conn_i2) = grid.connections.get(player.connection).unwrap();
|
||||
let node_1 = grid.nodes.get(*conn_i1).unwrap();
|
||||
let node_2 = grid.nodes.get(*conn_i2).unwrap();
|
||||
|
||||
on_connection(&player.position, node_1, node_2)
|
||||
}
|
||||
|
||||
fn on_connection(player_position: &Vec2, node_1: &Vec2, node_2: &Vec2) -> bool {
|
||||
let on_x = if node_1.x <= node_2.x {
|
||||
node_1.x <= player_position.x && player_position.x <= node_2.x
|
||||
} else {
|
||||
node_2.x <= player_position.x && player_position.x <= node_1.x
|
||||
};
|
||||
|
||||
let on_y = if node_1.y <= node_2.y {
|
||||
node_1.y <= player_position.y && player_position.y <= node_2.y
|
||||
} else {
|
||||
node_2.y <= player_position.y && player_position.y <= node_1.y
|
||||
};
|
||||
|
||||
on_x && on_y
|
||||
}
|
||||
|
||||
fn update_connections(player: &mut Player, grid: &Grid) -> bool {
|
||||
for conn in &player.next_connections {
|
||||
let (next_conn_i1, next_conn_i2) = grid.connections.get(*conn).unwrap();
|
||||
let next_node_1 = grid.nodes.get(*next_conn_i1).unwrap();
|
||||
let next_node_2 = grid.nodes.get(*next_conn_i2).unwrap();
|
||||
|
||||
if on_connection(&player.position, next_node_1, next_node_2) {
|
||||
player.connection = *conn;
|
||||
//Update next connections
|
||||
let mut next_connections = Vec::new();
|
||||
for (i, (poss_conn_i1, poss_conn_i2)) in grid.connections.iter().enumerate() {
|
||||
if (next_conn_i1, next_conn_i2) != (poss_conn_i1, poss_conn_i2)
|
||||
&& next_conn_i1 == poss_conn_i1
|
||||
|| next_conn_i1 == poss_conn_i2
|
||||
|| next_conn_i2 == poss_conn_i1
|
||||
|| next_conn_i2 == poss_conn_i2
|
||||
{
|
||||
next_connections.push(i);
|
||||
}
|
||||
}
|
||||
player.next_connections = next_connections;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn in_node_range(player_position: &Vec2, node: &Vec2, range: f32) -> bool {
|
||||
node.x - range <= player_position.x
|
||||
&& player_position.x <= node.x + range
|
||||
&& node.y - range <= player_position.y
|
||||
&& player_position.y <= node.y + range
|
||||
}
|
||||
|
||||
fn get_squared_node_range(player_position: &Vec2, node: &Vec2) -> f32 {
|
||||
(player_position.x - node.x).abs() + (player_position.y - node.y).abs()
|
||||
}
|
||||
|
||||
fn snap_to_closest_node(player: &mut Player, grid: &Grid) {
|
||||
let (current_connection_index_1, current_connection_index_2) =
|
||||
grid.connections.get(player.connection).unwrap();
|
||||
|
||||
let mut nodes = HashSet::new();
|
||||
nodes.insert(current_connection_index_1);
|
||||
nodes.insert(current_connection_index_2);
|
||||
for conn in &player.next_connections {
|
||||
let (next_connection_index_1, next_connection_index_2) =
|
||||
grid.connections.get(*conn).unwrap();
|
||||
|
||||
nodes.insert(next_connection_index_1);
|
||||
nodes.insert(next_connection_index_2);
|
||||
}
|
||||
|
||||
let mut closest_sqared_range = f32::MAX;
|
||||
let mut closest_node = &vec2(0.0, 0.0);
|
||||
for node_index in nodes {
|
||||
let current_node = grid.nodes.get(*node_index).unwrap();
|
||||
let current_squard_range = get_squared_node_range(&player.position, current_node);
|
||||
if closest_sqared_range > current_squard_range {
|
||||
closest_sqared_range = current_squard_range;
|
||||
closest_node = current_node;
|
||||
}
|
||||
}
|
||||
|
||||
player.position = *closest_node;
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
pub mod house;
|
||||
pub mod overworld;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub enum Activity {
|
||||
#[allow(dead_code)]
|
||||
House,
|
||||
#[default]
|
||||
Overworld
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
use comfy::*;
|
||||
|
||||
pub fn draw(_state: &crate::State, _engine: &comfy::EngineContext) {
|
||||
draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0);
|
||||
}
|
||||
|
||||
pub fn update(_state: &mut crate::State, _engine: &mut comfy::EngineContext) {}
|
31
src/activities/overworld/mod.rs
Normal file
31
src/activities/overworld/mod.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use comfy::{
|
||||
draw_rect_outline, draw_sprite, main_camera_mut, EngineContext, IVec2, Vec2, RED,
|
||||
WHITE
|
||||
};
|
||||
|
||||
use crate::game::ZLayer;
|
||||
|
||||
pub mod worldgen;
|
||||
|
||||
pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) {
|
||||
for (coords, tile) in state.overworld.iter_tiles() {
|
||||
for (i, texture) in tile.textures().iter().rev().enumerate() {
|
||||
let i = i as i32;
|
||||
draw_sprite(
|
||||
*texture,
|
||||
coords.as_vec2(),
|
||||
WHITE,
|
||||
ZLayer::MapMax - i,
|
||||
Vec2::ONE
|
||||
);
|
||||
draw_rect_outline(coords.as_vec2(), Vec2::ONE, 0.1, RED, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(state: &mut crate::State, _engine: &mut EngineContext<'_>) {
|
||||
let mut camera = main_camera_mut();
|
||||
camera.center = Vec2::ZERO;
|
||||
camera.zoom = 30.0;
|
||||
state.overworld.get_or_generate_tile(IVec2::ZERO);
|
||||
}
|
316
src/activities/overworld/worldgen.rs
Normal file
316
src/activities/overworld/worldgen.rs
Normal file
|
@ -0,0 +1,316 @@
|
|||
// TODO remove this
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::assets::ASSETS;
|
||||
use comfy::{IVec2, TextureHandle, UVec2};
|
||||
use log::info;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub enum MovementCost {
|
||||
/// No movement possible - cost infinitely high.
|
||||
Infinite,
|
||||
/// There is a path for this movement - movement is cheap.
|
||||
Path,
|
||||
/// There is no path and no obstacle.
|
||||
Default,
|
||||
/// There is an obstacle (i.e. fence) - movement is expensive.
|
||||
Obstacle
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Tile {
|
||||
Grass,
|
||||
|
||||
Path {
|
||||
left: bool,
|
||||
right: bool,
|
||||
top: bool,
|
||||
bottom: bool
|
||||
},
|
||||
|
||||
House {
|
||||
texture: TextureHandle,
|
||||
door: bool
|
||||
}
|
||||
}
|
||||
|
||||
impl Tile {
|
||||
pub fn textures(&self) -> Vec<TextureHandle> {
|
||||
match self {
|
||||
Self::Grass => vec![ASSETS.overworld.grass],
|
||||
|
||||
Self::Path {
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
bottom
|
||||
} => {
|
||||
let path_texture = match (left, right, top, bottom) {
|
||||
(true, true, false, false) => ASSETS.overworld.path_horiz,
|
||||
(false, false, true, true) => ASSETS.overworld.path_vert,
|
||||
|
||||
(true, false, true, false) => ASSETS.overworld.path_top_left,
|
||||
(true, false, false, true) => ASSETS.overworld.path_bottom_left,
|
||||
(false, true, true, false) => ASSETS.overworld.path_top_right,
|
||||
(false, true, false, true) => ASSETS.overworld.path_bottom_right,
|
||||
|
||||
(true, true, true, false) => ASSETS.overworld.path_top_left_right,
|
||||
(true, true, false, true) => ASSETS.overworld.path_bottom_left_right,
|
||||
(true, false, true, true) => ASSETS.overworld.path_top_left_bottom,
|
||||
(false, true, true, true) => ASSETS.overworld.path_top_right_bottom,
|
||||
|
||||
(true, true, true, true) => ASSETS.overworld.path_crossing,
|
||||
|
||||
(true, false, false, false)
|
||||
| (false, true, false, false)
|
||||
| (false, false, true, false)
|
||||
| (false, false, false, true) => panic!("We don't have no dead ends"),
|
||||
(false, false, false, false) => panic!("I think you meant grass?!?")
|
||||
};
|
||||
|
||||
vec![ASSETS.overworld.grass, path_texture]
|
||||
},
|
||||
|
||||
Self::House { texture, .. } => {
|
||||
vec![ASSETS.overworld.grass, *texture]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_stand_inside(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn movement_cost_left(&self) -> MovementCost {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn movement_cost_right(&self) -> MovementCost {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn movement_cost_up(&self) -> MovementCost {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn movement_cost_down(&self) -> MovementCost {
|
||||
unimplemented!()
|
||||
}
|
||||
pub fn can_enter_house(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// The size of a chunk (both width and height). This value squared gives the amount of
|
||||
/// tiles in the chunk.
|
||||
const CHUNK_SIZE: u32 = 100;
|
||||
|
||||
/// Chunks
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub struct Chunk {
|
||||
/// All tiles within this chunk.
|
||||
tiles: [Tile; (CHUNK_SIZE * CHUNK_SIZE) as usize],
|
||||
/// All paths that leave this chunk on the left hand side.
|
||||
paths_left: Vec<u32>,
|
||||
/// All paths that leave this chunk on the right hand side.
|
||||
paths_right: Vec<u32>,
|
||||
/// All paths that leave this chunk on the bottom side.
|
||||
paths_bottom: Vec<u32>,
|
||||
/// All paths that leave this chunk on the top side.
|
||||
paths_top: Vec<u32>
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub fn generate_chunk() -> Self {
|
||||
info!("gen chunk");
|
||||
// TODO real worldgen
|
||||
// for the time being we just copy this pre-made house block into the chunk
|
||||
|
||||
fn path(left: bool, right: bool, top: bool, bottom: bool) -> Tile {
|
||||
Tile::Path {
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
bottom
|
||||
}
|
||||
}
|
||||
|
||||
fn house(texture: TextureHandle) -> Tile {
|
||||
Tile::House {
|
||||
texture,
|
||||
door: false
|
||||
}
|
||||
}
|
||||
|
||||
let path_horiz = path(true, true, false, false);
|
||||
let path_vert = path(false, false, true, true);
|
||||
let path_crossing = path(true, true, true, true);
|
||||
let grass = Tile::Grass;
|
||||
|
||||
let block = [
|
||||
[
|
||||
path_crossing,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_crossing
|
||||
],
|
||||
[
|
||||
path_vert,
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
house(ASSETS.overworld.house_roof_top),
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
path_vert
|
||||
],
|
||||
[
|
||||
path_vert,
|
||||
grass,
|
||||
grass,
|
||||
house(ASSETS.overworld.house_roof_mid_left),
|
||||
house(ASSETS.overworld.house_mid_window),
|
||||
house(ASSETS.overworld.house_roof_mid_right),
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
path_vert
|
||||
],
|
||||
[
|
||||
path_vert,
|
||||
grass,
|
||||
house(ASSETS.overworld.house_roof_left),
|
||||
house(ASSETS.overworld.house_mid_window),
|
||||
house(ASSETS.overworld.house_mid),
|
||||
house(ASSETS.overworld.house_mid_window),
|
||||
house(ASSETS.overworld.house_roof_right),
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
path_vert
|
||||
],
|
||||
[
|
||||
path_vert,
|
||||
grass,
|
||||
house(ASSETS.overworld.house_bottom_left),
|
||||
house(ASSETS.overworld.house_bottom_door),
|
||||
house(ASSETS.overworld.house_bottom_window),
|
||||
house(ASSETS.overworld.house_bottom_window),
|
||||
house(ASSETS.overworld.house_bottom_right),
|
||||
grass,
|
||||
grass,
|
||||
grass,
|
||||
path_vert
|
||||
],
|
||||
[
|
||||
path_vert,
|
||||
grass,
|
||||
grass,
|
||||
path(false, true, true, false),
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path_horiz,
|
||||
path(true, false, true, true)
|
||||
],
|
||||
[
|
||||
path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass,
|
||||
path_vert
|
||||
],
|
||||
[
|
||||
path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass,
|
||||
path_vert
|
||||
]
|
||||
];
|
||||
|
||||
// and then we copy this pre-made block into our chunk
|
||||
let mut tiles = [Tile::Grass; (CHUNK_SIZE * CHUNK_SIZE) as usize];
|
||||
for y in 0 .. CHUNK_SIZE {
|
||||
for x in 0 .. CHUNK_SIZE {
|
||||
let row = block[y as usize % block.len()];
|
||||
tiles[(y * CHUNK_SIZE + x) as usize] = row[x as usize % row.len()];
|
||||
}
|
||||
}
|
||||
Self {
|
||||
tiles,
|
||||
paths_left: vec![],
|
||||
paths_right: vec![],
|
||||
paths_bottom: vec![],
|
||||
paths_top: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> {
|
||||
self.tiles
|
||||
.get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize)
|
||||
}
|
||||
|
||||
/// iterate over all tiles and its local chunk coords
|
||||
pub fn iter_tiles(&self) -> impl Iterator<Item = (UVec2, &Tile)> {
|
||||
self.tiles.iter().enumerate().map(|(i, tile)| {
|
||||
let i = i as u32;
|
||||
(UVec2::new(i % CHUNK_SIZE, i / CHUNK_SIZE), tile)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Overworld {
|
||||
chunks: HashMap<IVec2, Chunk>
|
||||
}
|
||||
|
||||
fn world_to_chunk_and_local_coords(world_coords: IVec2) -> (IVec2, UVec2) {
|
||||
let chunk_coords = IVec2 {
|
||||
x: world_coords.x.div_euclid(CHUNK_SIZE as _),
|
||||
y: world_coords.y.div_euclid(CHUNK_SIZE as _)
|
||||
};
|
||||
let local_chunk_coords = UVec2 {
|
||||
x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _,
|
||||
y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _
|
||||
};
|
||||
(chunk_coords, local_chunk_coords)
|
||||
}
|
||||
|
||||
impl Overworld {
|
||||
/// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not
|
||||
/// been generated yet.
|
||||
pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> {
|
||||
let (chunk_coords, local_chunk_coords) =
|
||||
world_to_chunk_and_local_coords(world_coords);
|
||||
|
||||
let chunk = self.chunks.get(&chunk_coords)?;
|
||||
chunk.get_tile(local_chunk_coords)
|
||||
}
|
||||
|
||||
pub fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile {
|
||||
let (chunk_coords, local_chunk_coords) =
|
||||
world_to_chunk_and_local_coords(world_coords);
|
||||
|
||||
let chunk = self
|
||||
.chunks
|
||||
.entry(chunk_coords)
|
||||
.or_insert_with(Chunk::generate_chunk);
|
||||
chunk.get_tile(local_chunk_coords).unwrap()
|
||||
}
|
||||
|
||||
/// iterate over all tiles and its global coords
|
||||
pub fn iter_tiles(&self) -> impl Iterator<Item = (IVec2, &Tile)> {
|
||||
self.chunks.iter().flat_map(|(chunk_coords, chunk)| {
|
||||
chunk.iter_tiles().map(|(local_coords, tile)| {
|
||||
// never fail because chunksize fits alswas into i32
|
||||
let local_coords: IVec2 = local_coords.try_into().unwrap();
|
||||
(local_coords + (*chunk_coords * CHUNK_SIZE as i32), tile)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
29
src/game.rs
29
src/game.rs
|
@ -1,9 +1,9 @@
|
|||
use comfy::*;
|
||||
|
||||
use crate::{
|
||||
activities::{house, overworld, Activity},
|
||||
State
|
||||
};
|
||||
use comfy::EngineContext;
|
||||
use std::ops::Sub;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Gost {
|
||||
|
@ -21,15 +21,36 @@ impl Default for Gost {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[repr(i32)]
|
||||
pub enum ZLayer {
|
||||
MapMax = -1,
|
||||
Human = 0,
|
||||
Ghost = 1
|
||||
}
|
||||
|
||||
pub fn update(state: &mut State, engine: &mut EngineContext) {
|
||||
impl From<ZLayer> for i32 {
|
||||
fn from(value: ZLayer) -> Self {
|
||||
// safe because #[repr(i32)]
|
||||
value as i32
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<i32> for ZLayer {
|
||||
type Output = i32;
|
||||
|
||||
fn sub(self, other: i32) -> Self::Output {
|
||||
i32::from(self) - other
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(state: &mut State, engine: &mut EngineContext<'_>) {
|
||||
match state.activity {
|
||||
Activity::House => house::update(state, engine),
|
||||
Activity::Overworld => overworld::update(state, engine)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(state: &State, engine: &EngineContext) {
|
||||
pub fn draw(state: &State, engine: &EngineContext<'_>) {
|
||||
match state.activity {
|
||||
Activity::House => house::draw(state, engine),
|
||||
Activity::Overworld => overworld::draw(state, engine)
|
||||
|
|
44
src/main.rs
44
src/main.rs
|
@ -1,26 +1,35 @@
|
|||
#![warn(rust_2018_idioms)]
|
||||
#![deny(clippy::wildcard_imports)]
|
||||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||
|
||||
mod assets {
|
||||
include!(env!("ASSETS_RS"));
|
||||
}
|
||||
|
||||
mod activities;
|
||||
mod game;
|
||||
mod ui;
|
||||
|
||||
use activities::Activity;
|
||||
use comfy::*;
|
||||
use self::{
|
||||
activities::{house::HouseState, overworld::worldgen::Overworld, Activity},
|
||||
assets::Assets
|
||||
use game::Gost;
|
||||
};
|
||||
use comfy::{
|
||||
init_game_config, pollster, run_comfy_main_async, EngineContext, EngineState,
|
||||
GameConfig, GameLoop
|
||||
};
|
||||
|
||||
const GAME_NAME: &str = "Powercreep";
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
struct State {
|
||||
setup_called: bool,
|
||||
activity: Activity,
|
||||
activity: Activity,
|
||||
gohst: Gost
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
activity: Activity::House,
|
||||
gohst: Default::default()
|
||||
}
|
||||
}
|
||||
overworld: Overworld,
|
||||
house: HouseState
|
||||
}
|
||||
|
||||
impl GameLoop for State {
|
||||
|
@ -28,7 +37,12 @@ impl GameLoop for State {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
fn update(&mut self, engine: &mut EngineContext) {
|
||||
fn update(&mut self, engine: &mut EngineContext<'_>) {
|
||||
if !self.setup_called {
|
||||
setup(engine);
|
||||
self.setup_called = true;
|
||||
}
|
||||
|
||||
game::update(self, engine);
|
||||
game::draw(self, engine);
|
||||
}
|
||||
|
@ -38,6 +52,10 @@ fn config(config: GameConfig) -> GameConfig {
|
|||
config
|
||||
}
|
||||
|
||||
fn setup(ctx: &mut EngineContext<'_>) {
|
||||
Assets::load(ctx);
|
||||
}
|
||||
|
||||
async fn run() {
|
||||
init_game_config(GAME_NAME.to_string(), env!("CARGO_PKG_VERSION"), config);
|
||||
let mut engine = EngineState::new();
|
||||
|
|
Loading…
Reference in a new issue