~saiko/game

40f16f4712fbcb52813b592a02d03e0c28d70b2f — 2xsaiko 1 year, 18 days ago 476356b
Drawing optimizations, fix border layout
A Cargo.lock => Cargo.lock +1565 -0
@@ 0,0 1,1565 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"

[[package]]
name = "alga"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658f9468113d34781f6ca9d014d174c74b73de870f1e0e3ad32079bbab253b19"
dependencies = [
 "approx",
 "libm",
 "num-complex",
 "num-traits",
]

[[package]]
name = "andrew"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
dependencies = [
 "bitflags",
 "line_drawing",
 "rusttype 0.7.9",
 "walkdir",
 "xdg",
 "xml-rs",
]

[[package]]
name = "android_glue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"

[[package]]
name = "approx"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
dependencies = [
 "num-traits",
]

[[package]]
name = "arrayref"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"

[[package]]
name = "arrayvec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"

[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"

[[package]]
name = "backtrace"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
dependencies = [
 "backtrace-sys",
 "cfg-if",
 "libc",
 "rustc-demangle",
]

[[package]]
name = "backtrace-sys"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
dependencies = [
 "cc",
 "libc",
]

[[package]]
name = "base64"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
dependencies = [
 "byteorder",
]

[[package]]
name = "bit-set"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
dependencies = [
 "bit-vec",
]

[[package]]
name = "bit-vec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"

[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"

[[package]]
name = "blake2b_simd"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0"
dependencies = [
 "arrayref",
 "arrayvec",
 "constant_time_eq",
]

[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"

[[package]]
name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"

[[package]]
name = "bzip2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
dependencies = [
 "bzip2-sys",
 "libc",
]

[[package]]
name = "bzip2-sys"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6584aa36f5ad4c9247f5323b0a42f37802b37a836f0ad87084d7a33961abe25f"
dependencies = [
 "cc",
 "libc",
]

[[package]]
name = "c2-chacha"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
dependencies = [
 "ppv-lite86",
]

[[package]]
name = "calloop"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7aa2097be53a00de9e8fc349fea6d76221f398f5c4fa550d420669906962d160"
dependencies = [
 "mio",
 "mio-extras",
 "nix",
]

[[package]]
name = "cc"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"

[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"

[[package]]
name = "cgl"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff"
dependencies = [
 "libc",
]

[[package]]
name = "chrono"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
dependencies = [
 "num-integer",
 "num-traits",
 "time",
]

[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
 "bitflags",
]

[[package]]
name = "cocoa"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
dependencies = [
 "bitflags",
 "block",
 "core-foundation",
 "core-graphics",
 "foreign-types",
 "libc",
 "objc",
]

[[package]]
name = "constant_time_eq"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"

[[package]]
name = "core-foundation"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
dependencies = [
 "core-foundation-sys",
 "libc",
]

[[package]]
name = "core-foundation-sys"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"

[[package]]
name = "core-graphics"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
dependencies = [
 "bitflags",
 "core-foundation",
 "foreign-types",
 "libc",
]

[[package]]
name = "core-video-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dc065219542086f72d1e9f7aadbbab0989e980263695d129d502082d063a9d0"
dependencies = [
 "cfg-if",
 "core-foundation-sys",
 "core-graphics",
 "libc",
 "objc",
]

[[package]]
name = "crc32fast"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
dependencies = [
 "cfg-if",
]

[[package]]
name = "crossbeam-utils"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
dependencies = [
 "cfg-if",
 "lazy_static",
]

[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
dependencies = [
 "cfg-if",
 "dirs-sys",
]

[[package]]
name = "dirs-sys"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
dependencies = [
 "cfg-if",
 "libc",
 "redox_users",
 "winapi 0.3.8",
]

[[package]]
name = "dispatch"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e93ca78226c51902d7aa8c12c988338aadd9e85ed9c6be8aaac39192ff3605"

[[package]]
name = "dlib"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
dependencies = [
 "libloading",
]

[[package]]
name = "downcast-rs"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"

[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"

[[package]]
name = "failure"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
dependencies = [
 "backtrace",
 "failure_derive",
]

[[package]]
name = "failure_derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
dependencies = [
 "proc-macro2 1.0.7",
 "quote 1.0.2",
 "syn",
 "synstructure",
]

[[package]]
name = "fixedbitset"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"

[[package]]
name = "flate2"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f"
dependencies = [
 "cfg-if",
 "crc32fast",
 "libc",
 "miniz_oxide",
]

[[package]]
name = "float-pretty-print"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5251eae93541dccf57e6f7e5590a76a652eb4e4ddd44f851a32162e1bb203e81"

[[package]]
name = "fnv"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"

[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
 "foreign-types-shared",
]

[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"

[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"

[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
 "bitflags",
 "fuchsia-zircon-sys",
]

[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"

[[package]]
name = "gamev2"
version = "0.1.0"
dependencies = [
 "bit-set",
 "chrono",
 "float-pretty-print",
 "glium",
 "itertools",
 "log",
 "nalgebra",
 "ncollide3d",
 "simplelog",
 "zip",
]

[[package]]
name = "generic-array"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
dependencies = [
 "typenum",
]

[[package]]
name = "getrandom"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
dependencies = [
 "cfg-if",
 "libc",
 "wasi",
]

[[package]]
name = "gl_generator"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca98bbde17256e02d17336a6bdb5a50f7d0ccacee502e191d3e3d0ec2f96f84a"
dependencies = [
 "khronos_api",
 "log",
 "xml-rs",
]

[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
 "khronos_api",
 "log",
 "xml-rs",
]

[[package]]
name = "glium"
version = "0.26.0-alpha5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5562f15bd5c6f23d5b07090bb990a6478da430df018ee85e3fbc370230ef058"
dependencies = [
 "backtrace",
 "fnv",
 "gl_generator 0.14.0",
 "glutin",
 "lazy_static",
 "memoffset",
 "smallvec 0.6.13",
 "takeable-option",
]

[[package]]
name = "glutin"
version = "0.22.0-alpha5"
dependencies = [
 "android_glue",
 "cgl",
 "cocoa",
 "core-foundation",
 "core-graphics",
 "glutin_egl_sys",
 "glutin_emscripten_sys",
 "glutin_gles2_sys",
 "glutin_glx_sys",
 "glutin_wgl_sys",
 "lazy_static",
 "libloading",
 "log",
 "objc",
 "osmesa-sys",
 "parking_lot 0.9.0",
 "wayland-client",
 "winapi 0.3.8",
 "winit",
]

[[package]]
name = "glutin_egl_sys"
version = "0.1.4"
dependencies = [
 "gl_generator 0.13.1",
 "winapi 0.3.8",
]

[[package]]
name = "glutin_emscripten_sys"
version = "0.1.0"

[[package]]
name = "glutin_gles2_sys"
version = "0.1.3"
dependencies = [
 "gl_generator 0.13.1",
 "objc",
]

[[package]]
name = "glutin_glx_sys"
version = "0.1.5"
dependencies = [
 "gl_generator 0.13.1",
 "x11-dl",
]

[[package]]
name = "glutin_wgl_sys"
version = "0.1.3"
dependencies = [
 "gl_generator 0.13.1",
]

[[package]]
name = "instant"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf"

[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
 "libc",
]

[[package]]
name = "itertools"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
dependencies = [
 "either",
]

[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
 "winapi 0.2.8",
 "winapi-build",
]

[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"

[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"

[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"

[[package]]
name = "libc"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"

[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
 "cc",
 "winapi 0.3.8",
]

[[package]]
name = "libm"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"

[[package]]
name = "line_drawing"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
dependencies = [
 "num-traits",
]

[[package]]
name = "lock_api"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586"
dependencies = [
 "scopeguard",
]

[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
 "cfg-if",
]

[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
 "libc",
]

[[package]]
name = "matrixmultiply"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f"
dependencies = [
 "rawpointer",
]

[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"

[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
dependencies = [
 "libc",
 "winapi 0.3.8",
]

[[package]]
name = "memoffset"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
dependencies = [
 "rustc_version",
]

[[package]]
name = "miniz_oxide"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625"
dependencies = [
 "adler32",
]

[[package]]
name = "mio"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
dependencies = [
 "cfg-if",
 "fuchsia-zircon",
 "fuchsia-zircon-sys",
 "iovec",
 "kernel32-sys",
 "libc",
 "log",
 "miow",
 "net2",
 "slab",
 "winapi 0.2.8",
]

[[package]]
name = "mio-extras"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
dependencies = [
 "lazycell",
 "log",
 "mio",
 "slab",
]

[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
dependencies = [
 "kernel32-sys",
 "net2",
 "winapi 0.2.8",
 "ws2_32-sys",
]

[[package]]
name = "nalgebra"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0abb021006c01b126a936a8dd1351e0720d83995f4fc942d0d426c654f990745"
dependencies = [
 "alga",
 "approx",
 "generic-array",
 "matrixmultiply",
 "num-complex",
 "num-rational",
 "num-traits",
 "rand",
 "rand_distr",
 "typenum",
]

[[package]]
name = "ncollide3d"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5b02e85d04190e6f39e9435a9b915483a9d31424d270f9107fd6d0ff8298fa6"
dependencies = [
 "alga",
 "approx",
 "bitflags",
 "downcast-rs",
 "either",
 "nalgebra",
 "num-traits",
 "petgraph",
 "slab",
 "slotmap",
 "smallvec 0.6.13",
]

[[package]]
name = "net2"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
dependencies = [
 "cfg-if",
 "libc",
 "winapi 0.3.8",
]

[[package]]
name = "nix"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
dependencies = [
 "bitflags",
 "cc",
 "cfg-if",
 "libc",
 "void",
]

[[package]]
name = "num-complex"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
dependencies = [
 "autocfg",
 "num-traits",
]

[[package]]
name = "num-integer"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
dependencies = [
 "autocfg",
 "num-traits",
]

[[package]]
name = "num-rational"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
dependencies = [
 "autocfg",
 "num-integer",
 "num-traits",
]

[[package]]
name = "num-traits"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
dependencies = [
 "autocfg",
]

[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
 "malloc_buf",
]

[[package]]
name = "ordered-float"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
dependencies = [
 "num-traits",
]

[[package]]
name = "ordermap"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"

[[package]]
name = "osmesa-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
dependencies = [
 "shared_library",
]

[[package]]
name = "parking_lot"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
dependencies = [
 "lock_api",
 "parking_lot_core 0.6.2",
 "rustc_version",
]

[[package]]
name = "parking_lot"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
dependencies = [
 "lock_api",
 "parking_lot_core 0.7.0",
]

[[package]]
name = "parking_lot_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
dependencies = [
 "cfg-if",
 "cloudabi",
 "libc",
 "redox_syscall",
 "rustc_version",
 "smallvec 0.6.13",
 "winapi 0.3.8",
]

[[package]]
name = "parking_lot_core"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
dependencies = [
 "cfg-if",
 "cloudabi",
 "libc",
 "redox_syscall",
 "smallvec 1.1.0",
 "winapi 0.3.8",
]

[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"

[[package]]
name = "petgraph"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
dependencies = [
 "fixedbitset",
 "ordermap",
]

[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"

[[package]]
name = "podio"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"

[[package]]
name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"

[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
 "unicode-xid 0.1.0",
]

[[package]]
name = "proc-macro2"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
dependencies = [
 "unicode-xid 0.2.0",
]

[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
 "proc-macro2 0.4.30",
]

[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
dependencies = [
 "proc-macro2 1.0.7",
]

[[package]]
name = "rand"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
dependencies = [
 "getrandom",
 "libc",
 "rand_chacha",
 "rand_core 0.5.1",
 "rand_hc",
]

[[package]]
name = "rand_chacha"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
dependencies = [
 "c2-chacha",
 "rand_core 0.5.1",
]

[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
 "rand_core 0.4.2",
]

[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"

[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
 "getrandom",
]

[[package]]
name = "rand_distr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
dependencies = [
 "rand",
]

[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
 "rand_core 0.5.1",
]

[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
 "cloudabi",
 "fuchsia-cprng",
 "libc",
 "rand_core 0.4.2",
 "rdrand",
 "winapi 0.3.8",
]

[[package]]
name = "raw-window-handle"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
dependencies = [
 "libc",
]

[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"

[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
 "rand_core 0.3.1",
]

[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"

[[package]]
name = "redox_users"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
dependencies = [
 "failure",
 "rand_os",
 "redox_syscall",
 "rust-argon2",
]

[[package]]
name = "rust-argon2"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
dependencies = [
 "base64",
 "blake2b_simd",
 "crossbeam-utils",
]

[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"

[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
 "semver",
]

[[package]]
name = "rusttype"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5"
dependencies = [
 "rusttype 0.8.2",
]

[[package]]
name = "rusttype"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14a911032fb5791ccbeec9f28fdcb9bf0983b81f227bafdfd227c658d0731c8a"
dependencies = [
 "approx",
 "arrayvec",
 "ordered-float",
 "stb_truetype",
]

[[package]]
name = "same-file"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
dependencies = [
 "winapi-util",
]

[[package]]
name = "scopeguard"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"

[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
 "semver-parser",
]

[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"

[[package]]
name = "shared_library"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11"
dependencies = [
 "lazy_static",
 "libc",
]

[[package]]
name = "simplelog"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05a3e303ace6adb0a60a9e9e2fbc6a33e1749d1e43587e2125f7efa9c5e107c5"
dependencies = [
 "chrono",
 "log",
 "term",
]

[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"

[[package]]
name = "slotmap"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c46a3482db8f247956e464d783693ece164ca056e6e67563ee5505bdb86452cd"

[[package]]
name = "smallvec"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
dependencies = [
 "maybe-uninit",
]

[[package]]
name = "smallvec"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"

[[package]]
name = "smithay-client-toolkit"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054"
dependencies = [
 "andrew",
 "bitflags",
 "dlib",
 "lazy_static",
 "memmap",
 "nix",
 "wayland-client",
 "wayland-protocols",
]

[[package]]
name = "stb_truetype"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51"
dependencies = [
 "byteorder",
]

[[package]]
name = "syn"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc157159e2a7df58cd67b1cace10b8ed256a404fb0070593f137d8ba6bef4de"
dependencies = [
 "proc-macro2 1.0.7",
 "quote 1.0.2",
 "unicode-xid 0.2.0",
]

[[package]]
name = "synstructure"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
dependencies = [
 "proc-macro2 1.0.7",
 "quote 1.0.2",
 "syn",
 "unicode-xid 0.2.0",
]

[[package]]
name = "takeable-option"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36ae8932fcfea38b7d3883ae2ab357b0d57a02caaa18ebb4f5ece08beaec4aa0"

[[package]]
name = "term"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
dependencies = [
 "dirs",
 "winapi 0.3.8",
]

[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
dependencies = [
 "libc",
 "redox_syscall",
 "winapi 0.3.8",
]

[[package]]
name = "typenum"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"

[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"

[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"

[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"

[[package]]
name = "walkdir"
version = "2.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
dependencies = [
 "same-file",
 "winapi 0.3.8",
 "winapi-util",
]

[[package]]
name = "wasi"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"

[[package]]
name = "wayland-client"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1080ebe0efabcf12aef2132152f616038f2d7dcbbccf7b2d8c5270fe14bcda"
dependencies = [
 "bitflags",
 "calloop",
 "downcast-rs",
 "libc",
 "mio",
 "nix",
 "wayland-commons",
 "wayland-scanner",
 "wayland-sys",
]

[[package]]
name = "wayland-commons"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb"
dependencies = [
 "nix",
 "wayland-sys",
]

[[package]]
name = "wayland-protocols"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cc286643656742777d55dc8e70d144fa4699e426ca8e9d4ef454f4bf15ffcf9"
dependencies = [
 "bitflags",
 "wayland-client",
 "wayland-commons",
 "wayland-scanner",
]

[[package]]
name = "wayland-scanner"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93b02247366f395b9258054f964fe293ddd019c3237afba9be2ccbe9e1651c3d"
dependencies = [
 "proc-macro2 0.4.30",
 "quote 0.6.13",
 "xml-rs",
]

[[package]]
name = "wayland-sys"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4"
dependencies = [
 "dlib",
 "lazy_static",
]

[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"

[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
dependencies = [
 "winapi-i686-pc-windows-gnu",
 "winapi-x86_64-pc-windows-gnu",
]

[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

[[package]]
name = "winapi-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
dependencies = [
 "winapi 0.3.8",
]

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

[[package]]
name = "winit"
version = "0.20.0-alpha5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14fbf7c84c8c1ff9d72982cb382c1a78fbe0f7556f49b1ca98de212d018c5b82"
dependencies = [
 "android_glue",
 "bitflags",
 "calloop",
 "cocoa",
 "core-foundation",
 "core-graphics",
 "core-video-sys",
 "dispatch",
 "instant",
 "lazy_static",
 "libc",
 "log",
 "objc",
 "parking_lot 0.10.0",
 "percent-encoding",
 "raw-window-handle",
 "smithay-client-toolkit",
 "wayland-client",
 "winapi 0.3.8",
 "x11-dl",
]

[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
dependencies = [
 "winapi 0.2.8",
 "winapi-build",
]

[[package]]
name = "x11-dl"
version = "2.18.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be65e1342a3baae65439cd03306778831a3d133b0d20243a7fb83fd5cf403c58"
dependencies = [
 "lazy_static",
 "libc",
 "maybe-uninit",
 "pkg-config",
]

[[package]]
name = "xdg"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"

[[package]]
name = "xml-rs"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"

[[package]]
name = "zip"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c21bb410afa2bd823a047f5bda3adb62f51074ac7e06263b2c97ecdd47e9fc6"
dependencies = [
 "bzip2",
 "crc32fast",
 "flate2",
 "podio",
 "time",
]

M data/shader/font.fsh => data/shader/font.fsh +2 -0
@@ 9,4 9,6 @@ out vec4 color;

void main() {
    color = f_color * texture2D(texture, f_uv);

    if (color.a < 0.1) discard;
}
\ No newline at end of file

M data/shader/uipoly.fsh => data/shader/uipoly.fsh +3 -3
@@ 1,9 1,9 @@
#version 400 core

uniform vec4 color;
in vec4 f_color;

out vec4 color_out;
out vec4 color;

void main() {
    color_out = color;
    color = f_color;
}
\ No newline at end of file

M data/shader/uipoly.vsh => data/shader/uipoly.vsh +6 -2
@@ 2,8 2,12 @@

uniform mat4 mvp;

in ivec2 xy;
in vec3 xyz;
in vec4 color;

out vec4 f_color;

void main() {
    gl_Position = mvp * vec4(xy, 0, 1);
    f_color = color;
    gl_Position = mvp * vec4(xyz, 1);
}
\ No newline at end of file

M data/strs/english.str => data/strs/english.str +2 -0
@@ 1,6 1,8 @@
// This file supports comments, except for in multiline strings. There, they
// will be treated like any other normal text.

// All the actual localization is split into multiple files so that there's
// not one huge unmaintainable file.
include english/ui.str

test_string: This is a test string.

M src/font/bdf/draw.rs => src/font/bdf/draw.rs +104 -32
@@ 2,7 2,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use glium::{Blend, DrawParameters, Program, Rect, Surface, VertexBuffer};
use glium::{DepthTest, DrawParameters, GlObject, Program, Rect, Surface, Texture2d, VertexBuffer};
use glium::backend::Facade;
use glium::index::{NoIndices, PrimitiveType};
use glium::texture::RawImage2d;


@@ 10,7 10,7 @@ use glium::uniforms::UniformsStorage;

use crate::font::bdf::Bdf;
use crate::font::FontRenderer;
use crate::math::Mat4;
use crate::math::{Mat4, Vec3};
use crate::tex::atlas::{Sprite, TextureAtlas};
use crate::util::{AnySurface, Color};



@@ 56,29 56,32 @@ impl<'a> BakedFont<'a> {
      }
    }
  }
}

impl<'a> FontRenderer for BakedFont<'a> {
  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]) -> Vec<(f32, f32)> {
    implement_vertex!(Vertex, xyz, uv, color, size, uv_size);

    #[derive(Clone, Copy)]
    struct Vertex {
      xyz: [f32; 3],
      uv: [f32; 2],
      color: [f32; 4],
      size: [f32; 2],
      uv_size: [f32; 2],
  pub fn create_data(&self, strs: &[(&str, f32, f32, Color)]) -> BakedString<'a> {
    let mut texture: Option<Rc<Texture2d>> = None;
    let mut result = BakedString {
      facade: self.facade,
      prog: self.prog.clone(),
      data: vec![],
    };

    let char_count = strs.iter().fold(0, |acc, &(a, ..)| acc + a.len());
    if char_count == 0 {
      return result;
    }

    let mut texture = None;
    let mut buf = Vec::with_capacity(strs.iter().fold(0, |acc, &(a, ..)| acc + a.len()));
    let mut result = Vec::with_capacity(strs.len());
    let mut buf = Vec::with_capacity(char_count);

    for &(s, mut x, mut y, color) in strs {
      for c in s.chars() {
        let glyph = self.bdf.glyph_or_default(c);
        let sprite = self.get_char_sprite(c);

        if texture.as_ref().map(|t| t.get_id() != sprite.texture().get_id()).unwrap_or(false) {
          result.insert(texture.unwrap(), buf);
          buf = vec![];
        }

        let x1 = x + glyph.width as f32;
        let y1 = y + glyph.height as f32;



@@ 95,25 98,28 @@ impl<'a> FontRenderer for BakedFont<'a> {
        x += glyph.dwidth_x as f32;
        y += glyph.dwidth_y as f32;
      }
      result.push((x, y));
    }

    if texture.is_some() {
      let mut dp = DrawParameters::default();
      dp.blend = Blend::alpha_blending();
    result.insert(texture.unwrap(), buf);

      let vb = VertexBuffer::new(self.facade, &buf).unwrap();
    result.update_vbuf()
  }
}

      surface.draw(
        &vb,
        NoIndices(PrimitiveType::Points),
        &self.prog,
        &UniformsStorage::new("mvp", *mvp.as_ref())
          .add("texture", &*texture.unwrap()),
        &dp);
    }
#[derive(Clone, Copy)]
struct Vertex {
  xyz: [f32; 3],
  uv: [f32; 2],
  color: [f32; 4],
  size: [f32; 2],
  uv_size: [f32; 2],
}

    result
implement_vertex!(Vertex, xyz, uv, color, size, uv_size);

impl<'a> FontRenderer for BakedFont<'a> {
  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]) {
    self.create_data(strs).draw(surface, mvp);
  }

  fn get_height(&self) -> f32 {


@@ 132,4 138,70 @@ impl<'a> FontRenderer for BakedFont<'a> {
        self.get_char_width(s.chars().last().unwrap())
    }
  }
}
\ No newline at end of file
}

pub struct BakedString<'a> {
  facade: &'a dyn Facade,
  prog: Rc<Program>,
  data: Vec<(Rc<Texture2d>, Vec<Vertex>, Option<VertexBuffer<Vertex>>)>,
}

impl<'a> BakedString<'a> {
  fn insert(&mut self, tex: Rc<Texture2d>, data: Vec<Vertex>) {
    match self.data.iter_mut().find(|(a, ..)| a.get_id() == tex.get_id()) {
      None => { self.data.push((tex, data, None)); }
      Some((_, vec, opt)) => {
        vec.extend_from_slice(&data);
        *opt = None;
      }
    }
  }

  pub fn combine(mut self, other: Self) -> Self {
    for (tex, entry, _) in other.data {
      self.insert(tex, entry);
    }
    self
  }

  pub fn update_vbuf(mut self) -> Self {
    for (_, entry, vbuf) in self.data.iter_mut() {
      if vbuf.is_none() {
        *vbuf = Some(VertexBuffer::new(self.facade, entry).unwrap());
      }
    }
    self
  }

  pub fn translate(mut self, offset: Vec3) -> Self {
    self.data.iter_mut()
      .flat_map(|(_, v, _)| v.iter_mut())
      .for_each(|Vertex { xyz, .. }| {
        xyz[0] += offset.x();
        xyz[1] += offset.y();
        xyz[2] += offset.z();
      });

    self.data.iter_mut().for_each(|(_, _, vbuf)| *vbuf = None);

    self
  }

  pub fn draw(&self, surface: &mut AnySurface, mvp: &Mat4) {
    let mut dp = DrawParameters::default();
    dp.depth.write = true;
    dp.depth.test = DepthTest::IfLessOrEqual;

    for (tex, _, vbuf) in self.data.iter() {
      if let Some(vbuf) = vbuf {
        surface.draw(
          vbuf,
          NoIndices(PrimitiveType::Points),
          &self.prog,
          &UniformsStorage::new("mvp", *mvp.as_ref())
            .add("texture", &**tex),
          &dp);
      }
    }
  }
}

M src/font/loader.rs => src/font/loader.rs +1 -1
@@ 45,7 45,7 @@ pub enum FontRenderers<'a> {
}

impl<'a> FontRenderer for FontRenderers<'a> {
  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]) -> Vec<(f32, f32)> {
  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]) {
    match self {
      FontRenderers::Bdf(f) => f.draw_strings(surface, mvp, strs),
    }

M src/font/mod.rs => src/font/mod.rs +5 -5
@@ 7,15 7,15 @@ pub mod multifont;
pub mod loader;

pub trait FontRenderer {
  fn draw_char(&self, surface: &mut AnySurface, mvp: &Mat4, c: char, x: f32, y: f32, color: Color) -> (f32, f32) {
    self.draw_string(surface, mvp, &c.to_string(), x, y, color)
  fn draw_char(&self, surface: &mut AnySurface, mvp: &Mat4, c: char, x: f32, y: f32, color: Color) {
    self.draw_string(surface, mvp, &c.to_string(), x, y, color);
  }

  fn draw_string(&self, surface: &mut AnySurface, mvp: &Mat4, s: &str, x: f32, y: f32, color: Color) -> (f32, f32) {
    *self.draw_strings(surface, mvp, &[(s, x, y, color)]).first().unwrap()
  fn draw_string(&self, surface: &mut AnySurface, mvp: &Mat4, s: &str, x: f32, y: f32, color: Color) {
    self.draw_strings(surface, mvp, &[(s, x, y, color)]);
  }

  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]) -> Vec<(f32, f32)>;
  fn draw_strings(&self, surface: &mut AnySurface, mvp: &Mat4, strs: &[(&str, f32, f32, Color)]);

  fn get_height(&self) -> f32;


M src/main.rs => src/main.rs +25 -22
@@ 187,10 187,12 @@ fn start_game(env: Rc<Environment>) {
  let mut frames_since_last = 0;
  let mut last_smooth_fps = Instant::now();

  let mut gui_mode = false;
  let mut gui_mode = true;

  gl_window.set_cursor_grab(true).unwrap();
  gl_window.set_cursor_visible(false);
  if !gui_mode {
    gl_window.set_cursor_grab(true).unwrap();
    gl_window.set_cursor_visible(false);
  }

  let fr = load_fonts(&env.rl, &display, &mut sm);



@@ 211,33 213,34 @@ fn start_game(env: Rc<Environment>) {

    let gui_mat = Mat4::get_ortho(0.0, window.width() as f32, window.height() as f32, 0.0, -10.0, 10.0);

    if !gui_mode {
      draw(&mut frame, &model, &props);
    }

    let mut surface = AnySurface::Frame(&mut frame);
    let mut g = Graphics::new(&display, &mut surface, fr.choose((12, false, window.dpi)), &mut sm, gui_mat);

    if gui_mode {
      let mut surface = AnySurface::Frame(&mut frame);
      let mut g = Graphics::new(&display, &mut surface, fr.choose((12, false, window.dpi)), &mut sm, gui_mat);
      ui.draw(&mut g);
    } else {
      draw(&mut frame, &model, &props);
    }

    let fr = fr.choose((14, false, window.dpi));

    let mut surface = AnySurface::Frame(&mut frame);
    let s = "Press [tab] to switch views";
    let color = Color::white();
    fr.draw_string(&mut surface, &gui_mat, s, window.width() as f32 - 2.0 - fr.get_str_width(s), 2.0, color);
    fr.draw_string(&mut surface, &gui_mat, &format!("fps: {} ({} actual)", smooth_fps, current_fps), 2.0, 2.0, color);
    fr.draw_string(&mut surface, &gui_mat,
                   &format!("pos: {:5.3} {:5.3} {:5.3}",
                            PrettyPrintFloat(camera.pos().x() as f64),
                            PrettyPrintFloat(camera.pos().y() as f64),
                            PrettyPrintFloat(camera.pos().z() as f64)),
                   2.0, 2.0 + fr.get_height(), color);
    fr.draw_string(&mut surface, &gui_mat,
                   &format!("ang: {:5.3} {:5.3} {:5.3}",
                            PrettyPrintFloat(camera.yaw() as f64),
                            PrettyPrintFloat(camera.pitch() as f64),
                            PrettyPrintFloat(camera.roll() as f64)),
                   2.0, 2.0 + 2.0 * fr.get_height(), color);
    g.draw_string(s, window.width() as i32 - 2, 2, StringDrawProps::default().with_alignment(Alignment::Right));
    g.draw_string(&format!("fps: {} ({} actual)", smooth_fps, current_fps), 2, 2, StringDrawProps::default());
    g.draw_string(&format!("pos: {:5.3} {:5.3} {:5.3}",
                           PrettyPrintFloat(camera.pos().x() as f64),
                           PrettyPrintFloat(camera.pos().y() as f64),
                           PrettyPrintFloat(camera.pos().z() as f64)),
                  2, 2 + fr.get_height() as i32, StringDrawProps::default());
    g.draw_string(&format!("ang: {:5.3} {:5.3} {:5.3}",
                           PrettyPrintFloat(camera.yaw() as f64),
                           PrettyPrintFloat(camera.pitch() as f64),
                           PrettyPrintFloat(camera.roll() as f64)),
                  2, 2 + 2 * fr.get_height() as i32, StringDrawProps::default());
    drop(g);
    frame.finish().unwrap();

    let center = LogicalPosition::new(window.scaled_width as f64 / 2.0, window.scaled_height as f64 / 2.0);

M src/ui/element/button.rs => src/ui/element/button.rs +8 -1
@@ 29,7 29,14 @@ impl<F: FnMut()> Element for Button<F> {

  fn get_resize_capabilities(&self, g: &Graphics) -> ResizeCapabilities {
    let fr = g.font_renderer();
    ResizeCapabilities::new(6 + fr.get_str_width(&self.text) as u32, 6 + fr.get_height() as u32, None, None)
    ResizeCapabilities::new(
      Some(6 + fr.get_str_width(&self.text) as u32),
      Some(6 + fr.get_height() as u32),
      None,
      None,
      None,
      None
    )
  }

  fn resize(&mut self, width: u32, height: u32) {

M src/ui/graphics.rs => src/ui/graphics.rs +135 -38
@@ 1,25 1,38 @@
use glium::{DrawParameters, Surface, VertexBuffer};
use glium::{DepthTest, DrawParameters, Surface, VertexBuffer};
use glium::backend::Facade;
use glium::index::{NoIndices, PrimitiveType};
use glium::uniforms::UniformsStorage;
use itertools::Itertools;

use crate::font::bdf::draw::BakedFont;
use crate::font::FontRenderer;
use crate::math::{Mat4, vec3};
use crate::math::{Mat4, vec3, Vec3};
use crate::shader::ShaderManager;
use crate::util::{AnySurface, Color};

pub struct Graphics<'a, 'b, 'c> {
  facade: &'a dyn Facade,
  surface: &'a mut AnySurface<'b>,
  fr: &'a dyn FontRenderer,
  fr: &'a BakedFont<'a>,
  sm: &'a mut ShaderManager<'c>,
  perspective: Mat4,
  mats: Vec<Mat4>,
  mats: Vec<Transformation>,
  strings: Vec<(String, f32, f32, Color, Transformation)>,
  lines: Vec<(i32, i32, i32, i32, Color, Transformation)>,
}

impl<'a, 'b, 'c> Graphics<'a, 'b, 'c> {
  pub fn new(facade: &'a dyn Facade, surface: &'a mut AnySurface<'b>, fr: &'a dyn FontRenderer, sm: &'a mut ShaderManager<'c>, perspective: Mat4) -> Self {
    Graphics { facade, surface, fr, sm, perspective, mats: vec![Mat4::identity()] }
  pub fn new(facade: &'a dyn Facade, surface: &'a mut AnySurface<'b>, fr: &'a BakedFont<'a>, sm: &'a mut ShaderManager<'c>, perspective: Mat4) -> Self {
    Graphics {
      facade,
      surface,
      fr,
      sm,
      perspective,
      mats: vec![Transformation::Identity],
      strings: vec![],
      lines: vec![],
    }
  }

  pub fn surface(&self) -> &AnySurface<'b> { self.surface }


@@ 30,19 43,17 @@ impl<'a, 'b, 'c> Graphics<'a, 'b, 'c> {

  pub fn perspective(&self) -> &Mat4 { &self.perspective }

  pub fn modelview(&self) -> &Mat4 { self.mats.last().unwrap() }

  pub fn mvp(&self) -> Mat4 { *self.perspective() * *self.modelview() }
  pub fn modelview(&self) -> &Transformation { self.mats.last().unwrap() }

  pub fn modelview_mut(&mut self) -> &mut Mat4 { self.mats.last_mut().unwrap() }
  pub fn mvp(&self) -> Mat4 { *self.perspective() * self.modelview().as_matrix() }

  pub fn transform(&mut self, mat: Mat4) {
    let m = self.modelview_mut();
    *m *= mat;
  pub fn transform(&mut self, tr: Transformation) {
    let m = self.mats.last_mut().unwrap();
    *m = m.combine(tr);
  }

  pub fn translatef(&mut self, x: f32, y: f32, z: f32) {
    self.transform(Mat4::get_translation(vec3(x, y, z)));
    self.transform(Transformation::Translation(x, y, z));
  }

  pub fn translatei(&mut self, x: i32, y: i32, z: i32) {


@@ 50,35 61,31 @@ impl<'a, 'b, 'c> Graphics<'a, 'b, 'c> {
  }

  pub fn draw_string(&mut self, t: &str, x: i32, y: i32, props: StringDrawProps) {
    match props.alignment {
      Alignment::Left => {
        self.fr.draw_string(self.surface, &self.mvp(), t, x as f32, y as f32, props.color);
      }
    let (x, y) = match props.alignment {
      Alignment::Left => (x as f32, y as f32),
      Alignment::Center => {
        let width = self.fr.get_str_width(t);
        self.fr.draw_string(self.surface, &self.mvp(), t, x as f32 - width / 2.0, y as f32, props.color);
        (x as f32 - width / 2.0, y as f32)
      }
      Alignment::Right => {
        let width = self.fr.get_str_width(t);
        self.fr.draw_string(self.surface, &self.mvp(), t, x as f32 - width, y as f32, props.color);
        (x as f32 - width, y as f32)
      }
    };

    self.strings.push((t.to_owned(), x as f32, y as f32, props.color, *self.modelview()));
  }

  pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: Color) {
    self.lines.push((x1, y1, x2, y2, color, *self.modelview()));
  }

  pub fn draw_polygon(&mut self, coords: &[[i32; 2]], color: Color) {
    let data = coords.iter().map(|&xy| PolygonPoint { xy }).collect::<Vec<_>>();
    let vb = VertexBuffer::new(self.facade, &data).unwrap();
    let mut dp = DrawParameters::default();
    dp.line_width = Some(1.0);
    let mvp = *self.mvp().as_ref();
    self.surface.draw(
      &vb,
      NoIndices(PrimitiveType::LineLoop),
      &self.sm.get("shader/uipoly.sdef").unwrap(),
      &UniformsStorage::new("mvp", mvp)
        .add("color", color.into_array()),
      &dp,
    ).unwrap();
    let v: Vec<_> = coords.iter()
      .zip(coords.iter().skip(1).chain(coords.iter().take(1)))
      .map(|(&a, &b)| (a, b))
      .collect();
    v.into_iter().for_each(|([x, y], [x1, y1])| self.draw_line(x, y, x1, y1, color));
  }

  pub fn draw_rect(&mut self, x: i32, y: i32, width: i32, height: i32, color: Color) {


@@ 96,13 103,59 @@ impl<'a, 'b, 'c> Graphics<'a, 'b, 'c> {
    self.mats.pop();
    result
  }
}

implement_vertex!(PolygonPoint, xy);
  pub fn flush(&mut self) {
    {
      let fr = self.fr;
      let data = self.strings
        .drain_filter(|(.., e)| e.try_as_translation().is_some())
        .map(|(a, b, c, d, e)| fr.create_data(&[(&a, b, c, d)]).translate(e.try_as_translation().unwrap()))
        .fold1(|a, b| a.combine(b))
        .map(|a| a.update_vbuf())
        .into_iter().for_each(|b| b.draw(self.surface, &self.perspective));

      for (a, b, c, d, e) in self.strings.drain(..) {
        self.fr.draw_string(self.surface, &(self.perspective * e.as_matrix()), &a, b, c, d);
      }
    }

#[derive(Copy, Clone)]
struct PolygonPoint {
  xy: [i32; 2],
    {
      implement_vertex!(PolygonPoint, xyz, color);

      #[derive(Copy, Clone)]
      struct PolygonPoint {
        xyz: [f32; 3],
        color: [f32; 4],
      }

      let mut data = vec![];
      for (x, y, x1, y1, color, tr) in self.lines.drain(..) {
        data.push(PolygonPoint { xyz: *tr.transform_vec3(vec3(x as f32, y as f32, 0.0)).as_ref(), color: color.into_array() });
        data.push(PolygonPoint { xyz: *tr.transform_vec3(vec3(x1 as f32, y1 as f32, 0.0)).as_ref(), color: color.into_array() });
      };

      let vb = VertexBuffer::new(self.facade, &data).unwrap();
      let mut dp = DrawParameters::default();
      dp.line_width = Some(1.0);
      dp.depth.test = DepthTest::IfLessOrEqual;
      dp.depth.write = true;

      let perspective = *self.perspective.as_ref();
      self.surface.draw(
        &vb,
        NoIndices(PrimitiveType::LinesList),
        &self.sm.get("shader/uipoly.sdef").unwrap(),
        &UniformsStorage::new("mvp", perspective),
        &dp,
      ).unwrap();
    }
  }
}

impl Drop for Graphics<'_, '_, '_> {
  fn drop(&mut self) {
    self.flush();
  }
}

#[derive(Clone, Copy, Debug)]


@@ 141,4 194,48 @@ pub enum Alignment {

impl Default for Alignment {
  fn default() -> Self { Alignment::Left }
}

#[derive(Clone, Copy, Debug)]
pub enum Transformation {
  Identity,
  Translation(f32, f32, f32),
  Matrix(Mat4),
}

impl Transformation {
  pub fn combine(self, other: Self) -> Transformation {
    use Transformation::*;
    match (self, other) {
      (Identity, Identity) => Identity,
      (Identity, x @ Translation(_, _, _)) |
      (x @ Translation(_, _, _), Identity) => x,
      (Translation(x, y, z), Translation(x1, y1, z1)) => Translation(x + x1, y + y1, z + z1),
      (a, b) => Matrix(a.as_matrix() * b.as_matrix()),
    }
  }

  pub fn transform_vec3(&self, vec: Vec3) -> Vec3 {
    match *self {
      Transformation::Identity => vec,
      Transformation::Translation(x, y, z) => vec + vec3(x, y, z),
      Transformation::Matrix(m) => m * vec,
    }
  }

  pub fn as_matrix(&self) -> Mat4 {
    match *self {
      Transformation::Identity => Mat4::identity(),
      Transformation::Translation(x, y, z) => Mat4::get_translation(vec3(x, y, z)),
      Transformation::Matrix(m) => m,
    }
  }

  pub fn try_as_translation(&self) -> Option<Vec3> {
    match *self {
      Transformation::Identity => Some(vec3(0.0, 0.0, 0.0)),
      Transformation::Translation(x, y, z) => Some(vec3(x, y, z)),
      Transformation::Matrix(_) => None,
    }
  }
}
\ No newline at end of file

M src/ui/layout/border.rs => src/ui/layout/border.rs +17 -35
@@ 1,8 1,9 @@
use std::cmp::max;

use crate::ui::layout::{LayoutElement, LayoutManager};
use crate::ui::layout::util::fill;
use crate::ui::layout::util::layout_stack;
use crate::ui::rescap::ResizeCapabilities;
use crate::util::single::Single;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Position {


@@ 35,7 36,8 @@ impl LayoutManager for BorderLayout {
  fn relayout(&self, elements: &mut [LayoutElement<Self::Data>], width: u32, height: u32) {
    let joined = |p| elements.iter()
      .filter(|el| *el.layout_data == p)
      .fold(ResizeCapabilities::zero_size(), |acc, a| acc.combine(a.caps()));
      .map(|el| el.caps())
      .single().or_none().unwrap_or(ResizeCapabilities::zero_size());

    let top_caps = joined(Position::Top);
    let bottom_caps = joined(Position::Bottom);


@@ 45,41 47,20 @@ impl LayoutManager for BorderLayout {
    let lcr_caps = left_caps.stack_right(center_caps).stack_right(right_caps);
    let full_caps = top_caps.stack_down(lcr_caps).stack_down(bottom_caps);

    let width = max(width, full_caps.min_width);
    let height = max(height, full_caps.min_height);
    let width = max(width, full_caps.min_width());
    let height = max(height, full_caps.min_height());

    let mut top_height = top_caps.min_height;
    let mut left_width = left_caps.min_width;
    let mut right_width = right_caps.min_width;
    let mut bottom_height = bottom_caps.min_height;
    let mut center_width = center_caps.min_width;
    let mut center_height = lcr_caps.min_height;
    let sizes = layout_stack(width, &[(left_caps, false), (center_caps, true), (right_caps, false)], false);

    // layout top-to-bottom
    {
      let extra = height - full_caps.min_height;
      let res = fill(extra, &[
        top_caps.preferred_height.map(|a| a - top_caps.min_height),
        lcr_caps.preferred_height.map(|a| a - lcr_caps.min_height),
        bottom_caps.preferred_height.map(|a| a - bottom_caps.min_height),
      ]);
      top_height += res[0];
      center_height += res[1];
      bottom_height += res[2];
    }
    let left_width = sizes[0];
    let center_width = sizes[1];
    let right_width = sizes[2];

    // layout left-to-right
    {
      let extra = width - full_caps.min_width;
      let res = fill(extra, &[
        left_caps.preferred_width.map(|a| a - left_caps.min_width),
        center_caps.preferred_width.map(|a| a - center_caps.min_width),
        right_caps.preferred_width.map(|a| a - right_caps.min_width),
      ]);
      left_width += res[0];
      center_width += res[1];
      right_width += res[2];
    }
    let sizes = layout_stack(height, &[(top_caps, false), (center_caps, true), (bottom_caps, false)], true);

    let top_height = sizes[0];
    let center_height = sizes[1];
    let bottom_height = sizes[2];

    for el in elements {
      match el.layout_data {


@@ 120,7 101,8 @@ impl LayoutManager for BorderLayout {
  fn get_resize_capabilities(&self, elements: &[LayoutElement<Self::Data>]) -> ResizeCapabilities {
    let joined = |p| elements.iter()
      .filter(|el| *el.layout_data == p)
      .fold(ResizeCapabilities::zero_size(), |acc, a| acc.combine(a.caps()));
      .map(|el| el.caps())
      .single().or_none().unwrap_or(ResizeCapabilities::zero_size());

    let top_caps = joined(Position::Top);
    let bottom_caps = joined(Position::Bottom);

M src/ui/layout/util.rs => src/ui/layout/util.rs +24 -4
@@ 1,3 1,5 @@
use crate::ui::rescap::ResizeCapabilities;

pub fn fill(mut amount: u32, sizes: &[Option<u32>]) -> Vec<u32> {
  let mut result = vec![0; sizes.len()];
  let mut candidates = (0..sizes.len()).collect::<Vec<_>>();


@@ 13,12 15,30 @@ pub fn fill(mut amount: u32, sizes: &[Option<u32>]) -> Vec<u32> {
        candidates.retain(|&j| j != i);
      }
      _ => {
        let rest = if count == 1 { 0 } else { amount / (count) };
        let first = amount - rest * (count - 1);
        candidates.iter().skip(1).for_each(|&i| result[i] += rest);
        result[*candidates.first().unwrap()] += first;
        if count>0 {
          let rest = if count == 1 { 0 } else { amount / count };
          let first = amount - rest * (count - 1);
          candidates.iter().skip(1).for_each(|&i| result[i] += rest);
          result[*candidates.first().unwrap()] += first;
        }
        break result;
      }
    }
  }
}

pub fn layout_stack(length: u32, rescaps: &[(ResizeCapabilities, bool)], height: bool) -> Vec<u32> {
  let min = |rc: &ResizeCapabilities| if height { rc.min_height() } else { rc.min_width() };
  let pref = |rc: &ResizeCapabilities| if height { rc.preferred_height() } else { rc.preferred_width() };
  let max = |rc: &ResizeCapabilities| if height { rc.max_height } else { rc.max_width };

  let mut sizes: Vec<u32> = rescaps.iter().map(|(el, _)| min(el)).collect();

  let grow = fill(length - sizes.iter().sum::<u32>(), &rescaps.iter()
    .map(|(a, b)| if *b { max(a) } else { Some(pref(a)) }.map(|x| x - min(a)))
    .collect::<Vec<_>>());

  sizes.iter_mut().zip(grow.into_iter()).for_each(|(a, b)| *a += b);

  sizes
}
\ No newline at end of file

M src/ui/rescap.rs => src/ui/rescap.rs +74 -19
@@ 2,19 2,35 @@ use std::cmp::{max, min};

#[derive(Default, Copy, Clone, Debug)]
pub struct ResizeCapabilities {
  pub min_width: u32,
  pub min_height: u32,
  pub min_width: Option<u32>,
  pub min_height: Option<u32>,
  pub preferred_width: Option<u32>,
  pub preferred_height: Option<u32>,
  pub max_width: Option<u32>,
  pub max_height: Option<u32>,
}

impl ResizeCapabilities {
  pub const fn new(min_width: u32, min_height: u32, preferred_width: Option<u32>, preferred_height: Option<u32>) -> Self {
    ResizeCapabilities { min_width, min_height, preferred_width, preferred_height }
  pub const fn new(
    min_width: Option<u32>,
    min_height: Option<u32>,
    preferred_width: Option<u32>,
    preferred_height: Option<u32>,
    max_width: Option<u32>,
    max_height: Option<u32>,
  ) -> Self {
    ResizeCapabilities {
      min_width,
      min_height,
      preferred_width,
      preferred_height,
      max_width,
      max_height,
    }
  }

  pub const fn zero_size() -> Self {
    Self::new(0, 0, Some(0), Some(0))
    Self::new(None, None, None, None, None, None)
  }

  pub fn combine(mut self, other: Self) -> Self {


@@ 22,42 38,66 @@ impl ResizeCapabilities {
    self.min_height = max(self.min_height, other.min_height);
    self.preferred_width = longer_of(self.preferred_width, other.preferred_width, self.min_width);
    self.preferred_height = longer_of(self.preferred_height, other.preferred_height, self.min_height);
    self.max_width = shorter_of(self.max_width, other.max_width, self.min_width);
    self.max_height = shorter_of(self.max_height, other.max_height, self.min_height);
    self
  }

  pub fn min_width(&self) -> u32 { self.min_width.unwrap_or(0) }

  pub fn min_height(&self) -> u32 { self.min_height.unwrap_or(0) }

  pub fn preferred_width(&self) -> u32 { self.preferred_width.unwrap_or_else(|| self.min_width()) }

  pub fn preferred_height(&self) -> u32 { self.preferred_height.unwrap_or_else(|| self.min_height()) }

  pub fn stack_right(mut self, other: Self) -> Self {
    let min_height = max(self.min_height, other.min_height);
    let min_height = longer_of_to0(self.min_height, other.min_height);
    ResizeCapabilities {
      min_width: self.min_width + other.min_width,
      min_width: combined_to0(self.min_width, other.min_width),
      min_height,
      preferred_width: combined(self.preferred_width, other.preferred_width),
      preferred_height: longer_of(self.preferred_height, other.preferred_height, min_height),
      preferred_height: same_or_none(self.preferred_height, other.preferred_height),
      max_width: combined(self.max_width, other.max_width),
      max_height: shorter_of(self.max_height, other.max_height, min_height),
    }
  }

  pub fn stack_down(mut self, other: Self) -> Self {
    let min_width = max(self.min_width, other.min_width);
    let min_width = longer_of_to0(self.min_width, other.min_width);
    ResizeCapabilities {
      min_width,
      min_height: self.min_height + other.min_height,
      preferred_width: longer_of(self.preferred_width, other.preferred_width, min_width),
      min_height: combined_to0(self.min_height, other.min_height),
      preferred_width: same_or_none(self.preferred_width, other.preferred_width),
      preferred_height: combined(self.preferred_height, other.preferred_height),
      max_width: shorter_of(self.max_width, other.max_width, min_width),
      max_height: combined(self.max_height, other.max_height),
    }
  }
}

fn shorter_of(a: Option<u32>, b: Option<u32>, lower_limit: u32) -> Option<u32> {
  match (a, b) {
    (Some(x), None) => Some(max(x, lower_limit)),
    (None, Some(x)) => Some(max(x, lower_limit)),
    (Some(a), Some(b)) => Some(max(min(a, b), lower_limit)),
    (None, None) => None,
fn shorter_of(a: Option<u32>, b: Option<u32>, lower_limit: Option<u32>) -> Option<u32> {
  match (a, b, lower_limit) {
    (Some(x), None, Some(lower_limit)) | (None, Some(x), Some(lower_limit)) => Some(max(x, lower_limit)),
    (Some(a), Some(b), Some(lower_limit)) => Some(max(min(a, b), lower_limit)),
    (x@Some(_), None, None) | (None, x@Some(_), None) => x,
    (Some(a), Some(b), None) | (Some(a), Some(b), None) => Some(min(a, b)),
    (None, None, x) => x,
  }
}

fn longer_of(a: Option<u32>, b: Option<u32>, lower_limit: u32) -> Option<u32> {
fn longer_of(a: Option<u32>, b: Option<u32>, lower_limit: Option<u32>) -> Option<u32> {
  match (a, b, lower_limit) {
    (Some(a), Some(b), Some(lower_limit)) => Some(max(max(a, b), lower_limit)),
    (Some(a), Some(b), None) => Some(max(a, b)),
    _ => None,
  }
}

fn longer_of_to0(a: Option<u32>, b: Option<u32>) -> Option<u32> {
  match (a, b) {
    (Some(a), Some(b)) => Some(max(max(a, b), lower_limit)),
    (Some(a), Some(b)) => Some(max(a, b)),
    (x @ Some(_), None) | (None, x @ Some(_)) => x,
    _ => None,
  }
}


@@ 68,3 108,18 @@ fn combined(a: Option<u32>, b: Option<u32>) -> Option<u32> {
    _ => None,
  }
}

fn combined_to0(a: Option<u32>, b: Option<u32>) -> Option<u32> {
  match (a, b) {
    (Some(a), Some(b)) => Some(a + b),
    (x @ Some(_), None) | (None, x @ Some(_)) => x,
    _ => None,
  }
}

fn same_or_none(a: Option<u32>, b: Option<u32>) -> Option<u32> {
  match (a, b) {
    (x @ Some(_), y @ Some(_)) if x == y => x,
    _ => None,
  }
}
\ No newline at end of file

M src/util/mod.rs => src/util/mod.rs +1 -0
@@ 11,3 11,4 @@ mod logpipe;
mod math;
mod multiwrite;
mod rectmap;
pub mod single;
\ No newline at end of file

A src/util/single.rs => src/util/single.rs +63 -0
@@ 0,0 1,63 @@
use std::fmt::Debug;

pub trait Single<T> {
  fn single(self) -> SingleResult<T>;
}

impl<T, Item> Single<Item> for T where T: Iterator<Item=Item> {
  fn single(self) -> SingleResult<Item> {
    self.fold(SingleResult::None, |acc, a| match acc {
      SingleResult::None => SingleResult::Some(a),
      SingleResult::Some(_) => SingleResult::More(2),
      SingleResult::More(count) => SingleResult::More(count + 1),
    })
  }
}

#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum SingleResult<T> {
  None,
  Some(T),
  More(usize),
}

impl <T: Debug> SingleResult<T> {
  pub fn unwrap(self) -> T {
    match self {
      SingleResult::Some(t) => t,
      _ => panic!("called `SingleResult::unwrap()` on a `{:?}` value", self),
    }
  }
}

impl <T> SingleResult<T> {
  pub fn into_option(self) -> Option<T> {
    match self {
      SingleResult::Some(s) => Some(s),
      _ => None,
    }
  }

  pub fn expect(self, msg: &str) -> T {
    match self {
      SingleResult::Some(t) => t,
      _ => panic!("{}", msg),
    }
  }

  pub fn or_none(self) -> Option<T> {
    match self {
      SingleResult::None => None,
      SingleResult::Some(t) => Some(t),
      SingleResult::More(count) => panic!("called `SingleResult::or_none()` on a `More({})` value", count),
    }
  }

  pub fn expect_or_none(self, msg: &str) -> Option<T> {
    match self {
      SingleResult::None => None,
      SingleResult::Some(t) => Some(t),
      SingleResult::More(_) => panic!("{}", msg),
    }
  }
}
\ No newline at end of file