@@ 296,6 296,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
+name = "amd"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a679e001575697a3bd195813feb57a4718ecc08dc194944015cbc5f6213c2b96"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
name = "android-activity"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 422,7 431,7 @@ checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 529,7 538,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 567,7 576,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 683,7 692,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 845,7 854,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 941,7 950,7 @@ checksum = "b8c733807158f8fcac68e23222e69ed91a6492ae9410fc2c145b9bb182cfd63e"
dependencies = [
"bevy_macro_utils",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 1034,7 1043,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 1146,7 1155,7 @@ checksum = "714273aa7f285c0aaa874b7fbe37fe4e6e45355e3e6f3321aefa1b78cda259e0"
dependencies = [
"bevy_macro_utils",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 1322,7 1331,7 @@ dependencies = [
"parking_lot",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"toml_edit",
]
@@ 1456,7 1465,7 @@ dependencies = [
"spin",
"wasm-bindgen",
"wasm-bindgen-futures",
- "web-time",
+ "web-time 1.1.0",
]
[[package]]
@@ 1532,7 1541,7 @@ dependencies = [
"indexmap",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"uuid",
]
@@ 1594,7 1603,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 1735,7 1744,7 @@ checksum = "5c3e4e32b1b96585740a2b447661af7db1b9d688db5e4d96da50461cd8f5ce63"
dependencies = [
"bevy_macro_utils",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 1963,7 1972,7 @@ dependencies = [
"regex",
"rustc-hash 2.1.1",
"shlex",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 2089,7 2098,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 2293,6 2302,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
+name = "clarabel"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d950c870fad4feed732bc3f7da489d223ba3911eac0522e6512eed7e659cfafe"
+dependencies = [
+ "amd",
+ "cfg-if",
+ "derive_builder",
+ "enum_dispatch",
+ "itertools 0.11.0",
+ "lazy_static",
+ "num-traits",
+ "serde",
+ "serde-big-array",
+ "serde_json",
+ "thiserror 1.0.69",
+ "web-time 0.2.4",
+]
+
+[[package]]
name = "clipboard-win"
version = "5.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2673,6 2702,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
[[package]]
+name = "darling"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "data-encoding"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2694,6 2758,37 @@ dependencies = [
]
[[package]]
+name = "derive_builder"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3"
+dependencies = [
+ "derive_builder_macro",
+]
+
+[[package]]
+name = "derive_builder_core"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "derive_builder_macro"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
+dependencies = [
+ "derive_builder_core",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "derive_more"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2710,7 2805,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"unicode-xid",
]
@@ 2837,7 2932,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 2956,7 3051,7 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
- "web-time",
+ "web-time 1.1.0",
"winapi",
"windows-sys 0.59.0",
"winit",
@@ 3012,7 3107,7 @@ dependencies = [
"profiling",
"thiserror 1.0.69",
"type-map",
- "web-time",
+ "web-time 1.1.0",
"wgpu 25.0.2",
"winit",
]
@@ 3032,7 3127,7 @@ dependencies = [
"profiling",
"raw-window-handle",
"smithay-clipboard",
- "web-time",
+ "web-time 1.1.0",
"webbrowser",
"winit",
]
@@ 3148,7 3243,7 @@ checksum = "1796db3d892515842ca2dfb11124c4bb4a9e58d9f2c5c1072e5bca1b2334507b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3174,7 3269,19 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
+]
+
+[[package]]
+name = "enum_dispatch"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
+dependencies = [
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.110",
]
[[package]]
@@ 3195,7 3302,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3206,7 3313,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3343,7 3450,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3460,7 3567,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3562,7 3669,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 3918,6 4025,16 @@ dependencies = [
]
[[package]]
+name = "good_lp"
+version = "1.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "776aa1ba88ac058e78408c17f4dbff826a51ae08ed6642f71ca0edd7fe9383f3"
+dependencies = [
+ "clarabel",
+ "fnv",
+]
+
+[[package]]
name = "gpu-alloc"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 4196,6 4313,12 @@ dependencies = [
]
[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
name = "idna"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 4322,6 4445,15 @@ dependencies = [
[[package]]
name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
@@ 4491,7 4623,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 4707,16 4839,6 @@ dependencies = [
]
[[package]]
-name = "microlp"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d1790c73b93164ff65868f63164497cb32339458a9297e17e212d91df62258"
-dependencies = [
- "log",
- "sprs",
-]
-
-[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 4882,22 5004,7 @@ checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
dependencies = [
"proc-macro2",
"quote",
- "syn",
-]
-
-[[package]]
-name = "ndarray"
-version = "0.17.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7c9125e8f6f10c9da3aad044cc918cf8784fa34de857b1aa68038eb05a50a9"
-dependencies = [
- "matrixmultiply",
- "num-complex",
- "num-integer",
- "num-traits",
- "portable-atomic",
- "portable-atomic-util",
- "rawpointer",
+ "syn 2.0.110",
]
[[package]]
@@ 5054,7 5161,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 5106,7 5213,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 5627,7 5734,7 @@ dependencies = [
"phf_shared",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"unicase",
]
@@ 5664,7 5771,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 5798,7 5905,7 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 5847,7 5954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 5878,7 5985,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 6454,6 6561,15 @@ dependencies = [
]
[[package]]
+name = "serde-big-array"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_arrays"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6479,7 6595,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 6513,7 6629,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 6744,18 6860,6 @@ dependencies = [
]
[[package]]
-name = "sprs"
-version = "0.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dca58a33be2188d4edc71534f8bafa826e787cc28ca1c47f31be3423f0d6e55"
-dependencies = [
- "ndarray",
- "num-complex",
- "num-traits",
- "smallvec",
-]
-
-[[package]]
name = "stable_deref_trait"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6784,8 6888,8 @@ dependencies = [
"console_error_panic_hook",
"ctrlc",
"getrandom 0.3.4",
+ "good_lp",
"leafwing-input-manager",
- "microlp",
"ordered-float 5.1.0",
"pico-args",
"rand 0.9.2",
@@ 6814,6 6918,12 @@ dependencies = [
]
[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6832,7 6942,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 6898,6 7008,17 @@ dependencies = [
[[package]]
name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
version = "2.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
@@ 6915,7 7036,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 6969,7 7090,7 @@ checksum = "2de773517ee4367314c7918f6c9ef69c201ba72bfdbffb00234c22c50a153b73"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"unicode-ident",
]
@@ 6999,7 7120,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7010,7 7131,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7227,7 7348,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7390,7 7511,7 @@ checksum = "536b6812192bda8551cfa0e52524e328c6a951b48e66529ee4522d6c721243d6"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7570,7 7691,7 @@ checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7620,7 7741,7 @@ checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 7683,7 7804,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"wasm-bindgen-shared",
]
@@ 7843,6 7964,16 @@ dependencies = [
[[package]]
name = "web-time"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
@@ 8329,7 8460,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 8340,7 8471,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 8351,7 8482,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 8362,7 8493,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 8727,7 8858,7 @@ dependencies = [
"wayland-protocols",
"wayland-protocols-plasma",
"web-sys",
- "web-time",
+ "web-time 1.1.0",
"windows-sys 0.52.0",
"x11-dl",
"x11rb",
@@ 8872,7 9003,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"synstructure",
]
@@ 8928,7 9059,7 @@ checksum = "dc6821851fa840b708b4cbbaf6241868cabc85a2dc22f426361b0292bfc0b836"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"zbus-lockstep",
"zbus_xml",
"zvariant",
@@ 8943,7 9074,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ 8997,7 9128,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 9017,7 9148,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"synstructure",
]
@@ 9057,7 9188,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
]
[[package]]
@@ 9098,7 9229,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.110",
"zvariant_utils",
]
@@ 9111,6 9242,6 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "syn",
+ "syn 2.0.110",
"winnow",
]
@@ 4,8 4,8 @@ use bevy::app::App;
use bevy::color::palettes::basic::{RED, WHITE};
use bevy::color::palettes::css::LIMEGREEN;
use bevy::math::Vec3Swizzles;
+use good_lp::{default_solver, variable, Expression, ProblemVariables, Solution, SolutionStatus, SolverModel, Variable};
use leafwing_input_manager::prelude::ActionState;
-use microlp::{OptimizationDirection, Problem};
use crate::attachment::Parts;
use crate::client::input::ClientAction;
use crate::ecs::thruster::{PartThrusters, Thruster, ThrusterOfPart};
@@ 56,6 56,8 @@ fn draw_thruster_debug(
}
// TODO: split this into two passes
+/// The thrust solver!
+/// This is an annoyingly complicated function...
fn solve_thrust(
me: Query<(Option<&Parts>, &GlobalTransform, Entity), With<Me>>,
parts: Query<&PartThrusters>,
@@ 78,6 80,7 @@ fn solve_thrust(
solution.thrusters_on.clear();
solution.converged = false;
+ // we need to find our entire ship
let Ok((our_parts, hearty_transform, hearty)) = me.single() else {
error!("could not solve for thrust: hearty does not exist?");
error!("failed to solve for thrust after {}ms", start.elapsed().as_millis());
@@ 91,49 94,84 @@ fn solve_thrust(
// +Z == counterclockwise/ccw
// -Z == clockwise/cw
- const MAGIC_TORQUE_SCALE_FACTOR: f32 = 100.0; // mystery units
- let mut target_unit_vector = Vec3::ZERO;
+ /*
- let mut anything_pressed = false;
+ Background info:
+ The thrust solver operates in two passes.
+
+ Pass 1: confusingly called the "Thrust" pass, is responsible for cartesian thrust vectoring
+ Pass 2: appropriately named the "Torque" pass, is soley responsible for torque
+
+ In the end, the results of both passes are added together and set as the thrust solution.
+
+ This is why this whole function operates in duplicate.
+
+ */
+
+ let mut target_unit_vector = Vec3::ZERO; // target vector for thrust pass
+ let mut target_torque_vector = Vec3::ZERO; // target vector for torque pass
+
+ let mut anything_pressed = false; // are we going to do anything?
+
+ // +y
if input.pressed(&ClientAction::ThrustForward) {
anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(0.0, 1.0, 0.0);
}
+ // -y
if input.pressed(&ClientAction::ThrustBackward) {
anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(0.0, -1.0, 0.0);
}
+ // +x
if input.pressed(&ClientAction::ThrustRight) {
anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(1.0, 0.0, 0.0);
}
+ // -x
if input.pressed(&ClientAction::ThrustLeft) {
anything_pressed = true;
target_unit_vector += hearty_transform.rotation() * Vec3::new(-1.0, 0.0, 0.0);
}
+ // cw => -z
if input.pressed(&ClientAction::TorqueCw) {
anything_pressed = true;
- target_unit_vector += Vec3::new(0.0, 0.0, -1.0 / MAGIC_TORQUE_SCALE_FACTOR);
+ target_torque_vector += Vec3::new(0.0, 0.0, -1.0);
}
+ // ccw => +z
if input.pressed(&ClientAction::TorqueCcw) {
anything_pressed = true;
- target_unit_vector += Vec3::new(0.0, 0.0, 1.0 / MAGIC_TORQUE_SCALE_FACTOR);
+ target_torque_vector += Vec3::new(0.0, 0.0, 1.0);
}
- target_unit_vector = target_unit_vector.normalize();
-
- if target_unit_vector == Vec3::ZERO || !anything_pressed {
+ if !anything_pressed {
trace!("no buttons are pressed; zeroing thrust solution");
trace!("solved thrust in {}ms", start.elapsed().as_millis());
solution.converged = true;
- events.write(solution.clone());
+ events.write(solution.clone()); // send our solution to the server, to be applied
return;
}
+ // Normalize the target vectors.
+ // The thrust solver operates purely based on direction;
+ // it does not care about the strength of the thrusters.
+ // Thus, we normalize everything;
+ // including the target unit vectors, which are rotated with respect to Hearty
+ if target_unit_vector != Vec3::ZERO {
+ target_unit_vector = target_unit_vector.normalize();
+ }
+ // TODO(core): the torque vector should already be normalized, but the solver breaks without this.
+ // TODO(core): Investigate
+ if target_torque_vector != Vec3::ZERO {
+ target_torque_vector = target_torque_vector.normalize();
+ }
+
+ // Determine all parts on the ship. It contains at least Hearty...
let mut all_parts = vec![hearty];
if let Some(parts) = our_parts {
+ // and if we have an &Parts, all the attached parts too
all_parts.extend(parts.iter());
}
@@ 142,7 180,7 @@ fn solve_thrust(
for part in &all_parts {
let Ok(part_thrusters) = parts.get(*part) else {
- continue;
+ continue; // This part has no thrusters
};
for thruster_id in &**part_thrusters {
let Ok((thruster, thruster_transform)) = thrusters.get(*thruster_id) else {
@@ 155,79 193,170 @@ fn solve_thrust(
// determine our xy offset from hearty
let relative_translation = thruster_transform.translation().xy() - hearty_transform.translation().xy();
- // determine our rotational offset from hearty
- let relative_rotation = thruster_transform.rotation() * -hearty_transform.rotation();
-
- let thruster_torque = relative_translation.extend(0.0).cross(thruster_vector.extend(0.0)).z / MAGIC_TORQUE_SCALE_FACTOR;
- // magically assemble the worldspace vector! for the solver (not shipspace)
- let target_vector = thruster_vector.extend(thruster_torque);
+ // Magic torque equation: I stole this from avian's code
+ // The only difference is that like everything else, it's all normalized
+ // I haven't the faintest idea what this actually does
+ // No touchy
+ let thruster_torque = relative_translation.normalize().extend(0.0).cross(thruster_vector.normalize().extend(0.0)).z;
+
+ // Although all the numbers going in were normalized, the torque output is in different
+ // units and is wacky. Re-normalize it to a set of expected values, since this is all
+ // direction based anyway.
+ let renormalized_thruster_torque = if thruster_torque.abs() < 0.1 {
+ 0.0 // This thruster's effect is small enough to be ignored
+ } else if thruster_torque < 0.0 {
+ -1.0 // if it's negative, force to -1
+ } else {
+ 1.0 // if it's positive, force to +1
+ };
- all_thrusters.push((thruster_id, target_vector));
+ // Then, push all this data for the next section to deal with.
+ all_thrusters.push((thruster_id,
+ thruster_vector.extend(0.0),
+ Vec3::new(0.0, 0.0, renormalized_thruster_torque)
+ ));
}
}
- // calculate thrust and torque values
- trace!("found {} thrusters, computing coefficients", all_thrusters.len());
+ /*
+ Why are we normalizing everything, you may ask?
+
+ A: The thrust solver concerns itself only with direction. It is intended to be a more dynamic
+ alternative to the standard "assume the ship is the structure it should be and guess the thrust
+ offsets from that" approach, mostly because I didn't want to implement that, and this seemed
+ more fun.
+
+ Also, it makes the solver converge faster, because reasons.
+ */
+
+ // calculate thrust ~~and torque~~ values
+
+ /*
+ Consult the paper for more information.
- for thruster in &all_thrusters {
- trace!("thruster on ship: {:?}", thruster);
+ Recall that we're optimizing an equation of form i_0 * x_0 + i_1 * x_1 + i_2 * x_2 ... i_n * x_n
+ "Coefficients" are i_0 ... i_n, and can be precomputed, and x_0 ... x_n is the "decision variables"
+ */
+
+ if all_thrusters.len() == 0 {
+ trace!("there are no thrusters; zeroing thrust solution");
+ trace!("solved thrust in {}ms", start.elapsed().as_millis());
+ solution.converged = true;
+ events.write(solution.clone()); // send our solution to the server, to be applied
+ return;
}
let coefficients = all_thrusters.iter()
.map(|u| {
- trace!("{} dot {}", target_unit_vector, u.1.normalize());
- target_unit_vector.dot(u.1.normalize())
+ // Computes both system coefficients, for simplicity
+ (
+ target_unit_vector.dot(u.1.normalize()), // Thrust coefficient
+ target_torque_vector.dot(u.2.normalize()) // Torque coefficient
+ )
})
.map(|u| {
- trace!("=> {u}");
// improve reliability:
- // if dot is <0.1, zap it entirely (this thruster is not helping)
- // TODO: figure out how to make this adjustable
- if u.abs() < 0.1 {
- 0.0
+ // if thrust coefficient is <0.1, zap it entirely (this thruster is not helping)
+ // This is done elsewhere for torque, so pass it (u.1) through unchanged
+ // TODO(core): figure out how to make this adjustable
+ if u.0.abs() < 0.1 {
+ (0.0, u.1)
} else {
- u
+ (u.0, u.1)
}
})
- //.map(|u| u.powi(3))
+ .map(|u| {
+ // Sometimes NaN shows up. This just means zero. I hate math.
+ (
+ if u.0.is_nan() { 0.0 } else { u.0 },
+ if u.1.is_nan() { 0.0 } else { u.1 },
+ )
+ })
.collect::<Vec<_>>();
- trace!("preparing model");
- let mut problem = Problem::new(OptimizationDirection::Maximize);
+ trace!("preparing models");
+ /* The Model is the actual solver. Currently using clarabel, but this could change. */
+ let mut thrust_variables = ProblemVariables::new();
+ let mut torque_variables = ProblemVariables::new();
// add variables to problem
+ // Iterate through each of our variables (thrusters) and add them to the model.
+ // This will be used next to create the actual problem.
let variables = coefficients.iter()
- .map(|u| problem.add_var(*u as f64, (0.0, 1.0)))
+ .map(|u| {
+ // We need to return these handles later to get the values back
+ (
+ (
+ u.0 as f64,
+ thrust_variables.add(variable().min(0.0).max(1.0).initial(u.0))
+ ),
+ (
+ u.1 as f64,
+ torque_variables.add(variable().min(0.0).max(1.0).initial(u.1))
+ ),
+ )
+ })
.collect::<Vec<_>>();
+ // Calculate the actual problem; this is a bounded sum
+ let thrust_problem: Expression = variables.iter().map(|u| u.0.0 * u.0.1).sum();
+ let torque_problem: Expression = variables.iter().map(|u| u.1.0 * u.1.1).sum();
+
trace!("prepared {} variables; solving", variables.len());
- let ssolution = match problem.solve() {
+ // now, we run the actual solver!
+
+ trace!("starting thrust solve @ {:?}", start.elapsed());
+
+ let thrust_solution = match thrust_variables.maximise(thrust_problem).using(default_solver).solve() {
Ok(soln) => soln,
Err(e) => {
- match e {
- microlp::Error::Infeasible => {
- error!("failed to solve for thrust: constraints cannot be satisfied");
- error!("failed to solve for thrust after {}ms", start.elapsed().as_millis());
- return;
- },
- microlp::Error::Unbounded => {
- error!("failed to solve for thrust: system is unbounded");
- error!("failed to solve for thrust after {}ms", start.elapsed().as_millis());
- return;
- },
- microlp::Error::InternalError(e) => {
- error!("failed to solve for thrust: solver encountered internal error: {e}");
- error!("failed to solve for thrust after {}ms", start.elapsed().as_millis());
- return;
- }
- }
+ error!("failed to solve for thrust: {}", e.to_string());
+ error!("failed to solve for thrust after {}ms", start.elapsed().as_millis());
+ return;
+ }
+ };
+
+ // did the solution converge?
+ match thrust_solution.status() {
+ SolutionStatus::Optimal => {}, // yay!
+ SolutionStatus::TimeLimit => {
+ warn!("thrust solver failed to converge, hit time limit")
+ }
+ SolutionStatus::GapLimit => {
+ warn!("thrust solver failed to converge, hit gap limit")
+ }
+ }
+
+ trace!("finished thrust solve @ {:?}", start.elapsed());
+ trace!("starting torque solve @ {:?}", start.elapsed());
+
+ let torque_solution = match torque_variables.maximise(torque_problem).using(default_solver).solve() {
+ Ok(soln) => soln,
+ Err(e) => {
+ error!("failed to solve for torque: {}", e.to_string());
+ error!("failed to solve for torque after {}ms", start.elapsed().as_millis());
+ return;
}
};
- trace!("found thrust solution!");
- trace!("solution alignment (higher is better): {}", ssolution.objective());
+ // did the solution converge?
+ match torque_solution.status() {
+ SolutionStatus::Optimal => {}, // yay!
+ SolutionStatus::TimeLimit => {
+ warn!("torque solver failed to converge, hit time limit")
+ }
+ SolutionStatus::GapLimit => {
+ warn!("torque solver failed to converge, hit gap limit")
+ }
+ }
+
+ trace!("finished torque solve @ {:?}ms", start.elapsed());
+
+ trace!("found thrust+torque solution!");
+
+ // Finally, extract the info out of the models and compile it into a cohesive ThrustSolution.
let mut new_soln = ThrustSolution {
thrusters_on: BTreeSet::default(),
@@ 235,16 364,20 @@ fn solve_thrust(
};
for thruster in all_thrusters.iter().enumerate() {
- trace!("solution: thruster #{} ({:?}): {} @ coeff {}", thruster.0, thruster.1.0, ssolution.var_value(variables[thruster.0]), coefficients[thruster.0]);
- // TODO: make this more easily adjustable
- if *ssolution.var_value(variables[thruster.0]) > 0.8 {
+ // TODO(core): make this more easily adjustable
+
+ // Currently, we only turn on a thruster if it's variable value (think weight in a weighted sum)
+ // is above 80%.
+ // The solver seems to be picking 0.0 or 1.0 in all circumstances anyway, but just in case.
+
+ if thrust_solution.value(variables[thruster.0].0.1) > 0.8 || torque_solution.value(variables[thruster.0].1.1) > 0.8 {
new_soln.thrusters_on.insert(*thruster.1.0);
}
}
let elapsed = start.elapsed();
- debug!(?elapsed, ?target_unit_vector, "solved for thrust");
- *solution = new_soln;
- events.write(solution.clone());
+ debug!(?elapsed, ?target_unit_vector, ?target_torque_vector, "solved for thrust and torque");
+ *solution = new_soln; // save it to the Resource for use on the client...
+ events.write(solution.clone()); // ...then send it to the server!
return;
}