Compare commits
7 Commits
main
...
falling-sa
Author | SHA1 | Date |
---|---|---|
Savanni D'Gerinel | 1f2611dda4 | |
Savanni D'Gerinel | d62454545f | |
Savanni D'Gerinel | 7364b81d10 | |
Savanni D'Gerinel | 1a7776b335 | |
Savanni D'Gerinel | 2323443378 | |
Savanni D'Gerinel | c27ce7fe80 | |
Savanni D'Gerinel | b414f3e0ea |
|
@ -120,6 +120,17 @@ version = "1.0.75"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener 2.5.3",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "2.1.1"
|
||||
|
@ -133,6 +144,126 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c"
|
||||
dependencies = [
|
||||
"async-lock 3.3.0",
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand 2.0.1",
|
||||
"futures-lite 2.2.0",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-global-executor"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
|
||||
dependencies = [
|
||||
"async-channel 2.1.1",
|
||||
"async-executor",
|
||||
"async-io 2.3.1",
|
||||
"async-lock 3.3.0",
|
||||
"blocking",
|
||||
"futures-lite 2.2.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
|
||||
dependencies = [
|
||||
"async-lock 2.8.0",
|
||||
"autocfg 1.1.0",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-lite 1.13.0",
|
||||
"log 0.4.20",
|
||||
"parking",
|
||||
"polling 2.8.0",
|
||||
"rustix 0.37.27",
|
||||
"slab",
|
||||
"socket2 0.4.10",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65"
|
||||
dependencies = [
|
||||
"async-lock 3.3.0",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-io",
|
||||
"futures-lite 2.2.0",
|
||||
"parking",
|
||||
"polling 3.3.2",
|
||||
"rustix 0.38.28",
|
||||
"slab",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
|
||||
dependencies = [
|
||||
"event-listener 2.5.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b"
|
||||
dependencies = [
|
||||
"event-listener 4.0.1",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-std"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
|
||||
dependencies = [
|
||||
"async-channel 1.9.0",
|
||||
"async-global-executor",
|
||||
"async-io 1.13.0",
|
||||
"async-lock 2.8.0",
|
||||
"crossbeam-utils",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-lite 1.13.0",
|
||||
"gloo-timers",
|
||||
"kv-log-macro",
|
||||
"log 0.4.20",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "2.0.0"
|
||||
|
@ -142,6 +273,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "atomic-write-file"
|
||||
version = "0.1.2"
|
||||
|
@ -264,6 +401,22 @@ dependencies = [
|
|||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118"
|
||||
dependencies = [
|
||||
"async-channel 2.1.1",
|
||||
"async-lock 3.3.0",
|
||||
"async-task",
|
||||
"fastrand 2.0.1",
|
||||
"futures-io",
|
||||
"futures-lite 2.2.0",
|
||||
"piper",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_html"
|
||||
version = "2.4.0"
|
||||
|
@ -861,6 +1014,31 @@ dependencies = [
|
|||
"zune-inflate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "falling-sand"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-channel 2.1.1",
|
||||
"async-std",
|
||||
"cairo-rs",
|
||||
"cool_asserts",
|
||||
"gio",
|
||||
"glib",
|
||||
"glib-build-tools 0.17.10",
|
||||
"gtk4",
|
||||
"libadwaita",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.1"
|
||||
|
@ -927,7 +1105,7 @@ checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
|
|||
name = "fitnesstrax"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-channel 2.1.1",
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"dimensioned 0.8.0",
|
||||
|
@ -1124,6 +1302,34 @@ version = "0.3.29"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
||||
dependencies = [
|
||||
"fastrand 1.9.0",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"memchr",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba"
|
||||
dependencies = [
|
||||
"fastrand 2.0.1",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.29"
|
||||
|
@ -1380,6 +1586,18 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gloo-timers"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gm-control-panel"
|
||||
version = "0.1.0"
|
||||
|
@ -1751,7 +1969,7 @@ dependencies = [
|
|||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.5.5",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -1878,6 +2096,15 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl-memoizer"
|
||||
version = "0.5.1"
|
||||
|
@ -1897,6 +2124,17 @@ dependencies = [
|
|||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.9.0"
|
||||
|
@ -1926,7 +2164,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"rustix 0.38.28",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -2005,6 +2243,15 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kv-log-macro"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
|
||||
dependencies = [
|
||||
"log 0.4.20",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "language-tags"
|
||||
version = "0.2.2"
|
||||
|
@ -2081,6 +2328,12 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.12"
|
||||
|
@ -2111,6 +2364,9 @@ name = "log"
|
|||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
dependencies = [
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "logger"
|
||||
|
@ -2663,6 +2919,17 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "piper"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"fastrand 2.0.1",
|
||||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.7.5"
|
||||
|
@ -2724,6 +2991,36 @@ dependencies = [
|
|||
"miniz_oxide 0.7.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"libc",
|
||||
"log 0.4.20",
|
||||
"pin-project-lite",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"pin-project-lite",
|
||||
"rustix 0.38.28",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
|
@ -3173,6 +3470,20 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.8",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.28"
|
||||
|
@ -3182,7 +3493,7 @@ dependencies = [
|
|||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.4.12",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -3442,6 +3753,16 @@ version = "1.11.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.5"
|
||||
|
@ -3786,9 +4107,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"fastrand 2.0.1",
|
||||
"redox_syscall",
|
||||
"rustix",
|
||||
"rustix 0.38.28",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -3929,7 +4250,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"socket2 0.5.5",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
@ -4315,6 +4636,12 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
|
@ -4360,6 +4687,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
|
|
28
Cargo.nix
28
Cargo.nix
|
@ -115,6 +115,16 @@ rec {
|
|||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"falling-sand" = rec {
|
||||
packageId = "falling-sand";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
packageId = "falling-sand";
|
||||
};
|
||||
|
||||
# Debug support which might change between releases.
|
||||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"file-service" = rec {
|
||||
packageId = "file-service";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
|
@ -2754,6 +2764,24 @@ rec {
|
|||
}
|
||||
];
|
||||
|
||||
};
|
||||
"falling-sand" = rec {
|
||||
crateName = "falling-sand";
|
||||
version = "0.1.0";
|
||||
edition = "2021";
|
||||
crateBin = [
|
||||
{
|
||||
name = "falling-sand";
|
||||
path = "src/main.rs";
|
||||
requiredFeatures = [ ];
|
||||
}
|
||||
];
|
||||
# We can't filter paths with references in Nix 2.4
|
||||
# See https://github.com/NixOS/nix/issues/5410
|
||||
src = if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion ))
|
||||
then lib.cleanSourceWith { filter = sourceFilter; src = ./falling-sand; }
|
||||
else ./falling-sand;
|
||||
|
||||
};
|
||||
"fastrand" = rec {
|
||||
crateName = "fastrand";
|
||||
|
|
|
@ -9,6 +9,7 @@ members = [
|
|||
"cyberpunk-splash",
|
||||
"dashboard",
|
||||
"emseries",
|
||||
"falling-sand",
|
||||
"file-service",
|
||||
"fitnesstrax/core",
|
||||
"fitnesstrax/app",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "falling-sand"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
adw = { version = "0.5", package = "libadwaita", features = [ "v1_4" ] }
|
||||
async-std = { version = "1" }
|
||||
async-channel = { version = "2" }
|
||||
cairo-rs = { version = "0.18" }
|
||||
gio = { version = "0.18" }
|
||||
glib = { version = "0.18" }
|
||||
gtk = { version = "0.7", package = "gtk4", features = [ "v4_10" ] }
|
||||
tokio = { version = "1", features = [ "full" ] }
|
||||
|
||||
[dev-dependencies]
|
||||
cool_asserts = "*"
|
||||
|
||||
[build-dependencies]
|
||||
glib-build-tools = "0.17"
|
|
@ -0,0 +1,222 @@
|
|||
use async_channel::Sender;
|
||||
use async_std::task;
|
||||
use glib::Object;
|
||||
use gtk::{prelude::*, subclass::prelude::*};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
/*
|
||||
mod sand_area;
|
||||
use sand_area::{SandArea, CELL_SIZE, HEIGHT, WIDTH};
|
||||
*/
|
||||
|
||||
mod profile;
|
||||
use profile::profile;
|
||||
|
||||
mod physics;
|
||||
use physics::World;
|
||||
|
||||
pub const WIDTH: usize = 601;
|
||||
pub const HEIGHT: usize = 601;
|
||||
pub const CELL_SIZE: usize = 1;
|
||||
const FPS: u64 = 60;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SandViewPrivate {
|
||||
rendering: RefCell<bool>,
|
||||
last_update: RefCell<std::time::Instant>,
|
||||
// area: RefCell<SandArea>,
|
||||
}
|
||||
|
||||
impl Default for SandViewPrivate {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rendering: RefCell::new(false),
|
||||
last_update: RefCell::new(std::time::Instant::now()),
|
||||
// area: RefCell::new(SandArea::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for SandViewPrivate {
|
||||
const NAME: &'static str = "SandView";
|
||||
type Type = SandView;
|
||||
type ParentType = gtk::DrawingArea;
|
||||
}
|
||||
|
||||
impl ObjectImpl for SandViewPrivate {}
|
||||
impl WidgetImpl for SandViewPrivate {}
|
||||
impl DrawingAreaImpl for SandViewPrivate {}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct SandView(ObjectSubclass<SandViewPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
||||
}
|
||||
|
||||
impl Default for SandView {
|
||||
fn default() -> Self {
|
||||
let s: Self = Object::builder().build();
|
||||
s.set_width_request(WIDTH as i32);
|
||||
s.set_height_request(HEIGHT as i32);
|
||||
|
||||
s.set_draw_func({
|
||||
let s = s.clone();
|
||||
move |_, context, width, height| {
|
||||
profile("redraw", || {
|
||||
context.set_source_rgb(0., 0., 0.);
|
||||
let _ = context.paint();
|
||||
context.set_source_rgb(0.1, 0.1, 0.1);
|
||||
/*
|
||||
for x in (0..width).step_by(CELL_SIZE) {
|
||||
context.move_to(x as f64, 0.);
|
||||
context.line_to(x as f64, HEIGHT as f64);
|
||||
}
|
||||
for y in (0..height).step_by(CELL_SIZE) {
|
||||
context.move_to(0., y as f64);
|
||||
context.line_to(WIDTH as f64, y as f64);
|
||||
}
|
||||
let _ = context.stroke();
|
||||
*/
|
||||
/*
|
||||
let area = s.imp().area.borrow();
|
||||
for x in 0..area.width {
|
||||
for y in 0..area.height {
|
||||
if area.grain(x, y) {
|
||||
context.set_source_rgb(0.8, 0.8, 0.8);
|
||||
} else {
|
||||
context.set_source_rgb(0., 0., 0.);
|
||||
}
|
||||
context.rectangle(
|
||||
(x * CELL_SIZE) as f64,
|
||||
(y * CELL_SIZE) as f64,
|
||||
(CELL_SIZE) as f64,
|
||||
(CELL_SIZE) as f64,
|
||||
);
|
||||
}
|
||||
}
|
||||
let _ = context.fill();
|
||||
*/
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl SandView {
|
||||
/*
|
||||
fn set_area(&self, area: SandArea) {
|
||||
*self.imp().area.borrow_mut() = area;
|
||||
self.queue_draw();
|
||||
}
|
||||
*/
|
||||
|
||||
fn set_last_update(&self, now: std::time::Instant) {
|
||||
*self.imp().last_update.borrow_mut() = now;
|
||||
}
|
||||
|
||||
fn last_update(&self) -> std::time::Instant {
|
||||
self.imp().last_update.borrow().clone()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
async fn animate(sender: Sender<SandArea>) {
|
||||
let mut sand_area = SandArea::default();
|
||||
sand_area.add_grain(20, 20);
|
||||
loop {
|
||||
std::thread::sleep(Duration::from_millis(1000 / FPS));
|
||||
sand_area = profile("next", || sand_area.next());
|
||||
sender.send(sand_area.clone()).await;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
async fn run_physics(world: World) {
|
||||
let mut last_update = std::time::Instant::now();
|
||||
let physics_tickspeed = std::time::Duration::from_millis(1000 / 60);
|
||||
loop {
|
||||
let now = std::time::Instant::now();
|
||||
|
||||
profile("world next", || world.next(now - last_update));
|
||||
last_update = wait_for_update(last_update, physics_tickspeed).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_update(
|
||||
last_update: std::time::Instant,
|
||||
tickspeed: std::time::Duration,
|
||||
) -> std::time::Instant {
|
||||
let now = std::time::Instant::now();
|
||||
let next_update = last_update + tickspeed;
|
||||
task::sleep(next_update - now).await;
|
||||
std::time::Instant::now()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let app = gtk::Application::builder()
|
||||
.application_id("com.luminescent-dreams.falling-sand")
|
||||
.build();
|
||||
|
||||
// let (sender, receiver) = async_channel::bounded(5);
|
||||
|
||||
let world = World::default();
|
||||
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let physics_thread = runtime.spawn(run_physics(world.clone()));
|
||||
/*
|
||||
let background_thread = runtime.spawn(animate(sender));
|
||||
*/
|
||||
|
||||
/*
|
||||
let sand_area = Arc::new(RwLock::new(SandArea::default()));
|
||||
*/
|
||||
|
||||
app.connect_activate(move |app| {
|
||||
let window = gtk::ApplicationWindow::new(app);
|
||||
window.present();
|
||||
|
||||
let view = SandView::default();
|
||||
window.set_child(Some(&view));
|
||||
|
||||
glib::spawn_future_local({
|
||||
let view = view.clone();
|
||||
view.set_last_update(std::time::Instant::now());
|
||||
let fps_delay = std::time::Duration::from_millis(1000 / FPS);
|
||||
// let sand_area = sand_area.clone();
|
||||
println!("FPS delay: {:?}", fps_delay);
|
||||
|
||||
async move {
|
||||
loop {
|
||||
/*
|
||||
profile("setting area", || {
|
||||
view.set_area(sand_area.read().unwrap().clone())
|
||||
});
|
||||
*/
|
||||
|
||||
// Now, determine how much time remains before the next update. This can vary frame by frame, based on how much rendering has to be done.
|
||||
let now = std::time::Instant::now();
|
||||
let mut wait_time = (view.last_update() + fps_delay) - now;
|
||||
if wait_time < std::time::Duration::from_millis(0) {
|
||||
wait_time = fps_delay;
|
||||
}
|
||||
view.set_last_update(now);
|
||||
async_std::task::sleep(wait_time).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.run();
|
||||
|
||||
// let _ = runtime.block_on(background_thread);
|
||||
let _ = runtime.block_on(physics_thread);
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
use crate::profile;
|
||||
use std::{
|
||||
ops::{Mul, Neg, Sub},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
const GRAVITY: f64 = 1.;
|
||||
|
||||
fn within(val1: f64, val2: f64, tolerance: f64) -> bool {
|
||||
(val1 - val2).abs() <= tolerance
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct Point {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn distance_sq(&self, other: &Point) -> f64 {
|
||||
let xdist = other.x - self.x;
|
||||
let ydist = other.y - self.y;
|
||||
|
||||
xdist * xdist + ydist * ydist
|
||||
}
|
||||
|
||||
fn eq(&self, other: &Point, tolerance: f64) -> bool {
|
||||
within(self.x, other.x, tolerance) && within(self.y, other.y, tolerance)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct Vector {
|
||||
dx: f64,
|
||||
dy: f64,
|
||||
}
|
||||
|
||||
impl Sub for Vector {
|
||||
type Output = Vector;
|
||||
fn sub(self, rhs: Vector) -> Self::Output {
|
||||
Self {
|
||||
dx: rhs.dx - self.dx,
|
||||
dy: rhs.dy - self.dy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Vector {
|
||||
type Output = Vector;
|
||||
fn neg(self) -> Self {
|
||||
Self {
|
||||
dx: -self.dx,
|
||||
dy: -self.dy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f64> for Vector {
|
||||
type Output = Vector;
|
||||
fn mul(self, rhs: f64) -> Self {
|
||||
Self {
|
||||
dx: self.dx * rhs,
|
||||
dy: self.dy * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct Grain {
|
||||
radius: f64,
|
||||
location: Point,
|
||||
velocity: Vector,
|
||||
}
|
||||
|
||||
impl Grain {
|
||||
fn translate(&mut self, vec: Vector) {
|
||||
self.location.x = self.location.x + vec.dx;
|
||||
self.location.y = self.location.y + vec.dy;
|
||||
}
|
||||
|
||||
fn move_by(&mut self, delta_t: std::time::Duration) {
|
||||
self.location.x = self.location.x + self.velocity.dx * (delta_t.as_secs_f64());
|
||||
self.location.y = self.location.y + self.velocity.dy * (delta_t.as_secs_f64());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct World {
|
||||
grains: Arc<RwLock<Vec<Grain>>>,
|
||||
}
|
||||
|
||||
impl World {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
grains: Arc::new(RwLock::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_grain(&self, grain: Grain) {
|
||||
self.grains.write().unwrap().push(grain);
|
||||
}
|
||||
|
||||
pub fn grain_count(&self) -> usize {
|
||||
self.grains.read().unwrap().len()
|
||||
}
|
||||
|
||||
pub fn grains(&self) -> Vec<Grain> {
|
||||
self.grains.read().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn next(&self, delta_t: std::time::Duration) {
|
||||
self.move_objects(delta_t);
|
||||
self.resolve_overlaps();
|
||||
}
|
||||
|
||||
fn move_objects(&self, delta_t: std::time::Duration) {
|
||||
/* First, need to resolve collisions between objects and ensure that they bounce in the correct direction. This will only resolve the initial collision in a step. Additional collisions are undetectable, so we will resolve those with the overlap code. */
|
||||
for grain in self.grains.write().unwrap().iter_mut() {
|
||||
grain.move_by(delta_t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Once all movement has been calculated out, some objects are probably still going to be overlapping. */
|
||||
fn resolve_overlaps(&self) {}
|
||||
}
|
||||
|
||||
pub trait Collision {
|
||||
type Other;
|
||||
fn overlap(&self, other: &Self::Other) -> Option<f64>;
|
||||
fn resolve_collision(&mut self, other: &mut Self::Other);
|
||||
}
|
||||
|
||||
impl Collision for Grain {
|
||||
type Other = Grain;
|
||||
|
||||
fn overlap(&self, other: &Self::Other) -> Option<f64> {
|
||||
let radii = (self.radius + other.radius) * (self.radius + other.radius);
|
||||
let distance = self.location.distance_sq(&other.location);
|
||||
if distance < radii {
|
||||
let dx = other.location.x - self.location.x;
|
||||
let dy = other.location.y - self.location.y;
|
||||
Some(radii.sqrt() - distance.sqrt())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_collision(&mut self, other: &mut Self::Other) {
|
||||
// between every two objects calculate out the point and angle of incidence for a collision.
|
||||
// Start with i, the intersection distance, which is the addition of the radii of both objects.
|
||||
// Then calculate t = i / |v1 - v2|
|
||||
// I don't think that my equation takes into account two objects that don't collide
|
||||
/*
|
||||
match self.overlap(other) {
|
||||
Some(overlap) => {
|
||||
// a collision has occured. First, undo the overlap by moving both pieces backwards to their intersection points
|
||||
// once reversed, calculate percentage of travel already done
|
||||
// next, calculate the bounce vectors
|
||||
// finally, apply the bounce vectors, scaled by remaining travel percentage
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use cool_asserts::assert_matches;
|
||||
|
||||
#[test]
|
||||
fn it_detects_grain_grain_collision() {
|
||||
let grain_1 = Grain {
|
||||
radius: 10.,
|
||||
location: Point { x: 0., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
let grain_2 = Grain {
|
||||
radius: 10.,
|
||||
location: Point { x: 1., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
let grain_3 = Grain {
|
||||
radius: 4.,
|
||||
location: Point { x: 15., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
|
||||
assert_matches!(grain_1.overlap(&grain_2), Some(overlap) => {
|
||||
assert!(within(overlap, 19., 0.1));
|
||||
} );
|
||||
assert_matches!(grain_1.overlap(&grain_3), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_moves_a_grain_according_to_time() {
|
||||
let mut grain_1 = Grain {
|
||||
radius: 10.,
|
||||
location: Point { x: 0., y: 0. },
|
||||
velocity: Vector { dx: 5., dy: 5. },
|
||||
};
|
||||
|
||||
grain_1.move_by(std::time::Duration::from_millis(500));
|
||||
let dest = Point { x: 2.5, y: 2.5 };
|
||||
assert!(grain_1.location.eq(&dest, 0.001));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_moves_many_grains() {
|
||||
let grain_1 = Grain {
|
||||
radius: 5.,
|
||||
location: Point { x: 0., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: -1. },
|
||||
};
|
||||
let grain_1_b = Grain {
|
||||
location: Point { x: 0., y: -0.5 },
|
||||
..grain_1
|
||||
};
|
||||
let grain_2 = Grain {
|
||||
radius: 5.,
|
||||
location: Point { x: 5., y: 5. },
|
||||
velocity: Vector { dx: 0., dy: 1. },
|
||||
};
|
||||
let grain_2_b = Grain {
|
||||
location: Point { x: 5., y: 5.5 },
|
||||
..grain_2
|
||||
};
|
||||
let grain_3 = Grain {
|
||||
radius: 5.,
|
||||
location: Point { x: 15., y: 0. },
|
||||
velocity: Vector { dx: 1., dy: 1. },
|
||||
};
|
||||
let grain_3_b = Grain {
|
||||
location: Point { x: 15.5, y: 0.5 },
|
||||
..grain_3
|
||||
};
|
||||
|
||||
let world = World::new();
|
||||
world.add_grain(grain_1);
|
||||
world.add_grain(grain_2);
|
||||
world.add_grain(grain_3);
|
||||
|
||||
world.next(std::time::Duration::from_millis(500));
|
||||
let grains = world.grains();
|
||||
for grain in grains {
|
||||
let tolerance = 0.001;
|
||||
assert!(
|
||||
grain.location.eq(&grain_1_b.location, tolerance)
|
||||
|| grain.location.eq(&grain_2_b.location, tolerance)
|
||||
|| grain.location.eq(&grain_3_b.location, tolerance)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_resolves_a_collision_when_no_collision_is_present() {
|
||||
let mut grain_1 = Grain {
|
||||
radius: 10.,
|
||||
location: Point { x: 0., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
let mut grain_2 = Grain {
|
||||
radius: 4.,
|
||||
location: Point { x: 15., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
|
||||
let grain_1_b = grain_1.clone();
|
||||
let grain_2_b = grain_2.clone();
|
||||
|
||||
grain_1.resolve_collision(&mut grain_2);
|
||||
assert!(grain_1.location.eq(&grain_1_b.location, 0.001));
|
||||
assert!(grain_2.location.eq(&grain_2_b.location, 0.001));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_resolves_a_collision() {
|
||||
let mut grain_1 = Grain {
|
||||
radius: 4.,
|
||||
location: Point { x: 0., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
let mut grain_2 = Grain {
|
||||
radius: 4.,
|
||||
location: Point { x: 4., y: 0. },
|
||||
velocity: Vector { dx: 0., dy: 0. },
|
||||
};
|
||||
|
||||
grain_1.resolve_collision(&mut grain_2);
|
||||
assert!(
|
||||
grain_1.location.eq(&Point { x: -2., y: 0. }, 0.001),
|
||||
"{:?}",
|
||||
grain_1
|
||||
);
|
||||
assert!(grain_2.location.eq(&Point { x: 6., y: 0. }, 0.001));
|
||||
assert_eq!(grain_1.overlap(&grain_2), None);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
pub fn profile<F, T>(tag: &str, f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let start_time = std::time::Instant::now();
|
||||
let retval = f();
|
||||
let end_time = std::time::Instant::now();
|
||||
println!("[{}] {:?}", tag, end_time - start_time);
|
||||
retval
|
||||
}
|
||||
|
||||
/*
|
||||
struct Profile {
|
||||
metric: Arc<RwLock<HashMap<String, [f64; 100]>>>,
|
||||
receiver: async_channel::Receiver<(String, f64)>,
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
async fn run(&self) {
|
||||
loop {
|
||||
if let Ok(name, value) = self.receiver.recv().await {
|
||||
self.metric.write().unwrap().entry(name).and_modify(|metric| metric.).or_insert(vec![0.; 100]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -81,6 +81,7 @@
|
|||
dashboard = cargo_nix.workspaceMembers.dashboard.build;
|
||||
file-service = cargo_nix.workspaceMembers.file-service.build;
|
||||
fitnesstrax = cargo_nix.workspaceMembers.fitnesstrax.build;
|
||||
falling-sand = cargo_nix.workspaceMembers.falling-sand.build;
|
||||
|
||||
all = pkgs.symlinkJoin {
|
||||
name = "all";
|
||||
|
|
Loading…
Reference in New Issue