Compare commits

..

No commits in common. "master" and "0.1.0" have entirely different histories.

16 changed files with 438 additions and 728 deletions

540
Cargo.lock generated
View File

@ -321,6 +321,12 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bevy"
version = "0.15.0"
@ -332,9 +338,9 @@ dependencies = [
[[package]]
name = "bevy-inspector-egui"
version = "0.28.1"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36172627eb6fd8586600972bcbba2880ed6f59e4e243dcf2ed7ff68d987577ce"
checksum = "dd64580f4496ed987c6231c6a7d833068914331a9084bf5a3dd9dcbc66fd8a73"
dependencies = [
"bevy-inspector-egui-derive",
"bevy_app",
@ -348,6 +354,7 @@ dependencies = [
"bevy_image",
"bevy_log",
"bevy_math",
"bevy_pbr",
"bevy_reflect",
"bevy_render",
"bevy_state",
@ -387,6 +394,38 @@ dependencies = [
"bevy_reflect",
]
[[package]]
name = "bevy_animation"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee48f3fc65f583e5e320e38874053e20e7a71205a62aaace5d607446781bd742"
dependencies = [
"bevy_app",
"bevy_asset",
"bevy_color",
"bevy_core",
"bevy_derive",
"bevy_ecs",
"bevy_hierarchy",
"bevy_log",
"bevy_math",
"bevy_reflect",
"bevy_render",
"bevy_time",
"bevy_transform",
"bevy_utils",
"blake3",
"derive_more",
"downcast-rs",
"either",
"petgraph",
"ron",
"serde",
"smallvec",
"thread_local",
"uuid",
]
[[package]]
name = "bevy_app"
version = "0.15.0"
@ -636,6 +675,21 @@ dependencies = [
"encase_derive_impl",
]
[[package]]
name = "bevy_gilrs"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc3a5f9e872133d7f5c2fab82e17781c19ed0b98f371362a23ed972bb538d20"
dependencies = [
"bevy_app",
"bevy_ecs",
"bevy_input",
"bevy_time",
"bevy_utils",
"derive_more",
"gilrs",
]
[[package]]
name = "bevy_gizmos"
version = "0.15.0"
@ -650,6 +704,7 @@ dependencies = [
"bevy_gizmos_macros",
"bevy_image",
"bevy_math",
"bevy_pbr",
"bevy_reflect",
"bevy_render",
"bevy_sprite",
@ -671,6 +726,38 @@ dependencies = [
"syn 2.0.90",
]
[[package]]
name = "bevy_gltf"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b21ed694796a001a5cf63de9ddc62fc017302b0e2998a361ef1126880ec93555"
dependencies = [
"base64 0.22.1",
"bevy_animation",
"bevy_app",
"bevy_asset",
"bevy_color",
"bevy_core",
"bevy_core_pipeline",
"bevy_ecs",
"bevy_hierarchy",
"bevy_image",
"bevy_math",
"bevy_pbr",
"bevy_reflect",
"bevy_render",
"bevy_scene",
"bevy_tasks",
"bevy_transform",
"bevy_utils",
"derive_more",
"gltf",
"percent-encoding",
"serde",
"serde_json",
"smallvec",
]
[[package]]
name = "bevy_hierarchy"
version = "0.15.0"
@ -702,6 +789,8 @@ dependencies = [
"derive_more",
"futures-lite",
"image",
"ktx2",
"ruzstd",
"serde",
"wgpu 23.0.1",
]
@ -729,6 +818,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4237e6e9b03902321032f00f931f18a4a211093bd9a7cf81276a0228a2a4417"
dependencies = [
"bevy_a11y",
"bevy_animation",
"bevy_app",
"bevy_asset",
"bevy_audio",
@ -738,7 +828,9 @@ dependencies = [
"bevy_derive",
"bevy_diagnostic",
"bevy_ecs",
"bevy_gilrs",
"bevy_gizmos",
"bevy_gltf",
"bevy_hierarchy",
"bevy_image",
"bevy_input",
@ -880,12 +972,14 @@ dependencies = [
"bevy_hierarchy",
"bevy_input",
"bevy_math",
"bevy_mesh",
"bevy_reflect",
"bevy_render",
"bevy_time",
"bevy_transform",
"bevy_utils",
"bevy_window",
"crossbeam-channel",
"uuid",
]
@ -910,6 +1004,7 @@ dependencies = [
"downcast-rs",
"erased-serde",
"glam",
"petgraph",
"serde",
"smallvec",
"smol_str",
@ -963,6 +1058,7 @@ dependencies = [
"futures-lite",
"image",
"js-sys",
"ktx2",
"naga 23.1.0",
"naga_oil",
"nonmax",
@ -1370,17 +1466,6 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "buns"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75f1d46ab84e22a81b97efa9ee5f22a3f3508edf23a0203904f213b4faf32fe2"
dependencies = [
"deki_proc",
"extension-traits",
"maflow",
]
[[package]]
name = "bytemuck"
version = "1.20.0"
@ -1633,15 +1718,6 @@ dependencies = [
"const_soft_float",
]
[[package]]
name = "convert_case"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
@ -1846,77 +1922,6 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "deki"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d99371f8ebec1287967d7316c45cc22490db154e695c40dc697640f5ad07a221"
dependencies = [
"deki_core",
"deki_derive",
"deki_lerp",
"deki_macros",
"deki_proc",
]
[[package]]
name = "deki_core"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b95a4595bf7b9f83a550c7f3daee5fa03ab7113f8ac9db49cbe91f282089c3a"
dependencies = [
"buns",
"derive-new",
"derive_more",
"extension-traits",
"fastapprox",
"fastrand",
"maflow",
"type_cell",
]
[[package]]
name = "deki_derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7812924b99c75f34230c3cff26a07e0d4253f56b84865d5e3f3750ff0dcb1db6"
dependencies = [
"derive_preset",
]
[[package]]
name = "deki_lerp"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64245eb17aca538ee0fb665909b324eb9219f6df57b029af5c1c53aaada0be5"
dependencies = [
"deki_core",
]
[[package]]
name = "deki_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058a36abf7e6c386334e058279c3aecc80bb8bd56f4254837d0f9c4eeafaaaa4"
dependencies = [
"deki_core",
"deki_proc",
]
[[package]]
name = "deki_proc"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47ae1da716b4b85978363cefa6963d63d0896ce9e4295b12c4a1636ad264dee3"
dependencies = [
"convert_case",
"extension-traits",
"maflow",
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "delaunator"
version = "1.0.2"
@ -1926,17 +1931,6 @@ dependencies = [
"robust",
]
[[package]]
name = "derive-new"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "derive_more"
version = "1.0.0"
@ -1952,23 +1946,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"syn 2.0.90",
"unicode-xid",
]
[[package]]
name = "derive_preset"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c676aecfc734fb672c8bf150b6984da6397d05a269a6bbe7308d6ddc91edf7e"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@ -2185,41 +2168,6 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "ext-trait"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703090345f7d5de48379b391c9dfe69967a3c1694730a3e53bf4c905f71069c0"
dependencies = [
"ext-trait-proc_macros",
]
[[package]]
name = "ext-trait-proc_macros"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9f3f15f123dee4e8a6b14f033ba22904a48c5935505dc07225ce440e640d8b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "extension-traits"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "360cbc11ebc403c8ebb731dfb4d3950835d40d3d9a20f0e89a27b17e991d0863"
dependencies = [
"ext-trait",
]
[[package]]
name = "fastapprox"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dfa3c0fd35278e839805680f4c2f673ca71eb91068115b4a611e71429bc0c46"
[[package]]
name = "fastrand"
version = "2.3.0"
@ -2257,6 +2205,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.4"
@ -2324,7 +2278,7 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
name = "forestiles"
version = "0.4.0"
version = "0.1.0"
dependencies = [
"android_logger",
"bevy",
@ -2333,7 +2287,6 @@ dependencies = [
"console_log",
"getrandom",
"log",
"mevy",
"noise",
"rand",
"voronoice",
@ -2418,6 +2371,40 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "gilrs"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb2c998745a3c1ac90f64f4f7b3a54219fd3612d7705e7798212935641ed18f"
dependencies = [
"fnv",
"gilrs-core",
"log",
"uuid",
"vec_map",
]
[[package]]
name = "gilrs-core"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "495af945e45efd6386227613cd9fb7bd7c43d3c095040e30c5304c489e6abed5"
dependencies = [
"core-foundation 0.10.0",
"inotify",
"io-kit-sys",
"js-sys",
"libc",
"libudev-sys",
"log",
"nix",
"uuid",
"vec_map",
"wasm-bindgen",
"web-sys",
"windows 0.52.0",
]
[[package]]
name = "gl_generator"
version = "0.14.0"
@ -2470,6 +2457,42 @@ dependencies = [
"web-sys",
]
[[package]]
name = "gltf"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7"
dependencies = [
"byteorder",
"gltf-json",
"lazy_static",
"serde_json",
]
[[package]]
name = "gltf-derive"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51"
dependencies = [
"inflections",
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "gltf-json"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14"
dependencies = [
"gltf-derive",
"serde",
"serde_derive",
"serde_json",
]
[[package]]
name = "glutin_wgl_sys"
version = "0.6.0"
@ -2795,6 +2818,42 @@ dependencies = [
"hashbrown 0.14.5",
]
[[package]]
name = "inflections"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"
[[package]]
name = "inotify"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.6.0",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "io-kit-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b"
dependencies = [
"core-foundation-sys",
"mach2",
]
[[package]]
name = "itertools"
version = "0.13.0"
@ -2804,6 +2863,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jni"
version = "0.21.1"
@ -2862,12 +2927,32 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "ktx2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lewton"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
dependencies = [
"byteorder",
"ogg",
"tinyvec",
]
[[package]]
name = "libc"
version = "0.2.169"
@ -2901,6 +2986,16 @@ dependencies = [
"redox_syscall 0.4.1",
]
[[package]]
name = "libudev-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
@ -2944,12 +3039,6 @@ dependencies = [
"libc",
]
[[package]]
name = "maflow"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "102d5acb8c2bd7b07a6e5cd3b7f73bc5cd401a96d8f78df86464afa62b962fde"
[[package]]
name = "malloc_buf"
version = "0.0.6"
@ -2998,84 +3087,6 @@ dependencies = [
"paste",
]
[[package]]
name = "mevy"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8802cdd2c9767abb83234d4b016917ab08cdb7fdae97a3a3e0a28a5f80febbd5"
dependencies = [
"mevy_core",
"mevy_ecs",
"mevy_ui",
]
[[package]]
name = "mevy_core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a388e5018afe90d85cd6e925a8c99a361e503b07aae760d70a432bdd1ab86172"
dependencies = [
"deki",
"mevy_core_syntax 0.1.1",
]
[[package]]
name = "mevy_core_syntax"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bece892cccb973e88cd8c4b686e2525a6f2a5e839e0870ac00e3d8fdd952e0e"
dependencies = [
"deki",
]
[[package]]
name = "mevy_core_syntax"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4915267a4ed798a3e9ef2fd1fff1b2cb5d1f356c5d131036e0ecddeae15ee267"
dependencies = [
"deki",
]
[[package]]
name = "mevy_ecs"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "407781ab6299ae18ebb9734a4db17ec6a865a31e196c2af926d16e552410f76f"
dependencies = [
"mevy_ecs_syntax",
]
[[package]]
name = "mevy_ecs_syntax"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be2b6d34fd01773ec549d05350d66141e8e2651f5123c41f8828306c8121f6e3"
dependencies = [
"deki",
"mevy_core_syntax 0.2.2",
]
[[package]]
name = "mevy_ui"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcea8c31c0895195aeb830b0edd650d7d0af71bec43721a9ace7723fed3b693c"
dependencies = [
"deki",
"mevy_ui_syntax",
]
[[package]]
name = "mevy_ui_syntax"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4cb9b2bb1c24ff7b13aecf3003849b6d6d3f4593b1ef321a8708ed431518d2a"
dependencies = [
"deki",
"mevy_core_syntax 0.2.2",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -3559,6 +3570,15 @@ dependencies = [
"nonmax",
]
[[package]]
name = "ogg"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
dependencies = [
"byteorder",
]
[[package]]
name = "once_cell"
version = "1.20.2"
@ -3638,6 +3658,8 @@ checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset 0.4.2",
"indexmap",
"serde",
"serde_derive",
]
[[package]]
@ -3977,6 +3999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb"
dependencies = [
"cpal",
"lewton",
"thiserror",
]
@ -3986,7 +4009,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64",
"base64 0.21.7",
"bitflags 2.6.0",
"serde",
"serde_derive",
@ -4034,6 +4057,21 @@ dependencies = [
"unicode-script",
]
[[package]]
name = "ruzstd"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
dependencies = [
"twox-hash",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
version = "1.0.6"
@ -4100,6 +4138,18 @@ dependencies = [
"syn 2.0.90",
]
[[package]]
name = "serde_json"
version = "1.0.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
@ -4539,13 +4589,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a"
[[package]]
name = "type_cell"
version = "0.3.4"
name = "twox-hash"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d985656e9b8900f54ed89cce2fccf14f6c1e079f1a519635a3ba3c4a896e1e"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
"once_cell",
"paste",
"cfg-if",
"static_assertions",
]
[[package]]
@ -4653,6 +4703,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.5"

View File

@ -1,13 +1,15 @@
[package]
name = "forestiles"
version = "0.4.0"
version = "0.1.0"
edition = "2021"
[lib]
name = "forestiles"
path = "src/lib.rs"
crate-type=[
"cdylib"
"staticlib",
"cdylib",
"rlib"
]
[[bin]]
@ -18,28 +20,45 @@ name = "forestiles"
bevy = { version = "0.15", default-features = false, features = [
"android-native-activity",
"android_shared_stdcxx",
"animation",
"bevy_asset",
"bevy_audio",
"bevy_color",
"bevy_core_pipeline",
"bevy_gilrs",
"bevy_gizmos",
"bevy_gltf",
"bevy_mesh_picking_backend",
"bevy_pbr",
"bevy_picking",
"bevy_render",
"bevy_scene",
"bevy_sprite",
"bevy_sprite_picking_backend",
"bevy_state",
"bevy_text",
"bevy_ui",
"bevy_ui_picking_backend",
"bevy_window",
"bevy_winit",
"custom_cursor",
"default_font",
"hdr",
"multi_threaded",
"png",
"smaa_luts",
"sysinfo_plugin",
"tonemapping_luts",
"vorbis",
"webgl2",
"wayland",
"png"
]}
bevy-inspector-egui = { version = "0.28", default-features = false, features = [
"bevy_pbr",
"bevy_image",
"bevy_render",
"egui_open_url"
]}
mevy = "0.1"
log = "0.4"
rand = { version = "0.8", features = ["small_rng"] }
voronoice = "0.2"
@ -66,11 +85,11 @@ android_logger = "0.14"
opt-level = 1
# Enable a large amount of optimization in the dev profile for dependencies.
# [profile.dev.package."*"]
# opt-level = 1
[profile.dev.package."*"]
opt-level = 3
[package.metadata.android]
package = "org.forestiles.game"
package = "org.forestiles.example"
apk_name = "forestiles"
strip = "strip"
# see https://github.com/rust-mobile/cargo-apk

Binary file not shown.

Before

(image error) Size: 1.5 KiB

Binary file not shown.

Before

(image error) Size: 2.4 KiB

Binary file not shown.

Before

(image error) Size: 1.6 KiB

Binary file not shown.

Before

(image error) Size: 1.4 KiB

Binary file not shown.

Before

(image error) Size: 2.7 KiB

Binary file not shown.

Before

(image error) Size: 1.7 KiB

View File

@ -1,15 +1,13 @@
use std::time::Duration;
use bevy::{input::mouse::MouseWheel, math::NormedVectorSpace, picking::{focus::HoverMap, pointer::PointerId}, prelude::*, utils::HashMap, window::PrimaryWindow};
use bevy::{math::NormedVectorSpace, picking::{focus::HoverMap, pointer::PointerId}, prelude::*, utils::HashMap, window::PrimaryWindow};
use crate::ui;
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup);
// .add_systems(Update, move_cam)
// .init_resource::<Pointers>();
app.add_systems(Startup, setup)
.add_systems(Update, move_cam)
.init_resource::<Pointers>();
}
}
@ -17,39 +15,40 @@ fn setup(mut cmds: Commands, window: Query<&Window>) {
let zoom = 2./window.single().width().min(window.single().height());
cmds.spawn((
Camera2d,
Transform::from_scale(Vec3::new(zoom, zoom, zoom))
Transform::from_scale(Vec3::new(zoom, zoom, 1.))
));
}
#[derive(Resource, Default)]
struct Pointers(HashMap<PointerId, (Vec2, Option<Duration>)>);
struct Pointers(HashMap<PointerId, Vec2>);
fn move_cam(
mut cam: Query<&mut Transform, With<Camera2d>>,
map_ui_entity: Query<Entity, With<ui::MapUIComponent>>,
mouse_buttons: Res<ButtonInput<MouseButton>>,
mut ev_scroll: EventReader<MouseWheel>,
touches: Res<Touches>,
window: Query<&Window, With<PrimaryWindow>>,
mut pointers: ResMut<Pointers>,
hover_map: Res<HoverMap>,
time: Res<Time>
hover_map: Res<HoverMap>
) {
let window = window.single();
let mut cam = cam.single_mut();
let map_ui_entity = map_ui_entity.single();
let ps = hover_map.iter().filter_map(|(id, hit_map)| match id {
PointerId::Mouse => window.cursor_position().map(|p|
match pointers.0.get(id) {
Some(p_cache) => (p_cache.1.filter(|_| mouse_buttons.pressed(MouseButton::Left)), p, p_cache.0),
None => (None, p, p)
}
),
PointerId::Touch(i) => touches.get_pressed(*i).map(|t| (pointers.0.get(id).map(|(pos, start)| (*start).unwrap_or(time.elapsed())), t.position(), t.previous_position())),
PointerId::Mouse => window.cursor_position().map(|p| (mouse_buttons.pressed(MouseButton::Left), p, pointers.0.get(id).map(|p| *p).unwrap_or(p))),
PointerId::Touch(i) => touches.get_pressed(*i).map(|t| (true, t.position(), t.previous_position())),
_ => None
}.map(|(pressed_start,new_pos, old_pos)| (pressed_start,new_pos,old_pos,id,hit_map))
}.map(|(pressed,new_pos, old_pos)| (pressed,new_pos,old_pos,id,hit_map))
).collect::<Vec<_>>();
let pressed_on_map = ps.iter().filter(|p| p.0.is_some() && p.4.contains_key(&map_ui_entity)).collect::<Vec<_>>();
let pressed_on_map = ps.iter().filter(|p| p.0 && p.4.contains_key(&map_ui_entity)).collect::<Vec<_>>();
// let mut movement = Vec2::ZERO;
// for (pressed, new_pos, old_pos, id, hit_map) in pressed_on_map.iter() {
// let delta = new_pos - old_pos;
// cam.scale += delta.dot(movement)/delta.norm();
// movement.x -= delta.x*cam.scale.x/pressed_num as f32;
// movement.y += delta.y*cam.scale.y/pressed_num as f32;
// pointers.0.insert(**id, *new_pos);
// }
let old_midpoint = pressed_on_map.iter().fold(Vec2::ZERO, |acc, (_, _, old_pos, _, _)| {
acc + (old_pos/pressed_on_map.len() as f32)
@ -57,12 +56,9 @@ fn move_cam(
let new_midpoint = pressed_on_map.iter().fold(Vec2::ZERO, |acc, (_, new_pos, _, _, _)| {
acc + (new_pos/pressed_on_map.len() as f32)
});
// move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y;
// multiple fingers zoom
if pressed_on_map.len() > 1 {
let old_d_to_midpoint = pressed_on_map.iter().fold(0., |acc, (_, _, old_pos, _, _)| {
acc + (old_midpoint-old_pos).norm()
@ -71,22 +67,12 @@ fn move_cam(
acc + (new_midpoint-new_pos).norm()
});
let zoom = new_d_to_midpoint/old_d_to_midpoint;
cam.scale /= zoom;
dbg!(zoom);
cam.scale.x /= zoom;
cam.scale.y /= zoom;
}
// mouse scroll zoom
for ev in ev_scroll.read() {
let scale = (cam.scale.x-(ev.y*0.1/window.width().min(window.height()))).clamp(0.0001, 2./window.width().min(window.height()));
cam.scale = Vec3::new(scale, scale, scale);
}
// update cached pointer positions
pointers.0.clear();
for (pressed_start, new_pos, _, id, _) in ps {
match id {
PointerId::Mouse => {pointers.0.insert(*id, (new_pos, pressed_start));},
PointerId::Touch(_) => {pointers.0.insert(*id, (new_pos, pressed_start));},
_ => {}
}
for (_, new_pos, _, id, _) in ps {
pointers.0.insert(*id, new_pos);
}
}

View File

@ -1,11 +1,9 @@
#![feature(duration_constructors)]
use bevy::{prelude::*, diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
pub mod map;
pub mod camera;
pub mod ui;
pub mod time;
#[bevy_main]
pub fn main() {
@ -16,7 +14,6 @@ pub fn main() {
camera::Plugin,
map::Plugin,
ui::Plugin,
time::Plugin,
FrameTimeDiagnosticsPlugin,
LogDiagnosticsPlugin {
filter: Some(vec![FrameTimeDiagnosticsPlugin::FPS]),

View File

@ -1,26 +1,19 @@
use std::time::Duration;
use bevy::{asset::RenderAssetUsages, picking::PickSet, prelude::*, render::mesh::{Indices, PrimitiveTopology}};
use bevy::{asset::RenderAssetUsages, prelude::*, render::mesh::{Indices, PrimitiveTopology}};
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
use rand::{thread_rng, Rng, SeedableRng};
use rand::{Rng, SeedableRng};
use voronoice::{BoundingBox, Point, VoronoiBuilder};
mod cells;
mod picking;
use picking::*;
use cells::*;
pub use cells::CellKind;
use crate::{time::GameTime, ui::CurrentAction};
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup)
.add_systems(PreUpdate, picking_backend.in_set(PickSet::Backend))
.add_systems(Update, (update_map_mesh, cells_regeneration, expand))
.insert_resource(Time::<Fixed>::from_seconds(0.25)) // Time for a day
.add_systems(FixedUpdate, update_cells)
.insert_resource(ClearColor(Color::srgb(0., 0., 1.)))
.insert_resource(Seed(thread_rng().gen()));
.insert_resource(Seed(0));
}
}
@ -35,7 +28,7 @@ pub const SIZE: usize = 10000;
struct Seed(u32);
#[derive(Component)]
pub struct Voronoi (voronoice::Voronoi);
struct Voronoi (voronoice::Voronoi);
#[derive(Component)]
pub struct MapMarker;
@ -43,12 +36,6 @@ pub struct MapMarker;
#[derive(Component)]
struct MapColors (Vec<[f32; 4]>);
#[derive(Component)]
pub struct CellsEntities (Vec<Entity>);
#[derive(Component)]
pub struct MeshNeedsUpdate(bool);
fn setup(
mut cmds: Commands,
mut meshes: ResMut<Assets<Mesh>>,
@ -66,7 +53,7 @@ fn setup(
.set_lloyd_relaxation_iterations(3)
.build()
.unwrap();
let mut cells = Vec::with_capacity(SIZE);
let mut cells_data = Vec::with_capacity(SIZE);
let z_noise = Fbm::<Perlin>::new(seed.0);
let moisture_noise = Fbm::<Perlin>::new(seed.0+1)
.set_frequency(2.);
@ -86,27 +73,31 @@ fn setup(
} else if z <= 0.52 {
CellKind::Beach
} else if z < 0.8 {
CellKind::Dirt
CellKind::Grass
} else {
CellKind::Stone
};
cells.push(Cell {
kind: k,
voronoi_id: i,
altitude: (z*255.) as u8,
vertices: vec![]
});
cells_data.push(CellData::new(k, i, (z*255.) as u8, (m*255.) as u8, 0, vec![]));
}
let mut poss = Vec::new();
let mut colors = Vec::new();
let mut indices = Vec::new();
for (c, cd) in voronoi.iter_cells().zip(cells.iter_mut()).filter(|(_,cd)| cd.kind != CellKind::Forest) {
for (c, cd) in voronoi.iter_cells().zip(cells_data.iter_mut()).filter(|(_,cd)| cd.kind != CellKind::Forest) {
let color = cd.color();
// if c.site() == selected_tile {
// color[0] = (color[0]+0.4).clamp(0., 1.);
// color[1] = (color[1]+0.4).clamp(0., 1.);
// color[2] = (color[2]+0.4).clamp(0., 1.);
// }
let vs = c.iter_vertices().collect::<Vec<_>>();
let i = poss.len();
for v in vs.iter() {
poss.push(Vec3::new(v.x as f32, v.y as f32, 0.));
poss.push(Vec3::new(v.x as f32, v.y as f32, 0.));// [v.x as f32, v.y as f32, 0.]);
// poss.push(Vertex::new_col([v.x as f32, v.y as f32], color, 1));
colors.push(color);
}
for v in 1..(vs.len()-1) {
indices.extend_from_slice(&[i as u32, (i+v) as u32, (i+v+1) as u32]);
@ -114,7 +105,6 @@ fn setup(
}
}
let colors = vec![[0.; 4]; poss.len()];
let mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default())
// Add 4 vertices, each with its own position attribute (coordinate in
// 3D space), for each of the corners of the parallelogram.
@ -128,91 +118,49 @@ fn setup(
)
.with_inserted_indices(Indices::U32(indices));
let mut cells_entities = Vec::with_capacity(cells.len());
cmds.spawn((
Mesh2d(meshes.add(mesh)),
MeshMaterial2d(materials.add(ColorMaterial::default())),
Transform::default(),
Voronoi(voronoi),
MapColors(colors),
MeshNeedsUpdate(true),
MapMarker
)).with_children(|parent| {
for cell in cells {
let kind = cell.kind;
let mut cmd = parent.spawn(cell);
match kind {
CellKind::Grass | CellKind::Forest => {
cmd.insert((Wealth(0), Regeneration {
last_update: Duration::ZERO,
full_growth_duration: kind.regen_full_growth_duration()
}));
},
_ => {}
for cd in cells_data {
match cd.kind {
CellKind::Forest | CellKind::Grass => parent.spawn((cd, LastUpdate(0))),
_ => parent.spawn(cd)
};
}
cmd.observe(|
trigger: Trigger<Pointer<Click>>,
mut cells: Query<&mut Cell>,
mut map_needs_update: Query<&mut MeshNeedsUpdate, With<MapMarker>>,
mut cmds: Commands,
ca: Res<CurrentAction>,
gt: Res<GameTime>,
| {
if trigger.duration > Duration::from_millis(200) {
return
}
match *ca {
CurrentAction::ChangeCell(ck) => {
let mut cell = cells.get_mut(trigger.target).unwrap();
match ck {
CellKind::Forest => match cell.kind {
CellKind::Dirt | CellKind::Grass => {
cmds.entity(trigger.target).insert((Wealth(0), Regeneration {
last_update: gt.current,
full_growth_duration: CellKind::Forest.regen_full_growth_duration()
}));
cell.kind = CellKind::Forest;
map_needs_update.single_mut().0 = true;
},
_ => {}
},
CellKind::Grass => match cell.kind {
CellKind::Dirt => {
cmds.entity(trigger.target).insert((Wealth(0), Regeneration {
last_update: gt.current,
full_growth_duration: CellKind::Grass.regen_full_growth_duration()
}));
cell.kind = CellKind::Grass;
map_needs_update.single_mut().0 = true;
},
_ => {}
}
_ => {}
}
}
_ => {}
}
});
cells_entities.push(cmd.id());
}
}).insert(CellsEntities(cells_entities));
}
fn update_map_mesh(
cells: Query<(&Cell, Option<&Wealth>)>,
mut map: Query<(&Mesh2d, &mut MapColors, &mut MeshNeedsUpdate), With<MapMarker>>,
#[derive(Component)]
pub struct LastUpdate(usize);
fn update_cells(
mut cells: Query<(&mut CellData, &mut LastUpdate)>,
mut map: Query<(&Mesh2d, &mut MapColors), With<MapMarker>>,
mut meshes: ResMut<Assets<Mesh>>
) {
let (mesh, mut cols, mut needs_update) = map.single_mut();
if needs_update.0 {
let (mesh, mut cols) = map.single_mut();
if let Some(mesh) = meshes.get_mut(mesh) {
// let cols = mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR).unwrap();
let mut modified = false;
for (cell, wealth) in cells.iter() {
let col = cell.color(wealth.map(|w| w.0).unwrap_or_default());
for id in cell.vertices.iter() {
modified = modified || cols.0[*id] != col;
for (mut cd, mut lu) in cells.iter_mut() {
lu.0 += 1;
if lu.0 > match cd.kind {
CellKind::Void | CellKind::Sea | CellKind::Beach | CellKind::Dirt | CellKind::Stone => usize::MAX,
CellKind::Forest => 100*365/4, // Let's say that a forest takes 100 years to mature
CellKind::Grass => 7*7/4 // Let's say that grass takes 7 weaks to reach its max
} {
lu.0 = 0;
cd.resource = (cd.resource + 1).clamp(0, 4);
modified = true;
}
// cd.update();
let col = cd.color();
for id in cd.vertices.iter() {
cols.0[*id] = col.clone();
}
}
@ -220,6 +168,4 @@ fn update_map_mesh(
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, cols.0.clone());
}
}
needs_update.0 = false;
}
}

View File

@ -1,14 +1,8 @@
use std::time::Duration;
use bevy::prelude::*;
use rand::{seq::IteratorRandom, thread_rng, Rng};
use crate::time::GameTime;
use super::{CellsEntities, MapMarker, MeshNeedsUpdate, Voronoi};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CellKind {
Void,
Sea,
Beach,
Forest,
@ -16,112 +10,36 @@ pub enum CellKind {
Stone,
Grass
}
impl CellKind {
pub fn regen_full_growth_duration(&self) -> Duration {
match self {
CellKind::Sea | CellKind::Beach | CellKind::Dirt | CellKind::Stone => unreachable!(),
CellKind::Forest => Duration::from_days(365*100), // Let's say that a forest takes 100 years to mature
CellKind::Grass => Duration::from_weeks(7) // Let's say that grass takes 7 weeks to reach its max
}
}
}
#[derive(Debug, Component)]
pub struct Cell {
pub struct CellData {
pub kind: CellKind,
pub voronoi_id: usize,
pub altitude: u8,
pub cid: usize,
z: u8,
pub moisture: u8,
pub resource: u8, // How much resource there is (between 0 and 4)
pub vertices: Vec<usize>
}
impl Cell {
pub fn color(&self, wealth: u8) -> [f32; 4] {
impl CellData {
pub fn new(kind: CellKind, cell: usize, z: u8, moisture: u8, resource: u8, vertices: Vec<usize>) -> Self {
Self {
kind,
cid: cell,
z,
moisture,
resource,
vertices
}
}
pub fn color(&self) -> [f32; 4] {
match self.kind {
CellKind::Void => [0.; 4],
CellKind::Sea => [0., 0., 1., 1.],
CellKind::Beach => [0.82, 0.84, 0.51, 1.],
CellKind::Forest => [0., 0.5 - (wealth as f32/255.*0.4), 0., 1.],
CellKind::Dirt => [0.53 - (wealth as f32/255.*0.4), 0.38-(wealth as f32/255.*0.4), 0.29-(wealth as f32/255.*0.4), 1.],
CellKind::Forest => [0., 0.5 - (self.resource as f32/4.*0.4), 0., 1.],
CellKind::Dirt => [0.53 - (self.resource as f32/4.*0.4), 0.38-(self.resource as f32/4.*0.4), 0.29-(self.resource as f32/4.*0.4), 1.],
CellKind::Stone => [0.5, 0.5, 0.5, 1.],
CellKind::Grass => [(136./255.) - (wealth as f32/255.*0.15), (154./255.) + (wealth as f32/255.*0.1), (59./255.) - (wealth as f32/255.*0.15), 1.]
}
}
}
#[derive(Component)]
pub struct Wealth(pub u8);
impl Default for Wealth {
fn default() -> Self {
Wealth(u8::MAX)
}
}
#[derive(Component)]
#[require(Wealth)]
pub struct Regeneration {
pub last_update: Duration,
pub full_growth_duration: Duration
}
pub fn cells_regeneration(
mut cells: Query<(&mut Regeneration, &mut Wealth)>,
mut map_needs_update: Query<&mut MeshNeedsUpdate, With<MapMarker>>,
gt: Res<GameTime>
) {
let mut map_needs_update = map_needs_update.single_mut();
for (mut regen, mut wealth) in cells.iter_mut() {
if gt.current - regen.last_update > regen.full_growth_duration/u8::MAX as u32 {
regen.last_update = gt.current;
wealth.0 = wealth.0.saturating_add(1);
map_needs_update.0 = true;
}
}
}
pub fn expand(
mut cells: Query<(&mut Cell, Option<&Wealth>)>,
map: Query<(&Voronoi, &CellsEntities)>,
mut cmds: Commands,
t: Res<Time>,
gt: Res<GameTime>
) {
let (voronoi, cells_entities) = map.single();
let mut random = thread_rng();
let mut changes = Vec::new();
for (cell, wealth) in cells.iter() {
// TODO: search beter numbers, for now they are arbitrary
if cell.kind == CellKind::Forest || cell.kind == CellKind::Grass {
let wealth = if cell.kind == CellKind::Forest {
1.
} else {
wealth.unwrap().0 as f64/255.
};
if random.gen_bool((t.elapsed_secs_f64()*(gt.speed as f64)*wealth/(60.*60.*24.*30.)).min(1.)) { // Let say that grass takes 1 months to expand
let target = voronoi.0.cell(cell.voronoi_id).iter_neighbors().choose(&mut random).unwrap();
changes.push((target, CellKind::Grass));
}
}
if cell.kind == CellKind::Forest {
if random.gen_bool((t.elapsed_secs_f64()*(gt.speed as f64)*(wealth.unwrap().0 as f64/255.).sqrt()/(60.*60.*24.*365.*5.)).min(1.)) { // Let say that forest takes 5 years to expand
let target = voronoi.0.cell(cell.voronoi_id).iter_neighbors().choose(&mut random).unwrap();
changes.push((target, CellKind::Forest));
}
}
}
for (v_id, kind) in changes {
let target = cells_entities.0[v_id];
let (mut cell, _) = cells.get_mut(target).unwrap();
if kind == CellKind::Forest && (cell.kind == CellKind::Dirt || cell.kind == CellKind::Grass) {
cell.kind = CellKind::Forest;
cmds.entity(target).insert((Wealth(0), Regeneration {
full_growth_duration: CellKind::Forest.regen_full_growth_duration(),
last_update: gt.current
}));
} else if kind == CellKind::Grass && cell.kind == CellKind::Dirt {
cell.kind = CellKind::Grass;
cmds.entity(target).insert((Wealth(0), Regeneration {
full_growth_duration: CellKind::Grass.regen_full_growth_duration(),
last_update: gt.current
}));
CellKind::Grass => [(136./255.) - (self.resource as f32/4.*0.4), (204./255.) - (self.resource as f32/4.*0.4), (59./255.) - (self.resource as f32/4.*0.4), 1.]
}
}
}

View File

@ -1,39 +0,0 @@
use bevy::{picking::{backend::{HitData, PointerHits}, pointer::{PointerId, PointerLocation}}, prelude::*, window::PrimaryWindow};
use voronoice::Point;
use super::{CellsEntities, MapMarker, Voronoi};
pub fn picking_backend(
cam: Query<(&Transform, Entity), With<Camera2d>>,
window: Query<&Window, With<PrimaryWindow>>,
pointers: Query<(&PointerId, &PointerLocation)>,
map: Query<(&Voronoi, &CellsEntities, &Transform), With<MapMarker>>,
mut output: EventWriter<PointerHits>
) {
let (cam, cam_id) = cam.single();
let window = window.single();
let (voronoi, cells_entities, map_pos) = map.single();
let mut last_cell = 0;
for (id, l) in pointers.iter() {
if let Some(mut pos) = l.location().map(|l| l.position) {
pos -= window.size()/2.;
pos *= cam.scale.xy();
pos.x += cam.translation.x;
pos.y -= cam.translation.y;
if let Some(c) = voronoi.0.cell(last_cell).iter_path(Point { x: pos.x as f64, y: -pos.y as f64 }).last() {
last_cell = c;
output.send(PointerHits {
pointer: *id,
picks: vec![(cells_entities.0[c], HitData {
camera: cam_id,
depth: map_pos.translation.z,
position: Some(Vec3 { x: pos.x, y: pos.y, z: map_pos.translation.z }),
normal: None
})],
order: map_pos.translation.z
});
}
}
}
}

View File

@ -1,28 +0,0 @@
use std::time::Duration;
use bevy::prelude::*;
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.insert_resource(GameTime {
current: Duration::ZERO,
speed: 24. * 60. * 60. * 10.
})
.add_systems(PreUpdate, update_time);
}
}
#[derive(Resource)]
pub struct GameTime {
pub current: Duration,
pub speed: f32 // = game time / real time
}
fn update_time(
mut gt: ResMut<GameTime>,
time: Res<Time>
) {
let speed = gt.speed;
gt.current += Duration::from_secs_f32(time.delta_secs() * speed);
}

171
src/ui.rs
View File

@ -1,172 +1,27 @@
use mevy::*;
use bevy::{asset::embedded_asset, input::mouse::MouseWheel, math::{NormedVectorSpace, VectorSpace}, picking::{focus::HoverMap, pointer::PointerId}, prelude::*, utils::{dbg, HashMap}, window::PrimaryWindow};
use crate::map::{self, CellKind, MapMarker};
// #77767b
const TABBAR_COLOR: Color = Color::srgb(119./255., 118./255., 123./255.);
// #E8E8E8
const ENABLED_BUTTON_COLOR: Color = Color::srgb(232./255., 232./255., 232./255.);
use bevy::prelude::*;
pub struct Plugin;
impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.init_resource::<CurrentAction>()
.add_systems(Startup, setup)
.add_systems(Update, zoom_with_scroll);
embedded_asset!(app, "../assets/ui/enabled_tree.png");
embedded_asset!(app, "../assets/ui/disabled_tree.png");
embedded_asset!(app, "../assets/ui/enabled_grass.png");
embedded_asset!(app, "../assets/ui/disabled_grass.png");
embedded_asset!(app, "../assets/ui/enabled_cross.png");
embedded_asset!(app, "../assets/ui/disabled_cross.png");
app.add_systems(Startup, setup);
}
}
#[derive(Resource, Default, PartialEq, Eq)]
pub enum CurrentAction {
#[default]
None,
ChangeCell(CellKind)
}
#[derive(Component, Debug)]
struct PointersDragging(HashMap<PointerId, Vec2>);
#[derive(Component)]
pub struct MapUIComponent;
fn setup(
mut world: Commands,
asset_server: Res<AssetServer>
mut cmds: Commands
) {
cmds.spawn((
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
MapUIComponent
));
// Spawn all ui elements as children of this one
spawn!{
Node {width: 100%, height: 100%, display: Display::Flex, flex_direction: FlexDirection::Column, !};
PickingBehavior {
should_block_lower: false,
is_hoverable: true
};
.observe(|trigger: Trigger<Pointer<DragEnd>>, mut ptrs: Query<&mut PointersDragging>| {
if trigger.button == PointerButton::Primary {
ptrs.single_mut().0.remove(&trigger.pointer_id);
}
});
.observe(|
trigger: Trigger<Pointer<Drag>>,
mut ptrs: Query<&mut PointersDragging>,
mut cam: Query<&mut Transform, With<Camera2d>>,
| {
if trigger.button == PointerButton::Primary {
let mut ptrs = ptrs.single_mut();
if !ptrs.0.contains_key(&trigger.pointer_id) {
return
}
let mut cam = cam.single_mut();
let old_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let old_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (old_midpoint-pos).norm());
ptrs.0.insert(trigger.pointer_id, trigger.pointer_location.position);
let new_midpoint = ptrs.0.values().fold(Vec2::ZERO, |acc, pos| acc + (pos/ptrs.0.len() as f32));
let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm());
// move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y;
if ptrs.0.len() > 1 {
cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
}
}
}
);
[map][
Node{
flex_grow: 1.,
!};
PointersDragging(HashMap::new());
MapUIComponent;
PickingBehavior {
should_block_lower: false,
is_hoverable: true
};
.observe(|trigger: Trigger<Pointer<DragStart>>, mut ptrs: Query<&mut PointersDragging>| {
if trigger.button == PointerButton::Primary {
if let Ok(mut ptrs) = ptrs.get_mut(trigger.target) {
ptrs.0.insert(trigger.pointer_id, trigger.pointer_location.position);
}
}
});
]
[
Node{
width: 100%,
height: 10vh,
align_self: AlignSelf::FlexEnd,
!};
Button;
BackgroundColor(TABBAR_COLOR);
[forest][
ImageNode::new(asset_server.load("embedded://forestiles/../assets/ui/enabled_tree.png"));
Node {
// height: 80%,
// margin: [>1vh],
!};
BackgroundColor(TABBAR_COLOR);
.observe(move |trigger: Trigger<Pointer<Click>>, mut ca: ResMut<CurrentAction>, mut bg: Query<&mut BackgroundColor>| {
if trigger.button == PointerButton::Primary {
if *ca == CurrentAction::ChangeCell(CellKind::Forest) {
*ca = CurrentAction::None;
bg.get_mut(forest).unwrap().0 = TABBAR_COLOR;
bg.get_mut(grass).unwrap().0 = TABBAR_COLOR;
} else {
*ca = CurrentAction::ChangeCell(CellKind::Forest);
bg.get_mut(forest).unwrap().0 = ENABLED_BUTTON_COLOR;
bg.get_mut(grass).unwrap().0 = TABBAR_COLOR;
}
}
});
]
[grass][
ImageNode::new(asset_server.load("embedded://forestiles/../assets/ui/enabled_grass.png"));
Node {
// height: 80%,
// margin: [>1vh],
!};
BackgroundColor(TABBAR_COLOR);
.observe(move |trigger: Trigger<Pointer<Click>>, mut ca: ResMut<CurrentAction>, mut bg: Query<&mut BackgroundColor>| {
if trigger.button == PointerButton::Primary {
if *ca == CurrentAction::ChangeCell(CellKind::Grass) {
*ca = CurrentAction::None;
bg.get_mut(forest).unwrap().0 = TABBAR_COLOR;
bg.get_mut(grass).unwrap().0 = TABBAR_COLOR;
} else {
*ca = CurrentAction::ChangeCell(CellKind::Grass);
bg.get_mut(forest).unwrap().0 = TABBAR_COLOR;
bg.get_mut(grass).unwrap().0 = ENABLED_BUTTON_COLOR;
}
}
});
]
]
}
}
fn zoom_with_scroll(
mut cam: Query<&mut Transform, With<Camera2d>>,
mut ev_scroll: EventReader<MouseWheel>,
hover_map: Res<HoverMap>,
window: Query<&Window, With<PrimaryWindow>>,
map_ui_id: Query<Entity, With<MapUIComponent>>
) {
let map_ui_id = map_ui_id.single();
if hover_map.get(&PointerId::Mouse).and_then(|hovered_ids| hovered_ids.get(&map_ui_id)).is_some() {
let window = window.single();
let mut cam = cam.single_mut();
for ev in ev_scroll.read() {
let scale = (cam.scale.x-(ev.y*0.1/window.width().min(window.height()))).clamp(0.0001, 2./window.width().min(window.height()));
cam.scale = Vec3::new(scale, scale, scale);
}
}
}