diff --git a/.gitignore b/.gitignore
index 86a5eac79fb698d2caa8925e09dd17d638339c45..5e3b73d65d3f0d98014dfcbc827172021fc44080 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,6 @@ msdfgen
 
 .idea
 
-.DS_Store
\ No newline at end of file
+.DS_Store
+
+Cargo.lock
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index 07e9a91959a4ec5aeb54a9e061252368272a05ad..0000000000000000000000000000000000000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,3466 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "ab_glyph"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c"
-dependencies = [
- "ab_glyph_rasterizer",
- "owned_ttf_parser",
-]
-
-[[package]]
-name = "ab_glyph_rasterizer"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e"
-
-[[package]]
-name = "adler32"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
-
-[[package]]
-name = "ahash"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
-dependencies = [
- "getrandom",
- "once_cell",
- "version_check",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "alsa"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b"
-dependencies = [
- "alsa-sys",
- "bitflags",
- "libc",
- "nix",
-]
-
-[[package]]
-name = "alsa-sys"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
-dependencies = [
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "android_log-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
-
-[[package]]
-name = "android_logger"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66"
-dependencies = [
- "android_log-sys",
- "env_logger",
- "lazy_static",
- "log",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
-
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.56"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
-
-[[package]]
-name = "approx"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "arrayvec"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
-
-[[package]]
-name = "as-any"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "088ccb346677e658e7ccd9627c62576fba881f4db7fab71fa9e21bf31c0aa4cb"
-
-[[package]]
-name = "ash"
-version = "0.34.0+1.2.203"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df"
-dependencies = [
- "libloading",
-]
-
-[[package]]
-name = "async-channel"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
-dependencies = [
- "concurrent-queue",
- "event-listener",
- "futures-core",
-]
-
-[[package]]
-name = "async-executor"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
-dependencies = [
- "async-task",
- "concurrent-queue",
- "fastrand",
- "futures-lite",
- "once_cell",
- "slab",
-]
-
-[[package]]
-name = "async-task"
-version = "4.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "base-x"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
-
-[[package]]
-name = "base64"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
-
-[[package]]
-name = "bevy"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fce306d40a111309ee61d4626efbafccdd46bb80657122c38061fa7264c08e4"
-dependencies = [
- "bevy_internal",
-]
-
-[[package]]
-name = "bevy-crevice-derive"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "191a752a01c3402deb24320acf42288bf822e5d22f19ae1d903797f02e9b0c33"
-dependencies = [
- "bevy_macro_utils",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "bevy_animation"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c087569c34b168dd988e8b3409ce273661b4a58c3c534d0e381950589f59f68e"
-dependencies = [
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_ecs",
- "bevy_hierarchy",
- "bevy_math",
- "bevy_reflect",
- "bevy_transform",
- "bevy_utils",
-]
-
-[[package]]
-name = "bevy_app"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32660ae99fa3498ca379de28b7e2f447e6531b0e432bf200901efeec075553c1"
-dependencies = [
- "bevy_derive",
- "bevy_ecs",
- "bevy_reflect",
- "bevy_utils",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "bevy_asset"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2afd395240087924ba49c8cae2b00d007aeb1db53ee726a543b1e90dce2d3ab"
-dependencies = [
- "anyhow",
- "bevy_app",
- "bevy_diagnostic",
- "bevy_ecs",
- "bevy_log",
- "bevy_reflect",
- "bevy_tasks",
- "bevy_utils",
- "crossbeam-channel",
- "downcast-rs",
- "js-sys",
- "ndk-glue 0.5.1",
- "notify",
- "parking_lot",
- "rand",
- "serde",
- "thiserror",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
-]
-
-[[package]]
-name = "bevy_audio"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73a1c827ae837b62868539040176fb6d4daecf24983b98a0284d158e52cd21d5"
-dependencies = [
- "anyhow",
- "bevy_app",
- "bevy_asset",
- "bevy_ecs",
- "bevy_reflect",
- "bevy_utils",
- "parking_lot",
- "rodio",
-]
-
-[[package]]
-name = "bevy_core"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12c0f8614b6014671ab60bacb8bf681373d08b0bb15633b8ef72b895cf966d29"
-dependencies = [
- "bevy_app",
- "bevy_derive",
- "bevy_ecs",
- "bevy_math",
- "bevy_reflect",
- "bevy_tasks",
- "bevy_utils",
- "bytemuck",
-]
-
-[[package]]
-name = "bevy_core_pipeline"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74d570bc9310196190910a5b1ffd8c8c35bd6b73f918d0651ae3c3d4e57be9a7"
-dependencies = [
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_ecs",
- "bevy_render",
- "bevy_utils",
-]
-
-[[package]]
-name = "bevy_crevice"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3da0a284fb26c02cb96ef4d5bbf4de5fad7e1a901730035a61813bf64e28482e"
-dependencies = [
- "bevy-crevice-derive",
- "bytemuck",
- "glam",
- "mint",
-]
-
-[[package]]
-name = "bevy_derive"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6abddf2ed415f31d28a9bf9ab3c0bc857e98a722858d38dba65bdda481f8d714"
-dependencies = [
- "bevy_macro_utils",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "bevy_diagnostic"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ebf72ea058cfc379756e9da7de6861174e1860504f41e3e5a46d5b1c35d6644"
-dependencies = [
- "bevy_app",
- "bevy_core",
- "bevy_ecs",
- "bevy_log",
- "bevy_utils",
-]
-
-[[package]]
-name = "bevy_ecs"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e67dd06b14e787d2026fe6e2b63f67482afcc62284f20ea2784d8b0662e95f"
-dependencies = [
- "async-channel",
- "bevy_ecs_macros",
- "bevy_reflect",
- "bevy_tasks",
- "bevy_utils",
- "downcast-rs",
- "fixedbitset",
- "fxhash",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "bevy_ecs_macros"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "718923a491490bd81074492d61fc08134f9c62a29ba8666818cd7a6630421246"
-dependencies = [
- "bevy_macro_utils",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "bevy_gilrs"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15b164983e8057a1a730412a7c26ccc540d9ce76d2c6ab68edd258a0baeb1762"
-dependencies = [
- "bevy_app",
- "bevy_ecs",
- "bevy_input",
- "bevy_utils",
- "gilrs",
-]
-
-[[package]]
-name = "bevy_gltf"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e07bda7721091c1a683343d466132dc69dec65aa83d8c9e328a2fb3431f03be"
-dependencies = [
- "anyhow",
- "base64",
- "bevy_animation",
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_ecs",
- "bevy_hierarchy",
- "bevy_log",
- "bevy_math",
- "bevy_pbr",
- "bevy_reflect",
- "bevy_render",
- "bevy_scene",
- "bevy_transform",
- "bevy_utils",
- "gltf",
- "percent-encoding",
- "thiserror",
-]
-
-[[package]]
-name = "bevy_hierarchy"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f407f152f35541a099484200afe3b0ca09ce625469e8233dcdc264d6f88e01a"
-dependencies = [
- "bevy_app",
- "bevy_ecs",
- "bevy_reflect",
- "bevy_utils",
- "smallvec",
-]
-
-[[package]]
-name = "bevy_input"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff4ec4f6e38ef1b41ff68ec7badd6afc5c9699191e61e511c4abee91a5888afc"
-dependencies = [
- "bevy_app",
- "bevy_ecs",
- "bevy_math",
- "bevy_utils",
-]
-
-[[package]]
-name = "bevy_internal"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d518a8e5f526a9537fc8408a284caec7af22b23c3b23c0dee08bacc0930e2f1a"
-dependencies = [
- "bevy_animation",
- "bevy_app",
- "bevy_asset",
- "bevy_audio",
- "bevy_core",
- "bevy_core_pipeline",
- "bevy_derive",
- "bevy_diagnostic",
- "bevy_ecs",
- "bevy_gilrs",
- "bevy_gltf",
- "bevy_hierarchy",
- "bevy_input",
- "bevy_log",
- "bevy_math",
- "bevy_pbr",
- "bevy_reflect",
- "bevy_render",
- "bevy_scene",
- "bevy_sprite",
- "bevy_tasks",
- "bevy_text",
- "bevy_transform",
- "bevy_ui",
- "bevy_utils",
- "bevy_window",
- "bevy_winit",
- "ndk-glue 0.5.1",
-]
-
-[[package]]
-name = "bevy_kayak_renderer"
-version = "0.0.1"
-dependencies = [
- "bevy",
- "bytemuck",
- "kayak_font",
- "serde",
- "serde_json",
- "serde_path_to_error",
-]
-
-[[package]]
-name = "bevy_kayak_ui"
-version = "0.0.1"
-dependencies = [
- "bevy",
- "bevy_kayak_renderer",
- "bytemuck",
- "kayak_core",
- "kayak_font",
- "serde",
- "serde_json",
- "serde_path_to_error",
-]
-
-[[package]]
-name = "bevy_log"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "943ec496720ded2ff62b292d8e5fc845817a504915f41b7c5fd12b1380300f75"
-dependencies = [
- "android_log-sys",
- "bevy_app",
- "bevy_utils",
- "console_error_panic_hook",
- "tracing-log",
- "tracing-subscriber",
- "tracing-wasm",
-]
-
-[[package]]
-name = "bevy_macro_utils"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7ddfc33a99547e36718e56e414541e461c74ec318ff987a1e9f4ff46d0dacbb"
-dependencies = [
- "cargo-manifest",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "bevy_math"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20288df0f70ff258bbaffaf55209f1271a7436438591bbffc3d81e4d84b423f2"
-dependencies = [
- "bevy_reflect",
- "glam",
-]
-
-[[package]]
-name = "bevy_pbr"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06adee54840f18cfeda7af4cdc57608644fa840be076a562353f896bfdb9c694"
-dependencies = [
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_core_pipeline",
- "bevy_ecs",
- "bevy_math",
- "bevy_reflect",
- "bevy_render",
- "bevy_transform",
- "bevy_utils",
- "bevy_window",
- "bitflags",
- "bytemuck",
-]
-
-[[package]]
-name = "bevy_reflect"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d0793107bc4b7c6bd04232d739fc8d70aa5fb313bfad6e850f91f79b2557eed"
-dependencies = [
- "bevy_reflect_derive",
- "bevy_utils",
- "downcast-rs",
- "erased-serde",
- "glam",
- "parking_lot",
- "serde",
- "smallvec",
- "thiserror",
-]
-
-[[package]]
-name = "bevy_reflect_derive"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81c88de8067d19dfde31662ee78e3ee6971e2df27715799f91b515b37a636677"
-dependencies = [
- "bevy_macro_utils",
- "proc-macro2",
- "quote",
- "syn",
- "uuid",
-]
-
-[[package]]
-name = "bevy_render"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a358da8255b704153913c3499b3693fa5cfe13a48725ac6e76b043fa5633bc8"
-dependencies = [
- "anyhow",
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_crevice",
- "bevy_derive",
- "bevy_ecs",
- "bevy_math",
- "bevy_reflect",
- "bevy_transform",
- "bevy_utils",
- "bevy_window",
- "bitflags",
- "codespan-reporting",
- "copyless",
- "downcast-rs",
- "futures-lite",
- "hex",
- "hexasphere",
- "image",
- "naga",
- "once_cell",
- "parking_lot",
- "regex",
- "serde",
- "smallvec",
- "thiserror",
- "wgpu",
-]
-
-[[package]]
-name = "bevy_scene"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ea240f2ffce9f58a5601cc5ead24111f577dc4c656452839eb1fdf4b7a28529"
-dependencies = [
- "anyhow",
- "bevy_app",
- "bevy_asset",
- "bevy_ecs",
- "bevy_hierarchy",
- "bevy_reflect",
- "bevy_utils",
- "ron",
- "serde",
- "thiserror",
- "uuid",
-]
-
-[[package]]
-name = "bevy_sprite"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fcecfbc623410137d85a71a295ff7c16604b7be24529c9ea4b9a9881d7a142b"
-dependencies = [
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_core_pipeline",
- "bevy_ecs",
- "bevy_log",
- "bevy_math",
- "bevy_reflect",
- "bevy_render",
- "bevy_transform",
- "bevy_utils",
- "bitflags",
- "bytemuck",
- "copyless",
- "guillotiere",
- "rectangle-pack",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "bevy_tasks"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2b0f0b86c8f78c53a2d4c669522f45e725ed9d9c3d734f54ec30876494e04e"
-dependencies = [
- "async-channel",
- "async-executor",
- "event-listener",
- "futures-lite",
- "num_cpus",
- "wasm-bindgen-futures",
-]
-
-[[package]]
-name = "bevy_text"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a206112de011fd6baebaf476af69d87f4e38a1314b65e3c872060830d7c0b9fa"
-dependencies = [
- "ab_glyph",
- "anyhow",
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_ecs",
- "bevy_math",
- "bevy_reflect",
- "bevy_render",
- "bevy_sprite",
- "bevy_transform",
- "bevy_utils",
- "bevy_window",
- "glyph_brush_layout",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "bevy_transform"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2f7a77900fb23f24ca312c1f8df3eb47a45161326f41e9b4ef05b039793503"
-dependencies = [
- "bevy_app",
- "bevy_ecs",
- "bevy_hierarchy",
- "bevy_math",
- "bevy_reflect",
-]
-
-[[package]]
-name = "bevy_ui"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c65e79658d8a3d4da087a6fb8b229cfe1455cda2c4e8e6305b3b44fb46fb1d30"
-dependencies = [
- "bevy_app",
- "bevy_asset",
- "bevy_core",
- "bevy_core_pipeline",
- "bevy_derive",
- "bevy_ecs",
- "bevy_hierarchy",
- "bevy_input",
- "bevy_log",
- "bevy_math",
- "bevy_reflect",
- "bevy_render",
- "bevy_sprite",
- "bevy_text",
- "bevy_transform",
- "bevy_utils",
- "bevy_window",
- "bytemuck",
- "serde",
- "smallvec",
- "stretch",
-]
-
-[[package]]
-name = "bevy_utils"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f354c584812996febd48cc885f36b23004b49d6680e73fc95a69a2bb17a48e5"
-dependencies = [
- "ahash",
- "bevy_derive",
- "getrandom",
- "hashbrown",
- "instant",
- "tracing",
- "uuid",
-]
-
-[[package]]
-name = "bevy_window"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04fe33d177e10b2984fa90c1d19496fc6f6e7b36d4442699d359e2b4b507873d"
-dependencies = [
- "bevy_app",
- "bevy_ecs",
- "bevy_math",
- "bevy_utils",
- "raw-window-handle",
- "web-sys",
-]
-
-[[package]]
-name = "bevy_winit"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7c0e3b94cc73907f8a9f82945ca006a39ed2ab401aca0974b47a007a468509f"
-dependencies = [
- "approx",
- "bevy_app",
- "bevy_ecs",
- "bevy_input",
- "bevy_math",
- "bevy_utils",
- "bevy_window",
- "raw-window-handle",
- "wasm-bindgen",
- "web-sys",
- "winit",
-]
-
-[[package]]
-name = "bindgen"
-version = "0.56.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "lazy_static",
- "lazycell",
- "peeking_take_while",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
-]
-
-[[package]]
-name = "bit-set"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
-dependencies = [
- "bit-vec",
-]
-
-[[package]]
-name = "bit-vec"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "block"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-
-[[package]]
-name = "bumpalo"
-version = "3.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
-
-[[package]]
-name = "bytemuck"
-version = "1.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
-dependencies = [
- "bytemuck_derive",
-]
-
-[[package]]
-name = "bytemuck_derive"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "byteorder"
-version = "1.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
-
-[[package]]
-name = "bytes"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
-
-[[package]]
-name = "cache-padded"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
-
-[[package]]
-name = "cargo-manifest"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af6d65c7592744998c67947ec771c62687c76f00179a83ffd563c0482046bb98"
-dependencies = [
- "serde",
- "serde_derive",
- "toml",
-]
-
-[[package]]
-name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-dependencies = [
- "jobserver",
-]
-
-[[package]]
-name = "cesu8"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
-
-[[package]]
-name = "cexpr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
-
-[[package]]
-name = "clang-sys"
-version = "1.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "cocoa"
-version = "0.24.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
-dependencies = [
- "bitflags",
- "block",
- "cocoa-foundation",
- "core-foundation 0.9.3",
- "core-graphics 0.22.3",
- "foreign-types",
- "libc",
- "objc",
-]
-
-[[package]]
-name = "cocoa-foundation"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
-dependencies = [
- "bitflags",
- "block",
- "core-foundation 0.9.3",
- "core-graphics-types",
- "foreign-types",
- "libc",
- "objc",
-]
-
-[[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
-name = "color_quant"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
-
-[[package]]
-name = "combine"
-version = "4.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062"
-dependencies = [
- "bytes",
- "memchr",
-]
-
-[[package]]
-name = "concurrent-queue"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
-dependencies = [
- "cache-padded",
-]
-
-[[package]]
-name = "console_error_panic_hook"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
-dependencies = [
- "cfg-if 1.0.0",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "copyless"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
-
-[[package]]
-name = "core-foundation"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
-dependencies = [
- "core-foundation-sys 0.6.2",
- "libc",
-]
-
-[[package]]
-name = "core-foundation"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
-dependencies = [
- "core-foundation-sys 0.7.0",
- "libc",
-]
-
-[[package]]
-name = "core-foundation"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
-dependencies = [
- "core-foundation-sys 0.8.3",
- "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-foundation-sys"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
-
-[[package]]
-name = "core-graphics"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923"
-dependencies = [
- "bitflags",
- "core-foundation 0.7.0",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "core-graphics"
-version = "0.22.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
-dependencies = [
- "bitflags",
- "core-foundation 0.9.3",
- "core-graphics-types",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "core-graphics-types"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
-dependencies = [
- "bitflags",
- "core-foundation 0.9.3",
- "foreign-types",
- "libc",
-]
-
-[[package]]
-name = "core-video-sys"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828"
-dependencies = [
- "cfg-if 0.1.10",
- "core-foundation-sys 0.7.0",
- "core-graphics 0.19.2",
- "libc",
- "objc",
-]
-
-[[package]]
-name = "coreaudio-rs"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88"
-dependencies = [
- "bitflags",
- "coreaudio-sys",
-]
-
-[[package]]
-name = "coreaudio-sys"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b"
-dependencies = [
- "bindgen",
-]
-
-[[package]]
-name = "cpal"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116"
-dependencies = [
- "alsa",
- "core-foundation-sys 0.8.3",
- "coreaudio-rs",
- "jni",
- "js-sys",
- "lazy_static",
- "libc",
- "mach 0.3.2",
- "ndk 0.6.0",
- "ndk-glue 0.6.1",
- "nix",
- "oboe",
- "parking_lot",
- "stdweb 0.1.3",
- "thiserror",
- "wasm-bindgen",
- "web-sys",
- "winapi",
-]
-
-[[package]]
-name = "crc32fast"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
-dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
-dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
-dependencies = [
- "cfg-if 1.0.0",
- "lazy_static",
-]
-
-[[package]]
-name = "cty"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
-
-[[package]]
-name = "d3d12"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c"
-dependencies = [
- "bitflags",
- "libloading",
- "winapi",
-]
-
-[[package]]
-name = "darling"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "deflate"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
-dependencies = [
- "adler32",
- "byteorder",
-]
-
-[[package]]
-name = "desync"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5f27dcf5aa323a4d6fe62caa089e59f280445a5fa64734ffdbe4cdccf2d927a"
-dependencies = [
- "futures",
- "lazy_static",
- "num_cpus",
-]
-
-[[package]]
-name = "difference"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
-
-[[package]]
-name = "discard"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
-
-[[package]]
-name = "dispatch"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
-
-[[package]]
-name = "downcast-rs"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
-
-[[package]]
-name = "env_logger"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
-dependencies = [
- "log",
- "regex",
-]
-
-[[package]]
-name = "erased-serde"
-version = "0.3.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad132dd8d0d0b546348d7d86cb3191aad14b34e5f979781fc005c80d4ac67ffd"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "euclid"
-version = "0.22.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "event-listener"
-version = "2.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
-
-[[package]]
-name = "fastrand"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
-dependencies = [
- "instant",
-]
-
-[[package]]
-name = "filetime"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "redox_syscall",
- "winapi",
-]
-
-[[package]]
-name = "fixedbitset"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
-
-[[package]]
-name = "flo_rope"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "934e2de58fcae0ada41e86f12f49f169d2a0349ebd27fc4cfb3d3ba34db827be"
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[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 = "fsevent-sys"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
-
-[[package]]
-name = "futures-lite"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
-dependencies = [
- "fastrand",
- "futures-core",
- "futures-io",
- "memchr",
- "parking",
- "pin-project-lite",
- "waker-fn",
-]
-
-[[package]]
-name = "futures-macro"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
-
-[[package]]
-name = "futures-task"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
-
-[[package]]
-name = "futures-util"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "fxhash"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
-dependencies = [
- "byteorder",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
-dependencies = [
- "cfg-if 1.0.0",
- "js-sys",
- "libc",
- "wasi 0.10.2+wasi-snapshot-preview1",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "gilrs"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1550c8bdebc993576e343d600a954654708a9a1182396ee1e805d6fe60c72909"
-dependencies = [
- "fnv",
- "gilrs-core",
- "log",
- "uuid",
- "vec_map",
-]
-
-[[package]]
-name = "gilrs-core"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c7262ce1e88429c9b1d847820c9d2ba00adafc955218393d9c0861d5aaab88"
-dependencies = [
- "core-foundation 0.6.4",
- "io-kit-sys",
- "js-sys",
- "libc",
- "libudev-sys",
- "log",
- "nix",
- "rusty-xinput",
- "stdweb 0.4.20",
- "uuid",
- "vec_map",
- "web-sys",
- "winapi",
-]
-
-[[package]]
-name = "glam"
-version = "0.20.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3412e74893a912839a67e975aca0c88561e20e5461d2d358a5fa6d3b229fae59"
-dependencies = [
- "bytemuck",
- "mint",
- "serde",
-]
-
-[[package]]
-name = "glob"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
-
-[[package]]
-name = "glow"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919"
-dependencies = [
- "js-sys",
- "slotmap",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "gltf"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00e0a0eace786193fc83644907097285396360e9e82e30f81a21e9b1ba836a3e"
-dependencies = [
- "byteorder",
- "gltf-json",
- "lazy_static",
-]
-
-[[package]]
-name = "gltf-derive"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdd53d6e284bb2bf02a6926e4cc4984978c1990914d6cd9deae4e31cf37cd113"
-dependencies = [
- "inflections",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "gltf-json"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9949836a9ec5e7f83f76fb9bbcbc77f254a577ebbdb0820867bc11979ef97cad"
-dependencies = [
- "gltf-derive",
- "serde",
- "serde_derive",
- "serde_json",
-]
-
-[[package]]
-name = "glyph_brush_layout"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38"
-dependencies = [
- "ab_glyph",
- "approx",
- "xi-unicode",
-]
-
-[[package]]
-name = "gpu-alloc"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d"
-dependencies = [
- "bitflags",
- "gpu-alloc-types",
-]
-
-[[package]]
-name = "gpu-alloc-types"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "gpu-descriptor"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda"
-dependencies = [
- "bitflags",
- "gpu-descriptor-types",
- "hashbrown",
-]
-
-[[package]]
-name = "gpu-descriptor-types"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "guillotiere"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782"
-dependencies = [
- "euclid",
- "svg_fmt",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
-dependencies = [
- "ahash",
- "serde",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "hexasphere"
-version = "7.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04ab9d20ba513ff1582a7d885e91839f62cf28bef7c56b1b0428ca787315979b"
-dependencies = [
- "glam",
- "lazy_static",
-]
-
-[[package]]
-name = "hexf-parse"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
-name = "image"
-version = "0.23.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
-dependencies = [
- "bytemuck",
- "byteorder",
- "color_quant",
- "num-iter",
- "num-rational",
- "num-traits",
- "png",
- "scoped_threadpool",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
-dependencies = [
- "autocfg",
- "hashbrown",
-]
-
-[[package]]
-name = "inflections"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"
-
-[[package]]
-name = "inotify"
-version = "0.9.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
-dependencies = [
- "bitflags",
- "inotify-sys",
- "libc",
-]
-
-[[package]]
-name = "inotify-sys"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "inplace_it"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca"
-
-[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if 1.0.0",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "io-kit-sys"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f21dcc74995dd4cd090b147e79789f8d65959cbfb5f0b118002db869ea3bd0a0"
-dependencies = [
- "core-foundation-sys 0.6.2",
- "mach 0.2.3",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
-
-[[package]]
-name = "jni"
-version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
-dependencies = [
- "cesu8",
- "combine",
- "jni-sys",
- "log",
- "thiserror",
- "walkdir",
-]
-
-[[package]]
-name = "jni-sys"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
-
-[[package]]
-name = "jobserver"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.56"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "kayak_core"
-version = "0.1.0"
-dependencies = [
- "as-any",
- "bevy",
- "desync",
- "flo_rope",
- "futures",
- "indexmap",
- "kayak_font",
- "kayak_render_macros",
- "morphorm",
- "resources",
- "uuid",
-]
-
-[[package]]
-name = "kayak_font"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "bevy",
- "bytemuck",
- "serde",
- "serde_json",
- "serde_path_to_error",
- "unicode-segmentation",
- "xi-unicode",
-]
-
-[[package]]
-name = "kayak_render_macros"
-version = "0.1.0"
-dependencies = [
- "kayak_core",
- "pretty_assertions",
- "proc-macro-crate",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "kayak_ui"
-version = "0.1.0"
-dependencies = [
- "bevy",
- "bevy_kayak_ui",
- "kayak_core",
- "kayak_font",
- "kayak_render_macros",
- "rand",
-]
-
-[[package]]
-name = "khronos-egl"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3"
-dependencies = [
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "kqueue"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "058a107a784f8be94c7d35c1300f4facced2e93d2fbe5b1452b44e905ddca4a9"
-dependencies = [
- "kqueue-sys",
- "libc",
-]
-
-[[package]]
-name = "kqueue-sys"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
-dependencies = [
- "bitflags",
- "libc",
-]
-
-[[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.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
-name = "lewton"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
-dependencies = [
- "byteorder",
- "ogg",
- "tinyvec",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.121"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
-
-[[package]]
-name = "libloading"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
-dependencies = [
- "cfg-if 1.0.0",
- "winapi",
-]
-
-[[package]]
-name = "libm"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
-
-[[package]]
-name = "libudev-sys"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
-dependencies = [
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "lock_api"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "log"
-version = "0.4.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
-dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "mach"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "mach"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "malloc_buf"
-version = "0.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "matchers"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
-dependencies = [
- "regex-automata",
-]
-
-[[package]]
-name = "memchr"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
-
-[[package]]
-name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "metal"
-version = "0.23.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084"
-dependencies = [
- "bitflags",
- "block",
- "core-graphics-types",
- "foreign-types",
- "log",
- "objc",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
-dependencies = [
- "adler32",
-]
-
-[[package]]
-name = "mint"
-version = "0.5.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
-
-[[package]]
-name = "mio"
-version = "0.7.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
-dependencies = [
- "libc",
- "log",
- "miow",
- "ntapi",
- "winapi",
-]
-
-[[package]]
-name = "mio"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
-dependencies = [
- "libc",
- "log",
- "miow",
- "ntapi",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "winapi",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "morphorm"
-version = "0.2.0"
-source = "git+https://github.com/geom3trik/morphorm?rev=1243152d4cebea46fd3e5098df26402c73acae91#1243152d4cebea46fd3e5098df26402c73acae91"
-dependencies = [
- "bitflags",
- "smallvec",
-]
-
-[[package]]
-name = "naga"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705"
-dependencies = [
- "bit-set",
- "bitflags",
- "codespan-reporting",
- "hexf-parse",
- "indexmap",
- "log",
- "num-traits",
- "petgraph",
- "pp-rs",
- "rustc-hash",
- "spirv",
- "thiserror",
-]
-
-[[package]]
-name = "ndk"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
-dependencies = [
- "bitflags",
- "jni-sys",
- "ndk-sys 0.2.2",
- "num_enum",
- "thiserror",
-]
-
-[[package]]
-name = "ndk"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4"
-dependencies = [
- "bitflags",
- "jni-sys",
- "ndk-sys 0.3.0",
- "num_enum",
- "thiserror",
-]
-
-[[package]]
-name = "ndk-context"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e3c5cc68637e21fe8f077f6a1c9e0b9ca495bb74895226b476310f613325884"
-
-[[package]]
-name = "ndk-glue"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1c68f70683c5fc9a747a383744206cd371741b2f0b31781ab6770487ec572e2"
-dependencies = [
- "android_logger",
- "lazy_static",
- "libc",
- "log",
- "ndk 0.5.0",
- "ndk-context",
- "ndk-macro",
- "ndk-sys 0.2.2",
-]
-
-[[package]]
-name = "ndk-glue"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9ffb7443daba48349d545028777ca98853b018b4c16624aa01223bc29e078da"
-dependencies = [
- "lazy_static",
- "libc",
- "log",
- "ndk 0.6.0",
- "ndk-context",
- "ndk-macro",
- "ndk-sys 0.3.0",
-]
-
-[[package]]
-name = "ndk-macro"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c"
-dependencies = [
- "darling",
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "ndk-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
-
-[[package]]
-name = "ndk-sys"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97"
-dependencies = [
- "jni-sys",
-]
-
-[[package]]
-name = "nix"
-version = "0.23.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if 1.0.0",
- "libc",
- "memoffset",
-]
-
-[[package]]
-name = "nom"
-version = "5.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
-dependencies = [
- "memchr",
- "version_check",
-]
-
-[[package]]
-name = "notify"
-version = "5.0.0-pre.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c614e7ed2b1cf82ec99aeffd8cf6225ef5021b9951148eb161393c394855032c"
-dependencies = [
- "bitflags",
- "crossbeam-channel",
- "filetime",
- "fsevent-sys",
- "inotify",
- "kqueue",
- "libc",
- "mio 0.7.14",
- "walkdir",
- "winapi",
-]
-
-[[package]]
-name = "ntapi"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "num-derive"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
-dependencies = [
- "autocfg",
- "num-traits",
-]
-
-[[package]]
-name = "num-iter"
-version = "0.1.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "num_enum"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
-dependencies = [
- "num_enum_derive",
-]
-
-[[package]]
-name = "num_enum_derive"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "objc"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
-dependencies = [
- "malloc_buf",
- "objc_exception",
-]
-
-[[package]]
-name = "objc_exception"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "oboe"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2"
-dependencies = [
- "jni",
- "ndk 0.6.0",
- "ndk-glue 0.6.1",
- "num-derive",
- "num-traits",
- "oboe-sys",
-]
-
-[[package]]
-name = "oboe-sys"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "ogg"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
-dependencies = [
- "byteorder",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
-
-[[package]]
-name = "owned_ttf_parser"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d"
-dependencies = [
- "ttf-parser",
-]
-
-[[package]]
-name = "parking"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
-
-[[package]]
-name = "parking_lot"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
-dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
-dependencies = [
- "cfg-if 1.0.0",
- "instant",
- "libc",
- "redox_syscall",
- "smallvec",
- "winapi",
-]
-
-[[package]]
-name = "peeking_take_while"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-
-[[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.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
-
-[[package]]
-name = "png"
-version = "0.16.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
-dependencies = [
- "bitflags",
- "crc32fast",
- "deflate",
- "miniz_oxide",
-]
-
-[[package]]
-name = "pp-rs"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
-
-[[package]]
-name = "pretty_assertions"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5dc44a7f8ba9e19aeb6f900eb518343170f2aae27d3c9c78e4d5c3db623638d"
-dependencies = [
- "ansi_term 0.9.0",
- "difference",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
-dependencies = [
- "thiserror",
- "toml",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "profiling"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987"
-
-[[package]]
-name = "quote"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "range-alloc"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6"
-
-[[package]]
-name = "raw-window-handle"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41"
-dependencies = [
- "cty",
-]
-
-[[package]]
-name = "rectangle-pack"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb"
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "regex"
-version = "1.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-dependencies = [
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "renderdoc-sys"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157"
-
-[[package]]
-name = "resources"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42070ea13709eb92d2977b48c7d3bd44866fa328e14248f8d1f00d6ea14d5066"
-dependencies = [
- "downcast-rs",
- "fxhash",
- "parking_lot",
-]
-
-[[package]]
-name = "rodio"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e"
-dependencies = [
- "cpal",
- "lewton",
-]
-
-[[package]]
-name = "ron"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678"
-dependencies = [
- "base64",
- "bitflags",
- "serde",
-]
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rusty-xinput"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2aa654bc32eb9ca14cce1a084abc9dfe43949a4547c35269a094c39272db3bb"
-dependencies = [
- "lazy_static",
- "log",
- "winapi",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "scoped_threadpool"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[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 = "serde"
-version = "1.0.136"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.136"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "serde_path_to_error"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7868ad3b8196a8a0aea99a8220b124278ee5320a55e4fde97794b6f85b1a377"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
-dependencies = [
- "sha1_smol",
-]
-
-[[package]]
-name = "sha1_smol"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
-
-[[package]]
-name = "sharded-slab"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "shlex"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
-
-[[package]]
-name = "slab"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
-
-[[package]]
-name = "slotmap"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342"
-dependencies = [
- "version_check",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "spirv"
-version = "0.2.0+1.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830"
-dependencies = [
- "bitflags",
- "num-traits",
-]
-
-[[package]]
-name = "stdweb"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
-
-[[package]]
-name = "stdweb"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
-dependencies = [
- "discard",
- "rustc_version",
- "serde",
- "serde_json",
- "stdweb-derive",
- "stdweb-internal-macros",
- "stdweb-internal-runtime",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "stdweb-derive"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-macros"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
-dependencies = [
- "base-x",
- "proc-macro2",
- "quote",
- "serde",
- "serde_derive",
- "serde_json",
- "sha1",
- "syn",
-]
-
-[[package]]
-name = "stdweb-internal-runtime"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
-
-[[package]]
-name = "stretch"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b0dc6d20ce137f302edf90f9cd3d278866fd7fb139efca6f246161222ad6d87"
-dependencies = [
- "lazy_static",
- "libm",
-]
-
-[[package]]
-name = "strsim"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-
-[[package]]
-name = "svg_fmt"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"
-
-[[package]]
-name = "syn"
-version = "1.0.91"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
-
-[[package]]
-name = "toml"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
-dependencies = [
- "indexmap",
- "serde",
-]
-
-[[package]]
-name = "tracing"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
-dependencies = [
- "cfg-if 1.0.0",
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee"
-dependencies = [
- "lazy_static",
- "valuable",
-]
-
-[[package]]
-name = "tracing-log"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
-dependencies = [
- "lazy_static",
- "log",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-subscriber"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9df98b037d039d03400d9dd06b0f8ce05486b5f25e9a2d7d36196e142ebbc52"
-dependencies = [
- "ansi_term 0.12.1",
- "lazy_static",
- "matchers",
- "regex",
- "sharded-slab",
- "smallvec",
- "thread_local",
- "tracing",
- "tracing-core",
- "tracing-log",
-]
-
-[[package]]
-name = "tracing-wasm"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07"
-dependencies = [
- "tracing",
- "tracing-subscriber",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "ttf-parser"
-version = "0.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c74c96594835e10fa545e2a51e8709f30b173a092bfd6036ef2cec53376244f3"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
-
-[[package]]
-name = "uuid"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
-dependencies = [
- "getrandom",
- "serde",
-]
-
-[[package]]
-name = "valuable"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "version_check"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "waker-fn"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
-
-[[package]]
-name = "walkdir"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
-dependencies = [
- "same-file",
- "winapi",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
-dependencies = [
- "cfg-if 1.0.0",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
-dependencies = [
- "cfg-if 1.0.0",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
-
-[[package]]
-name = "web-sys"
-version = "0.3.56"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "wgpu"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567"
-dependencies = [
- "arrayvec",
- "js-sys",
- "log",
- "naga",
- "parking_lot",
- "raw-window-handle",
- "smallvec",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "wgpu-core",
- "wgpu-hal",
- "wgpu-types",
-]
-
-[[package]]
-name = "wgpu-core"
-version = "0.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d"
-dependencies = [
- "arrayvec",
- "bitflags",
- "cfg_aliases",
- "codespan-reporting",
- "copyless",
- "fxhash",
- "log",
- "naga",
- "parking_lot",
- "profiling",
- "raw-window-handle",
- "smallvec",
- "thiserror",
- "wgpu-hal",
- "wgpu-types",
-]
-
-[[package]]
-name = "wgpu-hal"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93b1a9400e8d7f32dd4dd909bb9a391015d70633d639775ddd3f14d1104bc970"
-dependencies = [
- "arrayvec",
- "ash",
- "bit-set",
- "bitflags",
- "block",
- "core-graphics-types",
- "d3d12",
- "foreign-types",
- "fxhash",
- "glow",
- "gpu-alloc",
- "gpu-descriptor",
- "inplace_it",
- "js-sys",
- "khronos-egl",
- "libloading",
- "log",
- "metal",
- "naga",
- "objc",
- "parking_lot",
- "profiling",
- "range-alloc",
- "raw-window-handle",
- "renderdoc-sys",
- "thiserror",
- "wasm-bindgen",
- "web-sys",
- "wgpu-types",
- "winapi",
-]
-
-[[package]]
-name = "wgpu-types"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[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.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[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.26.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a"
-dependencies = [
- "bitflags",
- "cocoa",
- "core-foundation 0.9.3",
- "core-graphics 0.22.3",
- "core-video-sys",
- "dispatch",
- "instant",
- "lazy_static",
- "libc",
- "log",
- "mio 0.8.2",
- "ndk 0.5.0",
- "ndk-glue 0.5.1",
- "ndk-sys 0.2.2",
- "objc",
- "parking_lot",
- "percent-encoding",
- "raw-window-handle",
- "wasm-bindgen",
- "web-sys",
- "winapi",
- "x11-dl",
-]
-
-[[package]]
-name = "x11-dl"
-version = "2.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
-dependencies = [
- "lazy_static",
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "xi-unicode"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a"
diff --git a/Cargo.toml b/Cargo.toml
index c98100caffca573dda2bf18a12638316ec5ade93..6acc38013ba478a720f533a6c23da8f59fd1f700 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,15 +17,15 @@ bevy_renderer = [
 ]
 
 [dependencies]
-bevy = { version = "0.7.0", optional = true }
+bevy = { version = "0.8.0", optional = true, default-features = false }
 bevy_kayak_ui = { path = "bevy_kayak_ui", optional = true }
 kayak_core = { path = "kayak_core" }
 kayak_font = { path = "kayak_font" }
 kayak_render_macros = { path = "kayak_render_macros" }
 
 [dev-dependencies]
-bevy = { version = "0.7.0" }
-rand = { version = "0.8.4" }
+bevy = "0.8.0"
+rand = "0.8.4"
 
 [[example]]
 name = "todo"
diff --git a/README.md b/README.md
index 3a45cad3318d3d16776ee87a92e98dccb2280028..514a9ccf7bb1a6b1f307756029630dd20e67fe17 100644
--- a/README.md
+++ b/README.md
@@ -43,11 +43,11 @@ Kayak UI is in the very early stages of development. Important features are miss
 <img src="images/screen1.png" alt="Kayak UI" width="600" />
 
 ## Usage
-Use bevy 0.6!
+Use bevy 0.7!
 
 ```rust
 kayak_ui = { git="https://github.com/StarArawn/kayak_ui", rev="{INSERT_COMMIT_SHA_HERE}", features = ["bevy_renderer"] }
-bevy = "0.6.0"
+bevy = "0.7.0"
 ```
 
 ## Declarative
@@ -148,4 +148,4 @@ To generate a font run the following command:
 ```
 .\msdf-atlas-gen.exe -font .\font_name.ttf -type msdf -minsize 32 -format png -imageout font_name.png -json font_name.json
 ```
-Where font_name is the name of your font. You can play around with the different parameters that are provided but keep in mind that some of the font stuff is currently hardcoded and might result in graphical glitches if you change the settings too much. You should also try to use a decent size for the `minsize` parameter. The smaller the size the more artifacts will appear in the text.
\ No newline at end of file
+Where font_name is the name of your font. You can play around with the different parameters that are provided but keep in mind that some of the font stuff is currently hardcoded and might result in graphical glitches if you change the settings too much. You should also try to use a decent size for the `minsize` parameter. The smaller the size the more artifacts will appear in the text.
diff --git a/bevy_kayak_renderer/Cargo.toml b/bevy_kayak_renderer/Cargo.toml
index 1c96a65404d768a58d50dee0b6a486763786f54e..9dccd36424bba2bd1bc5206f8723c2ffbd8c1029 100644
--- a/bevy_kayak_renderer/Cargo.toml
+++ b/bevy_kayak_renderer/Cargo.toml
@@ -5,8 +5,16 @@ edition = "2021"
 
 [dependencies]
 bytemuck = "1.7.2"
-bevy = { version = "0.7.0" }
 kayak_font = { path = "../kayak_font" }
 serde = "1.0"
 serde_json = "1.0"
 serde_path_to_error = "0.1"
+
+[dependencies.bevy]
+version = "0.8.0"
+default-features = false
+features = [
+    "bevy_render",
+    "bevy_sprite",
+    "bevy_core_pipeline"
+]
diff --git a/bevy_kayak_renderer/src/camera/camera.rs b/bevy_kayak_renderer/src/camera/camera.rs
index 90eb4aa3a1b2b2fee6d653cb61129a9897336c48..a3e5ba4068f038671cd3015227ff8baa52322438 100644
--- a/bevy_kayak_renderer/src/camera/camera.rs
+++ b/bevy_kayak_renderer/src/camera/camera.rs
@@ -1,7 +1,9 @@
 use bevy::{
-    prelude::{Bundle, Component, GlobalTransform, Transform},
+    ecs::query::QueryItem,
+    prelude::{Bundle, Component, GlobalTransform, Transform, With},
     render::{
-        camera::{Camera, CameraProjection, DepthCalculation, WindowOrigin},
+        camera::{Camera, CameraProjection, CameraRenderGraph, DepthCalculation, WindowOrigin},
+        extract_component::ExtractComponent,
         primitives::Frustum,
         view::VisibleEntities,
     },
@@ -9,12 +11,22 @@ use bevy::{
 
 use super::ortho::UIOrthographicProjection;
 
-#[derive(Component, Default)]
+#[derive(Component, Clone, Default)]
 pub struct CameraUiKayak;
 
+impl ExtractComponent for CameraUiKayak {
+    type Query = &'static Self;
+    type Filter = With<Camera>;
+
+    fn extract_component(item: QueryItem<Self::Query>) -> Self {
+        item.clone()
+    }
+}
+
 #[derive(Bundle)]
 pub struct UICameraBundle {
     pub camera: Camera,
+    pub camera_render_graph: CameraRenderGraph,
     pub orthographic_projection: UIOrthographicProjection,
     pub visible_entities: VisibleEntities,
     pub frustum: Frustum,
@@ -48,7 +60,11 @@ impl UICameraBundle {
             orthographic_projection.far(),
         );
         UICameraBundle {
-            camera: Default::default(),
+            camera: Camera {
+                priority: isize::MAX - 1,
+                ..Default::default()
+            },
+            camera_render_graph: CameraRenderGraph::new(crate::render::draw_ui_graph::NAME),
             orthographic_projection,
             frustum,
             visible_entities: VisibleEntities::default(),
diff --git a/bevy_kayak_renderer/src/camera/mod.rs b/bevy_kayak_renderer/src/camera/mod.rs
index 529f1991287f53d075b4ebc51492f76d8be57601..03e5781f0757c6c6fce5c99ec0ff3525db9f0229 100644
--- a/bevy_kayak_renderer/src/camera/mod.rs
+++ b/bevy_kayak_renderer/src/camera/mod.rs
@@ -1,6 +1,6 @@
 use bevy::{
     prelude::{CoreStage, Plugin},
-    render::camera::CameraTypePlugin,
+    render::{camera::CameraProjectionPlugin, extract_component::ExtractComponentPlugin},
 };
 
 mod camera;
@@ -17,6 +17,7 @@ impl Plugin for KayakUICameraPlugin {
             CoreStage::PostUpdate,
             bevy::render::camera::camera_system::<UIOrthographicProjection>,
         )
-        .add_plugin(CameraTypePlugin::<CameraUiKayak>::default());
+        .add_plugin(CameraProjectionPlugin::<UIOrthographicProjection>::default())
+        .add_plugin(ExtractComponentPlugin::<CameraUiKayak>::default());
     }
 }
diff --git a/bevy_kayak_renderer/src/render/mod.rs b/bevy_kayak_renderer/src/render/mod.rs
index 1717e94a9a78f1e27acebfad5353a042129eba15..c75adb51de7f6c7495cdc14c4e4354f10ec7dc8f 100644
--- a/bevy_kayak_renderer/src/render/mod.rs
+++ b/bevy_kayak_renderer/src/render/mod.rs
@@ -1,32 +1,22 @@
 use bevy::{
-    core_pipeline::node::MAIN_PASS_DRIVER,
-    prelude::{Commands, Plugin, Res},
+    prelude::{Commands, Entity, Plugin, Query, With},
     render::{
-        camera::ActiveCamera,
-        render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
+        render_graph::{RenderGraph, SlotInfo, SlotType},
         render_phase::{DrawFunctions, RenderPhase},
-        RenderApp, RenderStage,
+        Extract, RenderApp, RenderStage,
     },
 };
 
 use crate::{
-    render::{
-        ui_pass::MainPassUINode, ui_pass_driver::UIPassDriverNode, unified::UnifiedRenderPlugin,
-    },
+    render::{ui_pass::MainPassUINode, unified::UnifiedRenderPlugin},
     CameraUiKayak,
 };
 
 use self::ui_pass::TransparentUI;
 
 mod ui_pass;
-mod ui_pass_driver;
 pub mod unified;
 
-pub mod node {
-    pub const UI_PASS_DEPENDENCIES: &str = "kayak_ui_pass_dependencies";
-    pub const UI_PASS_DRIVER: &str = "kayak_ui_pass_driver";
-}
-
 pub mod draw_ui_graph {
     pub const NAME: &str = "kayak_draw_ui";
     pub mod input {
@@ -66,14 +56,7 @@ impl Plugin for BevyKayakUIRenderPlugin {
             .unwrap();
         graph.add_sub_graph(draw_ui_graph::NAME, draw_ui_graph);
 
-        graph.add_node(node::UI_PASS_DEPENDENCIES, EmptyNode);
-        graph.add_node(node::UI_PASS_DRIVER, UIPassDriverNode);
-        graph
-            .add_node_edge(node::UI_PASS_DEPENDENCIES, node::UI_PASS_DRIVER)
-            .unwrap();
-        graph
-            .add_node_edge(MAIN_PASS_DRIVER, node::UI_PASS_DRIVER)
-            .unwrap();
+        // graph.add_node_edge(MAIN_PASS, draw_ui_graph::NAME).unwrap();
 
         app.add_plugin(UnifiedRenderPlugin);
     }
@@ -81,9 +64,9 @@ impl Plugin for BevyKayakUIRenderPlugin {
 
 pub fn extract_core_pipeline_camera_phases(
     mut commands: Commands,
-    active_camera: Res<ActiveCamera<CameraUiKayak>>,
+    active_camera: Extract<Query<Entity, With<CameraUiKayak>>>,
 ) {
-    if let Some(entity) = active_camera.get() {
+    if let Ok(entity) = active_camera.get_single() {
         commands
             .get_or_spawn(entity)
             .insert(RenderPhase::<TransparentUI>::default());
diff --git a/bevy_kayak_renderer/src/render/ui_pass.rs b/bevy_kayak_renderer/src/render/ui_pass.rs
index e3a5ea1dbde6fe13ea078d4500acc91ce8050742..13a5c8dfe02fe13196bbf3d12d7dd9371bf4c33a 100644
--- a/bevy_kayak_renderer/src/render/ui_pass.rs
+++ b/bevy_kayak_renderer/src/render/ui_pass.rs
@@ -1,4 +1,3 @@
-use bevy::core::FloatOrd;
 use bevy::ecs::prelude::*;
 use bevy::render::render_phase::{DrawFunctionId, PhaseItem};
 use bevy::render::render_resource::{CachedRenderPipelineId, RenderPassColorAttachment};
@@ -9,6 +8,7 @@ use bevy::render::{
     renderer::RenderContext,
     view::{ExtractedView, ViewTarget},
 };
+use bevy::utils::FloatOrd;
 
 pub struct TransparentUI {
     pub sort_key: FloatOrd,
@@ -62,22 +62,24 @@ impl Node for MainPassUINode {
         world: &World,
     ) -> Result<(), NodeRunError> {
         let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
-        let (transparent_phase, target) = self
-            .query
-            .get_manual(world, view_entity)
-            .expect("view entity should exist");
+        // adapted from bevy itself;
+        // see: <https://github.com/bevyengine/bevy/commit/09a3d8abe062984479bf0e99fcc1508bb722baf6>
+        let (transparent_phase, target) = match self.query.get_manual(world, view_entity) {
+            Ok(it) => it,
+            _ => return Ok(()),
+        };
         // let clear_color = world.get_resource::<ClearColor>().unwrap();
         {
             let pass_descriptor = RenderPassDescriptor {
                 label: Some("main_transparent_pass_UI"),
-                color_attachments: &[RenderPassColorAttachment {
+                color_attachments: &[Some(RenderPassColorAttachment {
                     view: &target.view,
                     resolve_target: None,
                     ops: Operations {
                         load: LoadOp::Load, //Clear(clear_color.0.into()),
                         store: true,
                     },
-                }],
+                })],
                 depth_stencil_attachment: None,
             };
 
diff --git a/bevy_kayak_renderer/src/render/ui_pass_driver.rs b/bevy_kayak_renderer/src/render/ui_pass_driver.rs
deleted file mode 100644
index ac24266c001d65694ebf818f229ff343ffe9b87a..0000000000000000000000000000000000000000
--- a/bevy_kayak_renderer/src/render/ui_pass_driver.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use bevy::render::{
-    render_graph::{Node, NodeRunError, RenderGraphContext, SlotValue},
-    renderer::RenderContext,
-};
-use bevy::{ecs::world::World, render::camera::ActiveCamera};
-
-use crate::CameraUiKayak;
-
-pub struct UIPassDriverNode;
-
-impl Node for UIPassDriverNode {
-    fn run(
-        &self,
-        graph: &mut RenderGraphContext,
-        _render_context: &mut RenderContext,
-        world: &World,
-    ) -> Result<(), NodeRunError> {
-        if let Some(camera_ui) = world.resource::<ActiveCamera<CameraUiKayak>>().get() {
-            graph.run_sub_graph(
-                super::draw_ui_graph::NAME,
-                vec![SlotValue::Entity(camera_ui)],
-            )?;
-        }
-
-        Ok(())
-    }
-}
diff --git a/bevy_kayak_renderer/src/render/unified/mod.rs b/bevy_kayak_renderer/src/render/unified/mod.rs
index 7831cc0037d834f89c08d4abee8758a10274ee0d..1283d64ecfbd1d045d1ae2d96db8e859b0b257f4 100644
--- a/bevy_kayak_renderer/src/render/unified/mod.rs
+++ b/bevy_kayak_renderer/src/render/unified/mod.rs
@@ -1,7 +1,9 @@
 use bevy::{
     prelude::{Assets, Commands, HandleUntyped, Plugin, Res},
     reflect::TypeUuid,
-    render::{render_phase::DrawFunctions, render_resource::Shader, RenderApp, RenderStage},
+    render::{
+        render_phase::DrawFunctions, render_resource::Shader, Extract, RenderApp, RenderStage,
+    },
     window::Windows,
 };
 
@@ -55,8 +57,8 @@ pub struct Dpi(f32);
 
 pub fn extract_baseline(
     mut commands: Commands,
-    windows: Res<Windows>,
-    window_size: Res<WindowSize>,
+    windows: Extract<Res<Windows>>,
+    window_size: Extract<Res<WindowSize>>,
 ) {
     let dpi = if let Some(window) = windows.get_primary() {
         window.scale_factor() as f32
@@ -64,6 +66,6 @@ pub fn extract_baseline(
         1.0
     };
 
-    commands.insert_resource(*window_size);
+    commands.insert_resource(window_size.clone());
     commands.insert_resource(Dpi(dpi));
 }
diff --git a/bevy_kayak_renderer/src/render/unified/pipeline.rs b/bevy_kayak_renderer/src/render/unified/pipeline.rs
index 6079343dd7174799e90eaddd4eeb50e0b9769943..58e01bf3cc8286851028c37fcaac262a95075103 100644
--- a/bevy_kayak_renderer/src/render/unified/pipeline.rs
+++ b/bevy_kayak_renderer/src/render/unified/pipeline.rs
@@ -1,12 +1,11 @@
-use bevy::math::Size;
-use bevy::render::render_resource::std140::AsStd140;
+use bevy::render::render_resource::{DynamicUniformBuffer, ShaderType};
+use bevy::utils::FloatOrd;
 use bevy::{
-    core::FloatOrd,
     ecs::system::{
         lifetimeless::{Read, SQuery, SRes},
         SystemState,
     },
-    math::{const_vec3, Mat4, Quat, Vec2, Vec3, Vec4},
+    math::{Mat4, Quat, Vec2, Vec3, Vec4},
     prelude::{Bundle, Component, Entity, FromWorld, Handle, Query, Res, ResMut, World},
     render::{
         color::Color,
@@ -17,12 +16,12 @@ use bevy::{
             BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType,
             BlendComponent, BlendFactor, BlendOperation, BlendState, BufferBindingType, BufferSize,
             BufferUsages, BufferVec, CachedRenderPipelineId, ColorTargetState, ColorWrites,
-            DynamicUniformVec, Extent3d, FragmentState, FrontFace, MultisampleState, PipelineCache,
-            PolygonMode, PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor,
-            SamplerBindingType, SamplerDescriptor, Shader, ShaderStages, TextureDescriptor,
-            TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
-            TextureViewDescriptor, TextureViewDimension, VertexAttribute, VertexBufferLayout,
-            VertexFormat, VertexState, VertexStepMode,
+            Extent3d, FragmentState, FrontFace, MultisampleState, PipelineCache, PolygonMode,
+            PrimitiveState, PrimitiveTopology, RenderPipelineDescriptor, SamplerBindingType,
+            SamplerDescriptor, Shader, ShaderStages, TextureDescriptor, TextureDimension,
+            TextureFormat, TextureSampleType, TextureUsages, TextureViewDescriptor,
+            TextureViewDimension, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState,
+            VertexStepMode,
         },
         renderer::{RenderDevice, RenderQueue},
         texture::{BevyDefault, GpuImage, Image},
@@ -52,12 +51,12 @@ pub struct UnifiedPipeline {
 }
 
 const QUAD_VERTEX_POSITIONS: &[Vec3] = &[
-    const_vec3!([0.0, 1.0, 0.0]),
-    const_vec3!([1.0, 0.0, 0.0]),
-    const_vec3!([0.0, 0.0, 0.0]),
-    const_vec3!([0.0, 1.0, 0.0]),
-    const_vec3!([1.0, 1.0, 0.0]),
-    const_vec3!([1.0, 0.0, 0.0]),
+    Vec3::from_array([0.0, 1.0, 0.0]),
+    Vec3::from_array([1.0, 0.0, 0.0]),
+    Vec3::from_array([0.0, 0.0, 0.0]),
+    Vec3::from_array([0.0, 1.0, 0.0]),
+    Vec3::from_array([1.0, 1.0, 0.0]),
+    Vec3::from_array([1.0, 0.0, 0.0]),
 ];
 
 impl FontRenderingPipeline for UnifiedPipeline {
@@ -190,7 +189,7 @@ impl FromWorld for UnifiedPipeline {
                 shader: UNIFIED_SHADER_HANDLE.typed::<Shader>(),
                 shader_defs: vec![],
                 entry_point: "fragment".into(),
-                targets: vec![ColorTargetState {
+                targets: vec![Some(ColorTargetState {
                     format: TextureFormat::bevy_default(),
                     blend: Some(BlendState {
                         color: BlendComponent {
@@ -205,7 +204,7 @@ impl FromWorld for UnifiedPipeline {
                         },
                     }),
                     write_mask: ColorWrites::ALL,
-                }],
+                })],
             }),
             layout: Some(vec![
                 view_layout.clone(),
@@ -265,10 +264,7 @@ impl FromWorld for UnifiedPipeline {
             texture,
             sampler,
             texture_view,
-            size: Size {
-                width: 1.0,
-                height: 1.0,
-            },
+            size: Vec2::new(1.0, 1.0),
             texture_format: TextureFormat::Rgba8UnormSrgb,
         };
 
@@ -338,7 +334,7 @@ struct QuadVertex {
 }
 
 #[repr(C)]
-#[derive(Copy, Clone, AsStd140)]
+#[derive(Copy, Clone, ShaderType)]
 struct QuadType {
     pub t: i32,
 }
@@ -346,7 +342,7 @@ struct QuadType {
 pub struct QuadMeta {
     vertices: BufferVec<QuadVertex>,
     view_bind_group: Option<BindGroup>,
-    types_buffer: DynamicUniformVec<QuadType>,
+    types_buffer: DynamicUniformBuffer<QuadType>,
     types_bind_group: Option<BindGroup>,
 }
 
@@ -355,7 +351,7 @@ impl Default for QuadMeta {
         Self {
             vertices: BufferVec::new(BufferUsages::VERTEX),
             view_bind_group: None,
-            types_buffer: DynamicUniformVec::default(),
+            types_buffer: DynamicUniformBuffer::default(),
             types_bind_group: None,
         }
     }
@@ -379,7 +375,7 @@ pub fn prepare_quads(
     }
 
     sprite_meta.types_buffer.clear();
-    sprite_meta.types_buffer.reserve(2, &render_device);
+    // sprite_meta.types_buffer.reserve(2, &render_device);
     let quad_type_offset = sprite_meta.types_buffer.push(QuadType { t: 0 });
     let text_type_offset = sprite_meta.types_buffer.push(QuadType { t: 1 });
     let image_type_offset = sprite_meta.types_buffer.push(QuadType { t: 2 });
diff --git a/bevy_kayak_renderer/src/render/unified/shader.wgsl b/bevy_kayak_renderer/src/render/unified/shader.wgsl
index b43867e2662cb4a946bb4e94ddddbde284304843..293d4f9fe0dde7a644894688b9e8cd5bff6ba52d 100644
--- a/bevy_kayak_renderer/src/render/unified/shader.wgsl
+++ b/bevy_kayak_renderer/src/render/unified/shader.wgsl
@@ -1,32 +1,32 @@
 struct View {
-    view_proj: mat4x4<f32>;
-    world_position: vec3<f32>;
+    view_proj: mat4x4<f32>,
+    world_position: vec3<f32>,
 };
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> view: View;
 
 struct QuadType {
-    t: i32;
+    t: i32,
 };
-[[group(2), binding(0)]]
+@group(2) @binding(0)
 var<uniform> quad_type: QuadType;
 
 struct VertexOutput {
-    [[builtin(position)]] position: vec4<f32>;
-    [[location(0)]] color: vec4<f32>;
-    [[location(1)]] uv: vec3<f32>;
-    [[location(2)]] pos: vec2<f32>;
-    [[location(3)]] size: vec2<f32>;
-    [[location(4)]] border_radius: f32;
-    [[location(5)]] pixel_position: vec2<f32>;
+    @builtin(position) position: vec4<f32>,
+    @location(0) color: vec4<f32>,
+    @location(1) uv: vec3<f32>,
+    @location(2) pos: vec2<f32>,
+    @location(3) size: vec2<f32>,
+    @location(4) border_radius: f32,
+    @location(5) pixel_position: vec2<f32>,
 };
 
-[[stage(vertex)]]
+@vertex
 fn vertex(
-    [[location(0)]] vertex_position: vec3<f32>,
-    [[location(1)]] vertex_color: vec4<f32>,
-    [[location(2)]] vertex_uv: vec4<f32>,
-    [[location(3)]] vertex_pos_size: vec4<f32>,
+    @location(0) vertex_position: vec3<f32>,
+    @location(1) vertex_color: vec4<f32>,
+    @location(2) vertex_uv: vec4<f32>,
+    @location(3) vertex_pos_size: vec4<f32>,
 ) -> VertexOutput {
     var out: VertexOutput;
     out.color = vertex_color;
@@ -39,27 +39,26 @@ fn vertex(
     return out;
 }
 
-[[group(1), binding(0)]]
+@group(1) @binding(0)
 var font_texture: texture_2d_array<f32>;
-[[group(1), binding(1)]]
+@group(1) @binding(1)
 var font_sampler: sampler;
 
-[[group(3), binding(0)]]
+@group(3) @binding(0)
 var image_texture: texture_2d<f32>;
-[[group(3), binding(1)]]
+@group(3) @binding(1)
 var image_sampler: sampler;
 
 let RADIUS: f32 = 0.1;
 
 // Where P is the position in pixel space, B is the size of the box adn R is the radius of the current corner.
-fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32 
-{
-    var q = abs(p)-b+r;
+fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32 {
+    var q = abs(p) - b + r;
     return min(max(q.x, q.y), 0.0) + length(max(q, vec2<f32>(0.0))) - r;
 }
 
-[[stage(fragment)]]
-fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
+@fragment
+fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
     if (quad_type.t == 0) {
         var size = in.size;
         var pos = in.pos.xy * 2.0;
@@ -70,14 +69,14 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
             size,
             bs,
         );
-        rect_dist = 1.0 - smoothStep(0.0, fwidth(rect_dist), rect_dist);
-        return vec4<f32>(in.color.rgb, rect_dist);
+        rect_dist = 1.0 - smoothstep(0.0, fwidth(rect_dist), rect_dist);
+        return vec4<f32>(in.color.rgb, rect_dist * in.color.a);
     }
     if (quad_type.t == 1) {
         var px_range = 3.5;
         var tex_dimensions = textureDimensions(font_texture);
         var msdf_unit = vec2<f32>(px_range, px_range) / vec2<f32>(f32(tex_dimensions.x), f32(tex_dimensions.y));
-        var x = textureSample(font_texture, font_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y), i32(in.uv.z)); 
+        var x = textureSample(font_texture, font_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y), i32(in.uv.z));
         var v = max(min(x.r, x.g), min(max(x.r, x.g), x.b));
         var sig_dist = (v - 0.5) * dot(msdf_unit, 0.5 / fwidth(in.uv.xy));
         var a = clamp(sig_dist + 0.5, 0.0, 1.0);
@@ -90,9 +89,9 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
             in.size.xy,
             bs,
         );
-        mask = 1.0 - smoothStep(0.0, fwidth(mask), mask);
+        mask = 1.0 - smoothstep(0.0, fwidth(mask), mask);
         var color = textureSample(image_texture, image_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y));
         return vec4<f32>(color.rgb * in.color.rgb, color.a * in.color.a * mask);
     }
     return in.color;
-}
\ No newline at end of file
+}
diff --git a/bevy_kayak_ui/Cargo.toml b/bevy_kayak_ui/Cargo.toml
index 4abc681e85ff702ccb699757d582567403bc4272..29f12fdf1f9d75ba1fc89d0b6c177d92a6dee1c1 100644
--- a/bevy_kayak_ui/Cargo.toml
+++ b/bevy_kayak_ui/Cargo.toml
@@ -5,10 +5,15 @@ edition = "2021"
 
 [dependencies]
 bytemuck = "1.7.2"
-bevy = { version = "0.7.0" }
 kayak_core = { path = "../kayak_core" }
 kayak_font = { path = "../kayak_font" }
 bevy_kayak_renderer = { path = "../bevy_kayak_renderer" }
 serde = "1.0"
 serde_json = "1.0"
 serde_path_to_error = "0.1"
+log = "0.4"
+
+[dependencies.bevy]
+version = "0.8.0"
+features = ["bevy_winit"]
+default-features = false
diff --git a/bevy_kayak_ui/src/lib.rs b/bevy_kayak_ui/src/lib.rs
index 2d1a27a269a09df7457dd83aef80cfcab741079a..9ea3eae1c6bc9b8b0f59530abee98a8b6c4b66bb 100644
--- a/bevy_kayak_ui/src/lib.rs
+++ b/bevy_kayak_ui/src/lib.rs
@@ -2,7 +2,7 @@ use bevy::{
     input::{
         keyboard::KeyboardInput,
         mouse::{MouseButtonInput, MouseScrollUnit, MouseWheel},
-        ElementState,
+        ButtonState,
     },
     math::Vec2,
     prelude::{EventReader, IntoExclusiveSystem, MouseButton, Plugin, Res, World},
@@ -63,10 +63,12 @@ pub fn process_events(world: &mut World) {
         if let Some(window) = windows.get_primary() {
             Vec2::new(window.width(), window.height())
         } else {
-            panic!("Couldn't find primary window!");
+            log::warn!("Couldn't find primiary window!");
+            return;
         }
     } else {
-        panic!("Couldn't find primary window!");
+        log::warn!("Couldn't find primiary window!");
+        return;
     };
 
     if let Some(bevy_context) = world.remove_resource::<BevyContext>() {
@@ -99,9 +101,9 @@ pub fn process_events(world: &mut World) {
                     for event in mouse_button_input_events.iter() {
                         match event.button {
                             MouseButton::Left => {
-                                if event.state == ElementState::Pressed {
+                                if event.state == ButtonState::Pressed {
                                     input_events.push(InputEvent::MouseLeftPress);
-                                } else if event.state == ElementState::Released {
+                                } else if event.state == ButtonState::Released {
                                     input_events.push(InputEvent::MouseLeftRelease);
                                 }
                             }
@@ -126,7 +128,7 @@ pub fn process_events(world: &mut World) {
                             let kayak_key_code = key::convert_virtual_key_code(key_code);
                             input_events.push(InputEvent::Keyboard {
                                 key: kayak_key_code,
-                                is_pressed: matches!(event.state, ElementState::Pressed),
+                                is_pressed: matches!(event.state, ButtonState::Pressed),
                             });
                         }
                     }
diff --git a/bevy_kayak_ui/src/render/font/extract.rs b/bevy_kayak_ui/src/render/font/extract.rs
index 61b8380c60f55001135999ad2f9afa4bcf4c1a06..569f5e6d5cb4a0ce3a6298f0e2996303d487eb2d 100644
--- a/bevy_kayak_ui/src/render/font/extract.rs
+++ b/bevy_kayak_ui/src/render/font/extract.rs
@@ -34,7 +34,7 @@ pub fn extract_texts(
     };
 
     let font_handle = font_mapping.get_handle(font.clone()).unwrap();
-    let font = match fonts.get(font_handle.clone()) {
+    let font = match fonts.get(&font_handle) {
         Some(font) => font,
         None => return Vec::new(),
     };
diff --git a/bevy_kayak_ui/src/render/mod.rs b/bevy_kayak_ui/src/render/mod.rs
index aa55c2b1b13766b39795a6998215efa035ffc96d..efdfcd5ce898e925e8b38f42d966806f79240d9b 100644
--- a/bevy_kayak_ui/src/render/mod.rs
+++ b/bevy_kayak_ui/src/render/mod.rs
@@ -2,7 +2,7 @@ use crate::{BevyContext, FontMapping, ImageManager};
 use bevy::{
     math::Vec2,
     prelude::{Assets, Commands, Plugin, Res},
-    render::{color::Color, texture::Image, RenderApp, RenderStage},
+    render::{color::Color, texture::Image, Extract, RenderApp, RenderStage},
     sprite::Rect,
     window::Windows,
 };
@@ -33,18 +33,18 @@ impl Plugin for BevyKayakUIExtractPlugin {
 
 pub fn extract(
     mut commands: Commands,
-    context: Option<Res<BevyContext>>,
-    fonts: Res<Assets<KayakFont>>,
-    font_mapping: Res<FontMapping>,
-    image_manager: Res<ImageManager>,
-    images: Res<Assets<Image>>,
-    windows: Res<Windows>,
+    context: Extract<Option<Res<BevyContext>>>,
+    fonts: Extract<Res<Assets<KayakFont>>>,
+    font_mapping: Extract<Res<FontMapping>>,
+    image_manager: Extract<Res<ImageManager>>,
+    images: Extract<Res<Assets<Image>>>,
+    windows: Extract<Res<Windows>>,
 ) {
     if context.is_none() {
         return;
     }
 
-    let context = context.unwrap();
+    let context = context.as_ref().unwrap();
 
     let render_primitives = if let Ok(context) = context.kayak_context.read() {
         context.widget_manager.build_render_primitives()
diff --git a/examples/bevy_event.rs b/examples/bevy_event.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5b8365f66c5f3d0b80540c9acb9cf076b95a4725
--- /dev/null
+++ b/examples/bevy_event.rs
@@ -0,0 +1,82 @@
+use bevy::{
+    prelude::{App as BevyApp, AssetServer, Commands, EventReader, EventWriter, Res, ResMut},
+    window::WindowDescriptor,
+    DefaultPlugins,
+};
+use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
+use kayak_ui::core::{
+    render, rsx,
+    styles::{Style, StyleProp, Units},
+    widget, EventType, OnEvent,
+};
+use kayak_ui::widgets::{App, Button, Text, Window};
+
+pub struct MyEvent;
+
+#[widget]
+fn EventWindow() {
+    let button_text_styles = Style {
+        left: StyleProp::Value(Units::Stretch(1.0)),
+        right: StyleProp::Value(Units::Stretch(1.0)),
+        ..Default::default()
+    };
+
+    let on_event = OnEvent::new(move |ctx, event| match event.event_type {
+        EventType::Click(..) => {
+            ctx.query_world::<EventWriter<MyEvent>, _, ()>(|mut writer| writer.send(MyEvent));
+        }
+        _ => {}
+    });
+
+    rsx! {
+        <>
+            <Window draggable={true} position={(50.0, 50.0)} size={(300.0, 300.0)} title={"Bevy Event Example".to_string()}>
+                <Button on_event={Some(on_event)}>
+                    <Text styles={Some(button_text_styles)} line_height={Some(40.0)} size={24.0} content={"Send bevy event".to_string()}>{}</Text>
+                </Button>
+            </Window>
+        </>
+    }
+}
+
+fn startup(
+    mut commands: Commands,
+    mut font_mapping: ResMut<FontMapping>,
+    asset_server: Res<AssetServer>,
+) {
+    commands.spawn_bundle(UICameraBundle::new());
+
+    font_mapping.set_default(asset_server.load("roboto.kayak_font"));
+
+    let context = BevyContext::new(|context| {
+        render! {
+            <App>
+                <EventWindow />
+            </App>
+        }
+    });
+
+    commands.insert_resource(context);
+}
+
+fn on_my_event(mut reader: EventReader<MyEvent>) {
+    for _ in reader.iter() {
+        println!("MyEvent detected");
+    }
+}
+
+fn main() {
+    BevyApp::new()
+        .insert_resource(WindowDescriptor {
+            width: 1270.0,
+            height: 720.0,
+            title: String::from("UI Example"),
+            ..Default::default()
+        })
+        .add_plugins(DefaultPlugins)
+        .add_event::<MyEvent>()
+        .add_plugin(BevyKayakUIPlugin)
+        .add_startup_system(startup)
+        .add_system(on_my_event)
+        .run();
+}
diff --git a/examples/bevy_state.rs b/examples/bevy_state.rs
index 11e7b8736a0de3cbd7c1e59a5b69b0526356ab4c..9ebd91ad7da57fab1962d07ac174c8280ec03ef3 100644
--- a/examples/bevy_state.rs
+++ b/examples/bevy_state.rs
@@ -4,9 +4,7 @@ use bevy::{
     DefaultPlugins,
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
-use kayak_ui::core::{
-    render, rsx, widget, Event, EventType, Index, KayakContextRef, KeyCode, OnEvent,
-};
+use kayak_ui::core::{render, rsx, widget, Event, EventType, KayakContextRef, KeyCode, OnEvent};
 use kayak_ui::widgets::{App, Text};
 
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
diff --git a/examples/clipping.rs b/examples/clipping.rs
index 28c64658e6180a32201cb01f920c2d9e9fb84e6a..43887fce0cb4096a9ab3e2ca7936f3e5834032b8 100644
--- a/examples/clipping.rs
+++ b/examples/clipping.rs
@@ -7,7 +7,6 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager,
 use kayak_ui::core::{
     render,
     styles::{Edge, Style, StyleProp, Units},
-    Index,
 };
 use kayak_ui::widgets::{App, Clip, NinePatch, Text};
 
diff --git a/examples/counter.rs b/examples/counter.rs
index 4c1d46d615605e2c69229d9a76677c4ff6ed0758..9b2643391804c016a9c6d9e1ae58f449a2330190 100644
--- a/examples/counter.rs
+++ b/examples/counter.rs
@@ -7,7 +7,7 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle
 use kayak_ui::core::{
     render, rsx,
     styles::{Style, StyleProp, Units},
-    use_state, widget, EventType, Index, OnEvent,
+    use_state, widget, EventType, OnEvent,
 };
 use kayak_ui::widgets::{App, Button, Text, Window};
 
diff --git a/examples/fold.rs b/examples/fold.rs
index 3b0570cc3125ce18a1f170863fcc0103845c694c..d22c51740a168ce73ec7d0921632855cb0a571ae 100644
--- a/examples/fold.rs
+++ b/examples/fold.rs
@@ -9,7 +9,7 @@ use kayak_ui::{
     core::{
         render, rsx,
         styles::{Style, StyleProp, Units},
-        use_state, widget, Color, EventType, Handler, Index, OnEvent,
+        use_state, widget, Color, EventType, Handler, OnEvent,
     },
     widgets::{App, Background, Button, Fold, If, Text, Window},
 };
diff --git a/examples/full_ui.rs b/examples/full_ui.rs
index b3138993fb30699e00a08eb864a4b02609e9cf80..cc4188dcf90d176d6b9d19ec2b75f35b2545bfd1 100644
--- a/examples/full_ui.rs
+++ b/examples/full_ui.rs
@@ -7,7 +7,7 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager,
 use kayak_ui::core::{
     render, rsx,
     styles::{Edge, LayoutType, Style, StyleProp, Units},
-    widget, Bound, Children, EventType, Index, MutableBound, OnEvent, WidgetProps,
+    widget, Bound, Children, EventType, MutableBound, OnEvent, WidgetProps,
 };
 use kayak_ui::widgets::{App, NinePatch, Text};
 
diff --git a/examples/global_counter.rs b/examples/global_counter.rs
index 46653ee5ec559f321acd297ed6f4e262619f2cb2..a4d20530b7827b8934557d79690ae70221c8f665 100644
--- a/examples/global_counter.rs
+++ b/examples/global_counter.rs
@@ -4,7 +4,7 @@ use bevy::{
     DefaultPlugins,
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
-use kayak_ui::core::{bind, render, rsx, widget, Binding, Bound, Index, MutableBound};
+use kayak_ui::core::{bind, render, rsx, widget, Binding, Bound, MutableBound};
 use kayak_ui::widgets::{App, Text, Window};
 
 #[derive(Clone, PartialEq)]
diff --git a/examples/hooks.rs b/examples/hooks.rs
index 65656123c37395a4c485106aee96dd3ca8290df3..170630fe3ee6b7dcf3018fafd298a9f0ba6e63f2 100644
--- a/examples/hooks.rs
+++ b/examples/hooks.rs
@@ -16,7 +16,7 @@ use bevy::{
 };
 use kayak_ui::{
     bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle},
-    core::{render, rsx, use_effect, use_state, widget, EventType, Index, OnEvent},
+    core::{render, rsx, use_effect, use_state, widget, EventType, OnEvent},
     widgets::{App, Button, Text, Window},
 };
 
diff --git a/examples/if.rs b/examples/if.rs
index 1280686cf6b56b13324e21df3391cc2b94558591..8719991045d5f32935cd752eddfc8a1dfdba6c14 100644
--- a/examples/if.rs
+++ b/examples/if.rs
@@ -7,7 +7,7 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle
 use kayak_ui::core::{
     render, rsx,
     styles::{Style, StyleProp, Units},
-    widget, Bound, EventType, Index, MutableBound, OnEvent,
+    widget, Bound, EventType, MutableBound, OnEvent,
 };
 use kayak_ui::widgets::{App, Button, If, Text, Window};
 
diff --git a/examples/image.rs b/examples/image.rs
index 952129f61231650460199b5058d8e6d8995f697e..fb6d6cbf816fd7b0cc313a8f1a7351f848da0dd5 100644
--- a/examples/image.rs
+++ b/examples/image.rs
@@ -1,5 +1,6 @@
 use bevy::{
     prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut},
+    render::texture::ImageSettings,
     window::WindowDescriptor,
     DefaultPlugins,
 };
@@ -8,7 +9,6 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundl
 use kayak_ui::core::{
     render,
     styles::{Corner, Style, StyleProp, Units},
-    Index,
 };
 use kayak_ui::widgets::{App, Image};
 
@@ -51,6 +51,7 @@ fn main() {
             title: String::from("UI Example"),
             ..Default::default()
         })
+        .insert_resource(ImageSettings::default_nearest())
         .add_plugins(DefaultPlugins)
         .add_plugin(BevyKayakUIPlugin)
         .add_startup_system(startup)
diff --git a/examples/nine_patch.rs b/examples/nine_patch.rs
index d5c13d41130ddb2a8e39b278ee206ac9875585b7..640b5559c5bd090fa632a8fdfbb2821bd0a2d5fa 100644
--- a/examples/nine_patch.rs
+++ b/examples/nine_patch.rs
@@ -1,5 +1,6 @@
 use bevy::{
     prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut},
+    render::texture::ImageSettings,
     window::WindowDescriptor,
     DefaultPlugins,
 };
@@ -7,7 +8,6 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundl
 use kayak_ui::core::{
     render,
     styles::{Edge, Style, StyleProp, Units},
-    Index,
 };
 use kayak_ui::widgets::{App, NinePatch};
 
@@ -73,6 +73,7 @@ fn main() {
             title: String::from("UI Example"),
             ..Default::default()
         })
+        .insert_resource(ImageSettings::default_nearest())
         .add_plugins(DefaultPlugins)
         .add_plugin(BevyKayakUIPlugin)
         .add_startup_system(startup)
diff --git a/examples/provider.rs b/examples/provider.rs
index e6bbc13986b8b16b454dde492093988d5950ce0b..349b6322a8865d01fb95e2027598b1c8ba334587 100644
--- a/examples/provider.rs
+++ b/examples/provider.rs
@@ -19,7 +19,7 @@ use kayak_ui::{
     core::{
         render, rsx,
         styles::{Edge, LayoutType, Style, StyleProp, Units},
-        widget, Bound, Color, EventType, Index, MutableBound, OnEvent, WidgetProps,
+        widget, Bound, Color, EventType, MutableBound, OnEvent, WidgetProps,
     },
     widgets::{App, Background, Element, If, Text, TooltipConsumer, TooltipProvider, Window},
 };
diff --git a/examples/scrollbox.rs b/examples/scrollbox.rs
index 42ae8c2eb433b1f8bfe9ec9d416f69f7dc522f48..fec1c35fa4ae7774186328cb695a720035fe18a7 100644
--- a/examples/scrollbox.rs
+++ b/examples/scrollbox.rs
@@ -7,7 +7,6 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager,
 use kayak_ui::core::{
     render,
     styles::{Edge, Style, StyleProp, Units},
-    Index,
 };
 use kayak_ui::widgets::{App, Inspector, NinePatch, ScrollBox, Text};
 
diff --git a/examples/shrink_grow_layout.rs b/examples/shrink_grow_layout.rs
index da59079cd21a3ecae6127a1c8f74e83412ceefee..1cd19128bccac01aba0d7cc0af2132a1266d7aa6 100644
--- a/examples/shrink_grow_layout.rs
+++ b/examples/shrink_grow_layout.rs
@@ -21,7 +21,7 @@ use kayak_ui::{
     widgets::Button,
 };
 use kayak_ui::{
-    core::{render, rsx, widget, Index},
+    core::{render, rsx, widget},
     widgets::Background,
 };
 
diff --git a/examples/tabs/tabs.rs b/examples/tabs/tabs.rs
index f0f81c3d98330626f1dafa1f4283d038cfeebd0f..6930af3588d8207744913a66c68c4c8e3f528ed8 100644
--- a/examples/tabs/tabs.rs
+++ b/examples/tabs/tabs.rs
@@ -15,7 +15,7 @@ use kayak_ui::{
     core::{
         constructor, render, rsx,
         styles::{Style, StyleProp, Units},
-        widget, Color, Index,
+        widget, Color,
     },
     widgets::{App, Text, Window},
 };
diff --git a/examples/text_box.rs b/examples/text_box.rs
index db9adcf8056737731fa4686a51f1f044125d4120..17286c14715f669adb62c0fb07095f517cb4a85b 100644
--- a/examples/text_box.rs
+++ b/examples/text_box.rs
@@ -9,15 +9,16 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle
 use kayak_ui::core::{
     render, rsx,
     styles::{Style, StyleProp, Units},
-    widget, Index,
+    widget,
 };
-use kayak_ui::widgets::{App, OnChange, TextBox, Window};
+use kayak_ui::widgets::{App, Inspector, OnChange, SpinBox, SpinBoxStyle, TextBox, Window};
 
 #[widget]
 fn TextBoxExample() {
     let (value, set_value, _) = use_state!("I started with a value!".to_string());
     let (empty_value, set_empty_value, _) = use_state!("".to_string());
     let (red_value, set_red_value, _) = use_state!("This text is red".to_string());
+    let (spin_value, set_spin_value, _) = use_state!("3".to_string());
 
     let input_styles = Style {
         top: StyleProp::Value(Units::Pixels(10.0)),
@@ -41,8 +42,14 @@ fn TextBoxExample() {
         set_red_value(event.value);
     });
 
+    let on_change_spin = OnChange::new(move |event| {
+        set_spin_value(event.value);
+    });
+
+    let vert = SpinBoxStyle::Vertical;
+
     rsx! {
-        <Window position={(50.0, 50.0)} size={(300.0, 300.0)} title={"TextBox Example".to_string()}>
+        <Window position={(50.0, 50.0)} size={(500.0, 300.0)} title={"TextBox Example".to_string()}>
             <TextBox styles={Some(input_styles)} value={value} on_change={Some(on_change)} />
             <TextBox
                 styles={Some(input_styles)}
@@ -51,6 +58,21 @@ fn TextBoxExample() {
                 placeholder={Some("This is a placeholder".to_string())}
             />
             <TextBox styles={Some(red_text_styles)} value={red_value} on_change={Some(on_change_red)} />
+            <SpinBox
+                styles={Some(input_styles)}
+                value={spin_value}
+                on_change={Some(on_change_spin)}
+                min_val={0.0}
+                max_val={10.0}
+            />
+            <SpinBox
+                spin_button_style={vert}
+                styles={Some(input_styles)}
+                value={spin_value}
+                on_change={Some(on_change_spin)}
+                min_val={0.0}
+                max_val={10.0}
+            />
         </Window>
     }
 }
diff --git a/examples/todo/todo.rs b/examples/todo/todo.rs
index b17b016e9d68b426348084b20277b9c0b5d857e3..9e0a17a7d22294e49b3232949538b069d18fb876 100644
--- a/examples/todo/todo.rs
+++ b/examples/todo/todo.rs
@@ -7,7 +7,7 @@ use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle
 use kayak_ui::core::{
     render, rsx,
     styles::{LayoutType, Style, StyleProp, Units},
-    use_state, widget, EventType, Handler, Index, OnEvent,
+    use_state, widget, EventType, Handler, OnEvent,
 };
 use kayak_ui::widgets::{App, Element, OnChange, TextBox, Window};
 
diff --git a/examples/vec_widget.rs b/examples/vec_widget.rs
index ad3966673edeea6916a3f0a7479134778942b0b6..f6103c05fe37c181f2431290f7b3cfdd7457cfbd 100644
--- a/examples/vec_widget.rs
+++ b/examples/vec_widget.rs
@@ -4,7 +4,7 @@ use bevy::{
     DefaultPlugins,
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
-use kayak_ui::core::{constructor, render, Index, VecTracker};
+use kayak_ui::core::{constructor, render, VecTracker};
 use kayak_ui::widgets::{App, Text};
 
 fn startup(
diff --git a/examples/windows.rs b/examples/windows.rs
index 1caa3f8aa9bb2b1223a38a9970b87085aff2bdcf..fe46f1cf17c5f659a13d75cb4812f047ad8fe98a 100644
--- a/examples/windows.rs
+++ b/examples/windows.rs
@@ -4,7 +4,6 @@ use bevy::{
     DefaultPlugins,
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle};
-use kayak_ui::core::Index;
 use kayak_ui::core::{render, rsx, widget};
 use kayak_ui::widgets::{App, Inspector, Window};
 
diff --git a/examples/world_interaction.rs b/examples/world_interaction.rs
index 98efecb3c26f872a73d4ae212fd84ad055b59064..bd2621ed64bee34988f1765b2f2017a6202be114 100644
--- a/examples/world_interaction.rs
+++ b/examples/world_interaction.rs
@@ -6,11 +6,11 @@
 //! behavior.
 
 use bevy::{
-    math::{const_vec2, Vec3Swizzles, Vec4Swizzles},
+    math::{Vec3Swizzles, Vec4Swizzles},
     prelude::{
-        App as BevyApp, AssetServer, Color as BevyColor, Commands, Component, CursorMoved,
-        EventReader, GlobalTransform, Input, MouseButton, OrthographicCameraBundle, Query, Res,
-        ResMut, Sprite, SpriteBundle, Transform, Vec2, Windows, With, Without,
+        App as BevyApp, AssetServer, Camera2dBundle, Color as BevyColor, Commands, Component,
+        CursorMoved, EventReader, GlobalTransform, Input, MouseButton, Query, Res, ResMut, Sprite,
+        SpriteBundle, Transform, Vec2, Windows, With, Without,
     },
     window::WindowDescriptor,
     DefaultPlugins,
@@ -20,12 +20,12 @@ use kayak_ui::{
     core::{
         render, rsx,
         styles::{Edge, Style, StyleProp, Units},
-        use_state, widget, EventType, Index, OnEvent,
+        use_state, widget, EventType, OnEvent,
     },
     widgets::{App, Button, Text, Window},
 };
 
-const TILE_SIZE: Vec2 = const_vec2!([50.0, 50.0]);
+const TILE_SIZE: Vec2 = Vec2::from_array([50.0, 50.0]);
 const COLORS: &[BevyColor] = &[BevyColor::TEAL, BevyColor::MAROON, BevyColor::INDIGO];
 
 /// This is the system that sets the active tile's target position
@@ -223,7 +223,7 @@ fn on_color_change(
 /// A system that sets up the world
 fn world_setup(mut commands: Commands, active_color: Res<ActiveColor>) {
     commands
-        .spawn_bundle(OrthographicCameraBundle::new_2d())
+        .spawn_bundle(Camera2dBundle::default())
         .insert(WorldCamera);
     commands
         .spawn_bundle(SpriteBundle {
diff --git a/kayak_core/Cargo.toml b/kayak_core/Cargo.toml
index 206530a1c377da57ec14b036a7168ae5d05ea244..3e162060a4ad6a706b9a8a385cd1fbe69ba7fa8a 100644
--- a/kayak_core/Cargo.toml
+++ b/kayak_core/Cargo.toml
@@ -11,7 +11,6 @@ bevy_renderer = ["bevy", "kayak_font/bevy_renderer"]
 
 [dependencies]
 as-any = "0.2"
-bevy = { version = "0.7.0", optional = true }
 desync = { version = "0.7" }
 flo_rope = { version = "0.1" }
 futures = { version = "0.3" }
@@ -21,3 +20,8 @@ morphorm = { git = "https://github.com/geom3trik/morphorm", rev = "1243152d4cebe
 resources = "1.1"
 uuid = { version = "0.8", features = ["v4"] }
 indexmap = "1.8"
+
+[dependencies.bevy]
+version = "0.8.0"
+optional = true
+default-features = false
\ No newline at end of file
diff --git a/kayak_core/src/styles/mod.rs b/kayak_core/src/styles/mod.rs
index 4860c8cbf19aab07b65196112a2d8d4f21193d12..84d928830837d1806aa7e07436873a0b959ba775 100644
--- a/kayak_core/src/styles/mod.rs
+++ b/kayak_core/src/styles/mod.rs
@@ -4,6 +4,8 @@ mod corner;
 mod edge;
 mod option_ref;
 
+use std::ops::Add;
+
 pub use corner::Corner;
 pub use edge::Edge;
 pub use morphorm::{LayoutType, PositionType, Units};
@@ -394,6 +396,18 @@ impl Style {
     }
 }
 
+impl Add for Style {
+    type Output = Style;
+
+    /// Defines the `+` operator for [`Style`]. This is a convenience wrapper of the `self.with_style()` method and useful for concatenating many small `Style` variables. 
+    /// Similar to `with_style()` In a `StyleA + StyleB` operation, values from `StyleB` are applied to any field of StyleA that are marked as [`StyleProp::Unset`].
+    ///
+    /// Note: since the changes are applied only to unset fields, addition is *not* commutative. This means StyleA + StyleB != StyleB + StyleA for most cases.
+    fn add(self, other: Style) -> Style {
+        self.with_style(other)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::{Edge, Style, StyleProp, Units};
@@ -533,6 +547,36 @@ mod tests {
         assert_eq!(expected, style);
     }
 
+    #[test]
+    fn styles_should_add() {
+        let expected_left = StyleProp::Default;
+        let expected_width = StyleProp::Value(Units::Stretch(1.0));
+        let expected_height = StyleProp::Inherit;
+
+        let expected = Style {
+            left: expected_left.clone(),
+            width: expected_width.clone(),
+            height: expected_height.clone(),
+            ..Default::default()
+        };
+
+        let style_a = Style::default();
+        let style_b = Style {
+            height: expected_height,
+            ..Default::default()
+        };
+        let style_c = Style {
+            left: expected_left,
+            ..Default::default()
+        };
+        let style_d = Style {
+            width: expected_width,
+            ..Default::default()
+        };
+
+        assert_eq!(expected, style_a + style_b + style_c + style_d);
+    }
+
     #[test]
     fn value_should_convert_to_property() {
         let expected_width = Units::Pixels(123.0);
diff --git a/kayak_font/Cargo.toml b/kayak_font/Cargo.toml
index f080a4381ac77bcdb9fff3d26277386ad17ff1af..428924f199a59dbf75fd363ea6b939b38f549c14 100644
--- a/kayak_font/Cargo.toml
+++ b/kayak_font/Cargo.toml
@@ -3,20 +3,28 @@ name = "kayak_font"
 version = "0.1.0"
 edition = "2021"
 
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
 [features]
 default = ["bevy_renderer"]
 bevy_renderer = ["bevy"]
 
 [dependencies]
 anyhow = { version = "1.0" }
-bevy = { version = "0.7.0", optional = true }
-bytemuck = "1.7.2"
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-serde_path_to_error = "0.1"
+nanoserde = "0.1.30"
 unicode-segmentation = "1.9"
 
 # Provides UAX #14 line break segmentation
 xi-unicode = "0.3"
+
+[dependencies.bevy]
+version = "0.8.0"
+optional = true
+default-features = false
+features = [
+    "bevy_asset",
+    "bevy_render",
+    "bevy_core_pipeline"
+]
+
+[dev-dependencies]
+bevy = "0.8"
+bytemuck = "1.12.0"
diff --git a/kayak_font/examples/bevy.rs b/kayak_font/examples/bevy.rs
index 2266e62439fe3c9b9e8453a5915892ddebe12fa6..d5092614f4cbf3a3125fabb47e3e485df06cb8b2 100644
--- a/kayak_font/examples/bevy.rs
+++ b/kayak_font/examples/bevy.rs
@@ -1,10 +1,10 @@
 use bevy::{
-    math::{const_vec2, Vec2},
+    math::Vec2,
     prelude::{
-        App as BevyApp, AssetServer, Commands, Component, Handle, Input, KeyCode, Query, Res,
-        ResMut, Sprite, SpriteBundle, Transform, With, Without,
+        App as BevyApp, AssetServer, Camera2dBundle, Commands, Component, Handle, Input, KeyCode,
+        Query, Res, ResMut, Sprite, SpriteBundle, Transform, With, Without,
     },
-    render::{camera::OrthographicCameraBundle, color::Color},
+    render::color::Color,
     window::WindowDescriptor,
     DefaultPlugins,
 };
@@ -15,8 +15,8 @@ use renderer::{FontRenderPlugin, Text};
 mod renderer;
 
 const FONT_SIZE: f32 = 24.0;
-const INITIAL_SIZE: Vec2 = const_vec2!([400.0, 300.0]);
-const INITIAL_POS: Vec2 = const_vec2!([-200.0, 0.0]);
+const INITIAL_SIZE: Vec2 = Vec2::from_array([400.0, 300.0]);
+const INITIAL_POS: Vec2 = Vec2::from_array([-200.0, 0.0]);
 const INSTRUCTIONS: &str =
     "Press 'A' and 'D' to shrink and grow the text box.\nPress 'Space' to cycle text alignment.";
 
@@ -24,7 +24,7 @@ const INSTRUCTIONS: &str =
 struct Instructions;
 
 fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
-    commands.spawn_bundle(OrthographicCameraBundle::new_2d());
+    commands.spawn_bundle(Camera2dBundle::default());
 
     let font_handle: Handle<KayakFont> = asset_server.load("roboto.kayak_font");
 
diff --git a/kayak_font/examples/renderer/extract.rs b/kayak_font/examples/renderer/extract.rs
index 999133619a4caf5c60df8484547647fe396af2e6..0c90bdb96b4592ee1ca552c9ee9de046ad0446df 100644
--- a/kayak_font/examples/renderer/extract.rs
+++ b/kayak_font/examples/renderer/extract.rs
@@ -1,7 +1,7 @@
 use bevy::{
     math::Vec2,
     prelude::{Assets, Commands, Handle, Query, Res},
-    sprite::Rect,
+    sprite::Rect, render::Extract,
 };
 use kayak_font::{KayakFont, TextProperties};
 
@@ -12,8 +12,8 @@ use super::{
 
 pub fn extract(
     mut commands: Commands,
-    fonts: Res<Assets<KayakFont>>,
-    texts: Query<(&Text, &Handle<KayakFont>)>,
+    fonts: Extract<Res<Assets<KayakFont>>>,
+    texts: Extract<Query<(&Text, &Handle<KayakFont>)>>,
 ) {
     let mut extracted_texts = Vec::new();
 
diff --git a/kayak_font/examples/renderer/mod.rs b/kayak_font/examples/renderer/mod.rs
index dec8300fd080f6cd14ab66e885f83878177a8ab5..10ccaff55844b4b5635db7eb7c2703f4f40c676c 100644
--- a/kayak_font/examples/renderer/mod.rs
+++ b/kayak_font/examples/renderer/mod.rs
@@ -1,5 +1,5 @@
 use bevy::{
-    core_pipeline::Transparent2d,
+    core_pipeline::core_2d::Transparent2d,
     prelude::{Assets, HandleUntyped, Plugin, Res, ResMut},
     reflect::TypeUuid,
     render::{
diff --git a/kayak_font/examples/renderer/pipeline.rs b/kayak_font/examples/renderer/pipeline.rs
index c37222150640f813d45b86b18697c696a792ae9e..32f5efd9e7ae27cdf9aba430ab28eea7b4942881 100644
--- a/kayak_font/examples/renderer/pipeline.rs
+++ b/kayak_font/examples/renderer/pipeline.rs
@@ -1,12 +1,10 @@
-use bevy::render::render_resource::std140::AsStd140;
 use bevy::{
-    core::FloatOrd,
-    core_pipeline::Transparent2d,
+    core_pipeline::core_2d::Transparent2d,
     ecs::system::{
         lifetimeless::{Read, SQuery, SRes},
         SystemState,
     },
-    math::{const_vec3, Mat4, Quat, Vec2, Vec3, Vec4},
+    math::{Mat4, Quat, Vec2, Vec3, Vec4},
     prelude::{Bundle, Component, Entity, FromWorld, Handle, Query, Res, ResMut, World},
     render::{
         color::Color,
@@ -18,7 +16,7 @@ use bevy::{
             BufferVec, CachedRenderPipelineId, ColorTargetState, ColorWrites, FragmentState,
             FrontFace, MultisampleState, PipelineCache, PolygonMode, PrimitiveState,
             PrimitiveTopology, RenderPipelineDescriptor, SamplerBindingType, Shader, ShaderStages,
-            TextureFormat, TextureSampleType, TextureViewDimension, VertexAttribute,
+            ShaderType, TextureFormat, TextureSampleType, TextureViewDimension, VertexAttribute,
             VertexBufferLayout, VertexFormat, VertexState, VertexStepMode,
         },
         renderer::{RenderDevice, RenderQueue},
@@ -26,6 +24,7 @@ use bevy::{
         view::{ViewUniformOffset, ViewUniforms},
     },
     sprite::Rect,
+    utils::FloatOrd,
 };
 use bytemuck::{Pod, Zeroable};
 use kayak_font::{
@@ -43,12 +42,12 @@ pub struct FontPipeline {
 }
 
 const QUAD_VERTEX_POSITIONS: &[Vec3] = &[
-    const_vec3!([0.0, 0.0, 0.0]),
-    const_vec3!([1.0, 1.0, 0.0]),
-    const_vec3!([0.0, 1.0, 0.0]),
-    const_vec3!([0.0, 0.0, 0.0]),
-    const_vec3!([1.0, 0.0, 0.0]),
-    const_vec3!([1.0, 1.0, 0.0]),
+    Vec3::from_array([0.0, 0.0, 0.0]),
+    Vec3::from_array([1.0, 1.0, 0.0]),
+    Vec3::from_array([0.0, 1.0, 0.0]),
+    Vec3::from_array([0.0, 0.0, 0.0]),
+    Vec3::from_array([1.0, 0.0, 0.0]),
+    Vec3::from_array([1.0, 1.0, 0.0]),
 ];
 
 impl FontRenderingPipeline for FontPipeline {
@@ -70,8 +69,6 @@ impl FromWorld for FontPipeline {
                 ty: BindingType::Buffer {
                     ty: BufferBindingType::Uniform,
                     has_dynamic_offset: true,
-                    // TODO: change this to ViewUniform::std140_size_static once crevice fixes this!
-                    // Context: https://github.com/LPGhatguy/crevice/issues/29
                     min_binding_size: BufferSize::new(144),
                 },
                 count: None,
@@ -143,7 +140,7 @@ impl FromWorld for FontPipeline {
                 shader: FONT_SHADER_HANDLE.typed::<Shader>(),
                 shader_defs: vec![],
                 entry_point: "fragment".into(),
-                targets: vec![ColorTargetState {
+                targets: vec![Some(ColorTargetState {
                     format: TextureFormat::bevy_default(),
                     blend: Some(BlendState {
                         color: BlendComponent {
@@ -158,7 +155,7 @@ impl FromWorld for FontPipeline {
                         },
                     }),
                     write_mask: ColorWrites::ALL,
-                }],
+                })],
             }),
             layout: Some(vec![view_layout.clone(), font_image_layout.clone()]),
             primitive: PrimitiveState {
@@ -213,7 +210,7 @@ struct QuadVertex {
 }
 
 #[repr(C)]
-#[derive(Copy, Clone, AsStd140)]
+#[derive(Copy, Clone, ShaderType)]
 struct QuadType {
     pub t: i32,
 }
diff --git a/kayak_font/examples/renderer/shader.wgsl b/kayak_font/examples/renderer/shader.wgsl
index 5213429eb5757c9c107e851fde4292f9dcfd527c..4bfdf8f701d0c5f46187aefc63043144488e487a 100644
--- a/kayak_font/examples/renderer/shader.wgsl
+++ b/kayak_font/examples/renderer/shader.wgsl
@@ -1,26 +1,27 @@
 struct View {
-    view_proj: mat4x4<f32>;
-    world_position: vec3<f32>;
-};
-[[group(0), binding(0)]]
+    view_proj: mat4x4<f32>,
+    world_position: vec3<f32>,
+}
+
+@group(0) @binding(0)
 var<uniform> view: View;
 
 struct VertexOutput {
-    [[builtin(position)]] position: vec4<f32>;
-    [[location(0)]] color: vec4<f32>;
-    [[location(1)]] uv: vec3<f32>;
-    [[location(2)]] pos: vec2<f32>;
-    [[location(3)]] size: vec2<f32>;
-    [[location(4)]] screen_position: vec2<f32>;
-    [[location(5)]] border_radius: f32;
+    @builtin(position) position: vec4<f32>,
+    @location(0) color: vec4<f32>,
+    @location(1) uv: vec3<f32>,
+    @location(2) pos: vec2<f32>,
+    @location(3) size: vec2<f32>,
+    @location(4) screen_position: vec2<f32>,
+    @location(5) border_radius: f32,
 };
 
-[[stage(vertex)]]
+@vertex
 fn vertex(
-    [[location(0)]] vertex_position: vec3<f32>,
-    [[location(1)]] vertex_color: vec4<f32>,
-    [[location(2)]] vertex_uv: vec4<f32>,
-    [[location(3)]] vertex_pos_size: vec4<f32>,
+    @location(0) vertex_position: vec3<f32>,
+    @location(1) vertex_color: vec4<f32>,
+    @location(2) vertex_uv: vec4<f32>,
+    @location(3) vertex_pos_size: vec4<f32>,
 ) -> VertexOutput {
     var out: VertexOutput;
     out.color = vertex_color;
@@ -33,17 +34,17 @@ fn vertex(
     return out;
 }
 
-[[group(1), binding(0)]]
+@group(1) @binding(0)
 var font_texture: texture_2d_array<f32>;
-[[group(1), binding(1)]]
+@group(1) @binding(1)
 var font_sampler: sampler;
 
-[[stage(fragment)]]
-fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
+@fragment
+fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
     var px_range = 2.5;
     var tex_dimensions = textureDimensions(font_texture);
     var msdf_unit = vec2<f32>(px_range, px_range) / vec2<f32>(f32(tex_dimensions.x), f32(tex_dimensions.y));
-    var x = textureSample(font_texture, font_sampler, vec2<f32>(in.uv.x, in.uv.y), i32(in.uv.z)); 
+    var x = textureSample(font_texture, font_sampler, vec2<f32>(in.uv.x, in.uv.y), i32(in.uv.z));
     var v = max(min(x.r, x.g), min(max(x.r, x.g), x.b));
     var sig_dist = (v - 0.5) * dot(msdf_unit, 0.5 / fwidth(in.uv.xy));
     var a = clamp(sig_dist + 0.5, 0.0, 1.0);
diff --git a/kayak_font/src/atlas.rs b/kayak_font/src/atlas.rs
index 97e6f5421b7f42a9879a8d1c77502d8d6be67be2..e710863f88bd5b9e2dd6e47d2a5c8d5c9e759f7e 100644
--- a/kayak_font/src/atlas.rs
+++ b/kayak_font/src/atlas.rs
@@ -1,33 +1,33 @@
-use serde::Deserialize;
+use nanoserde::DeJson;
 
-#[derive(Deserialize, Debug, Copy, Clone, PartialEq)]
+#[derive(DeJson, Debug, Copy, Clone, PartialEq)]
 pub enum SDFType {
-    #[serde(alias = "msdf")]
+    #[nserde(rename = "msdf")]
     Msdf,
 }
 
-#[derive(Deserialize, Debug, Copy, Clone, PartialEq)]
+#[derive(DeJson, Debug, Copy, Clone, PartialEq)]
 pub enum Origin {
-    #[serde(alias = "bottom")]
+    #[nserde(rename = "bottom")]
     Bottom,
-    #[serde(alias = "left")]
+    #[nserde(rename = "left")]
     Left,
-    #[serde(alias = "right")]
+    #[nserde(rename = "right")]
     Right,
-    #[serde(alias = "top")]
+    #[nserde(rename = "top")]
     Top,
 }
 
-#[derive(Deserialize, Debug, Copy, Clone, PartialEq)]
+#[derive(DeJson, Debug, Copy, Clone, PartialEq)]
 pub struct Atlas {
-    #[serde(alias = "type")]
+    #[nserde(rename = "type")]
     pub sdf_type: SDFType,
-    #[serde(alias = "distanceRange")]
+    #[nserde(rename = "distanceRange")]
     pub distance_range: f32,
-    #[serde(alias = "size")]
+    #[nserde(rename = "size")]
     pub font_size: f32,
     pub width: u32,
     pub height: u32,
-    #[serde(alias = "yOrigin")]
+    #[nserde(rename = "yOrigin")]
     pub y_origin: Origin,
 }
diff --git a/kayak_font/src/bevy/font_texture.rs b/kayak_font/src/bevy/font_texture.rs
index c0868a91b5bcd9297c7e9e33b6b2ee80840a45e2..26110bf83642556c3e0064a0e1210f014c9dc5fc 100644
--- a/kayak_font/src/bevy/font_texture.rs
+++ b/kayak_font/src/bevy/font_texture.rs
@@ -1,6 +1,7 @@
 use crate::KayakFont;
 use bevy::prelude::{AssetEvent, Assets, EventReader, Handle, Image, Local, Res, ResMut};
-use bevy::render::render_resource::{FilterMode, TextureFormat, TextureUsages};
+use bevy::render::render_resource::{FilterMode, SamplerDescriptor, TextureFormat, TextureUsages};
+use bevy::render::texture::ImageSampler;
 
 pub fn init_font_texture(
     mut not_processed: Local<Vec<Handle<KayakFont>>>,
@@ -23,9 +24,13 @@ pub fn init_font_texture(
         if let Some(font) = fonts.get(&font_handle) {
             if let Some(mut texture) = images.get_mut(&font.atlas_image) {
                 texture.texture_descriptor.format = TextureFormat::Rgba8Unorm;
-                texture.sampler_descriptor.min_filter = FilterMode::Linear;
-                texture.sampler_descriptor.mipmap_filter = FilterMode::Linear;
-                texture.sampler_descriptor.mag_filter = FilterMode::Linear;
+                texture.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor {
+                    label: Some("Present Sampler"),
+                    mag_filter: FilterMode::Linear,
+                    min_filter: FilterMode::Linear,
+
+                    ..Default::default()
+                });
                 texture.texture_descriptor.usage = TextureUsages::TEXTURE_BINDING
                     | TextureUsages::COPY_DST
                     | TextureUsages::COPY_SRC;
diff --git a/kayak_font/src/bevy/renderer/extract.rs b/kayak_font/src/bevy/renderer/extract.rs
index 16a9dbe7c2979fb10c7080a2c6327be692415495..490ba4c04d7e6af21cec68b27781fc64f27156b8 100644
--- a/kayak_font/src/bevy/renderer/extract.rs
+++ b/kayak_font/src/bevy/renderer/extract.rs
@@ -1,7 +1,10 @@
 use crate::bevy::renderer::FontTextureCache;
 use crate::KayakFont;
 use bevy::prelude::{AssetEvent, Assets, Commands, EventReader, Handle, Image, Local, Res, ResMut};
-use bevy::render::render_resource::{TextureFormat, TextureUsages};
+use bevy::render::{
+    render_resource::{TextureFormat, TextureUsages},
+    Extract,
+};
 use bevy::utils::HashSet;
 
 #[derive(Default)]
@@ -12,9 +15,9 @@ pub struct ExtractedFonts {
 pub(crate) fn extract_fonts(
     mut not_processed: Local<Vec<Handle<KayakFont>>>,
     mut commands: Commands,
-    font_assets: Res<Assets<KayakFont>>,
-    mut events: EventReader<AssetEvent<KayakFont>>,
-    textures: Res<Assets<Image>>,
+    font_assets: Extract<Res<Assets<KayakFont>>>,
+    mut events: Extract<EventReader<AssetEvent<KayakFont>>>,
+    textures: Extract<Res<Assets<Image>>>,
 ) {
     let mut extracted_fonts = ExtractedFonts { fonts: Vec::new() };
     let mut changed_assets = HashSet::default();
diff --git a/kayak_font/src/bevy/renderer/font_texture_cache.rs b/kayak_font/src/bevy/renderer/font_texture_cache.rs
index 5b18fbcee6181a72ddf3a791e85f4462b52af7f7..3d105f5731a424c271551ebb1ca82299553ab69c 100644
--- a/kayak_font/src/bevy/renderer/font_texture_cache.rs
+++ b/kayak_font/src/bevy/renderer/font_texture_cache.rs
@@ -1,6 +1,6 @@
 use crate::{KayakFont, Sdf};
 use bevy::{
-    math::{Size, Vec2},
+    math::Vec2,
     prelude::{Handle, Res},
     render::{
         render_asset::RenderAssets,
@@ -150,9 +150,9 @@ impl FontTextureCache {
             texture,
             sampler,
             texture_view,
-            size: Size {
-                width: size.0 as f32,
-                height: size.1 as f32,
+            size: Vec2 {
+                x: size.0 as f32,
+                y: size.1 as f32,
             },
             texture_format: format,
         };
@@ -195,9 +195,9 @@ impl FontTextureCache {
             texture,
             sampler,
             texture_view,
-            size: Size {
-                width: 1.0,
-                height: 1.0,
+            size: Vec2 {
+                x: 1.0,
+                y: 1.0,
             },
             texture_format: TextureFormat::Rgba8Unorm,
         };
diff --git a/kayak_font/src/glyph.rs b/kayak_font/src/glyph.rs
index 54301e01624311b438128e23d74fd7779867ded9..0975e26be28c112d2838940fe7ebfa8ef096836b 100644
--- a/kayak_font/src/glyph.rs
+++ b/kayak_font/src/glyph.rs
@@ -1,28 +1,50 @@
-use serde::{Deserialize, Deserializer};
-
-fn from_u32<'de, D>(deserializer: D) -> Result<char, D::Error>
-where
-    D: Deserializer<'de>,
-{
-    let number: u32 = Deserialize::deserialize(deserializer)?;
-    match char::from_u32(number) {
-        Some(c) => Ok(c),
-        None => Err(serde::de::Error::custom("Can't deserialize char from u32!")),
+use nanoserde::{DeJson, DeJsonErr, DeJsonState, SerJson, SerJsonState};
+
+pub struct UnicodeChar(char);
+
+impl DeJson for UnicodeChar {
+    fn de_json(state: &mut DeJsonState, input: &mut std::str::Chars) -> Result<Self, DeJsonErr> {
+        u32::de_json(state, input).and_then(|a| {
+            if let Some(a) = char::from_u32(a) {
+                Ok(Self(a))
+            } else {
+                Err(state.err_parse("Not unicode"))
+            }
+        })
+    }
+}
+
+impl SerJson for UnicodeChar {
+    fn ser_json(&self, d: usize, s: &mut SerJsonState) {
+        let out = self.0 as u32;
+        out.ser_json(d, s)
+    }
+}
+
+impl From<&char> for UnicodeChar {
+    fn from(c: &char) -> Self {
+        Self(*c)
+    }
+}
+
+impl From<&UnicodeChar> for char {
+    fn from(uc: &UnicodeChar) -> Self {
+        uc.0
     }
 }
 
-#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
+#[derive(DeJson, Debug, Clone, Copy, PartialEq)]
 pub struct Glyph {
-    #[serde(deserialize_with = "from_u32")]
+    #[nserde(proxy = "UnicodeChar")]
     pub unicode: char,
     pub advance: f32,
-    #[serde(alias = "atlasBounds")]
+    #[nserde(rename = "atlasBounds")]
     pub atlas_bounds: Option<Rect>,
-    #[serde(alias = "planeBounds")]
+    #[nserde(rename = "planeBounds")]
     pub plane_bounds: Option<Rect>,
 }
 
-#[derive(Deserialize, Default, Clone, Copy, Debug, PartialEq)]
+#[derive(DeJson, Default, Clone, Copy, Debug, PartialEq)]
 pub struct Rect {
     pub left: f32,
     pub bottom: f32,
diff --git a/kayak_font/src/metrics.rs b/kayak_font/src/metrics.rs
index 0e042bbe8f095f982ccba0f226752a1deef2f077..83d307f6206bb9231492057ea2d960fda28306b6 100644
--- a/kayak_font/src/metrics.rs
+++ b/kayak_font/src/metrics.rs
@@ -1,15 +1,15 @@
-use serde::Deserialize;
+use nanoserde::DeJson;
 
-#[derive(Deserialize, Debug, Copy, Clone, PartialEq)]
+#[derive(DeJson, Debug, Copy, Clone, PartialEq)]
 pub struct Metrics {
-    #[serde(alias = "emSize")]
+    #[nserde(rename = "emSize")]
     em_size: f32,
-    #[serde(alias = "lineHeight")]
+    #[nserde(rename = "lineHeight")]
     line_height: f32,
     ascender: f32,
     descender: f32,
-    #[serde(alias = "underlineY")]
+    #[nserde(rename = "underlineY")]
     underline_y: f32,
-    #[serde(alias = "underlineThickness")]
+    #[nserde(rename = "underlineThickness")]
     underline_thickness: f32,
 }
diff --git a/kayak_font/src/sdf.rs b/kayak_font/src/sdf.rs
index 13fe4d912cde34e5de6098841b79ada628fb0cd4..ec6ed8e5ccb63a14dd280830516dd03a81f64805 100644
--- a/kayak_font/src/sdf.rs
+++ b/kayak_font/src/sdf.rs
@@ -1,7 +1,7 @@
 use crate::{atlas::Atlas, glyph::Glyph, metrics::Metrics};
-use serde::Deserialize;
+use nanoserde::DeJson;
 
-#[derive(Deserialize, Debug, Clone, PartialEq)]
+#[derive(DeJson, Debug, Clone, PartialEq)]
 pub struct Sdf {
     pub atlas: Atlas,
     metrics: Metrics,
@@ -9,7 +9,7 @@ pub struct Sdf {
     kerning: Vec<KerningData>,
 }
 
-#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
+#[derive(DeJson, Debug, Clone, Copy, PartialEq)]
 pub struct KerningData {
     pub unicode1: u32,
     pub unicode2: u32,
@@ -18,14 +18,10 @@ pub struct KerningData {
 
 impl Sdf {
     pub fn from_string(data: String) -> Sdf {
-        let value: Sdf = match serde_path_to_error::deserialize(
-            &mut serde_json::Deserializer::from_str(&data),
-        ) {
+        let value: Sdf = match DeJson::deserialize_json(data.as_str()) {
             Ok(v) => v,
             Err(err) => {
-                let path = err.path().to_string();
-                dbg!(err);
-                panic!("failed to deserialize json! path: {}", path);
+                panic!("{}", dbg!(err));
             }
         };
 
@@ -33,14 +29,10 @@ impl Sdf {
     }
 
     pub fn from_bytes(data: &[u8]) -> Sdf {
-        let value: Sdf = match serde_path_to_error::deserialize(
-            &mut serde_json::Deserializer::from_slice(&data),
-        ) {
+        let value: Sdf = match DeJson::deserialize_json(std::str::from_utf8(data).unwrap()) {
             Ok(v) => v,
             Err(err) => {
-                let path = err.path().to_string();
-                dbg!(err);
-                panic!("failed to deserialize json! path: {}", path);
+                panic!("{}", dbg!(err));
             }
         };
 
@@ -49,6 +41,7 @@ impl Sdf {
 
     pub fn max_glyph_size(&self) -> (f32, f32) {
         let mut size = (0.0, 0.0);
+
         self.glyphs.iter().for_each(|glyph| {
             if let Some(atlas_bounds) = glyph.atlas_bounds {
                 let atlas_size = atlas_bounds.size();
diff --git a/kayak_render_macros/Cargo.toml b/kayak_render_macros/Cargo.toml
index 3866bb4e99a880687d51c176f557c10c407ee43b..559d82c112b4c9ef16492d1d61b1020e59929456 100644
--- a/kayak_render_macros/Cargo.toml
+++ b/kayak_render_macros/Cargo.toml
@@ -10,7 +10,7 @@ proc-macro = true
 default = []
 
 [dependencies]
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0", features = ["full", "extra-traits"] }
 quote = "1.0"
 proc-macro2 = "1.0"
 proc-macro-error = "1.0"
@@ -18,4 +18,4 @@ proc-macro-crate = "1.1"
 
 [dev-dependencies]
 kayak_core = { path = "../kayak_core", version = "0.1.0" }
-pretty_assertions = "0.3.4"
+pretty_assertions = "1.2.1"
diff --git a/kayak_render_macros/src/lib.rs b/kayak_render_macros/src/lib.rs
index f47a051f1cfaac0e04cac2f5182eab4360221777..a6a924356ff4a89047e350b5d56fc9ff62285a17 100644
--- a/kayak_render_macros/src/lib.rs
+++ b/kayak_render_macros/src/lib.rs
@@ -36,7 +36,7 @@ pub fn render(input: TokenStream) -> TokenStream {
 
     let result = quote! {
         let mut context = #kayak_core::KayakContextRef::new(context, None);
-        let parent_id: Option<Index> = None;
+        let parent_id: Option<#kayak_core::Index> = None;
         let children: Option<#kayak_core::Children> = None;
         #widget
         context.commit();
diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs
index 81ae6a101701076f01ed470510f09c3bc34dbc7a..e4915a51a1ae10c1ba8ecbae27892dd1695983df 100644
--- a/src/widgets/mod.rs
+++ b/src/widgets/mod.rs
@@ -9,7 +9,9 @@ mod image;
 mod inspector;
 mod nine_patch;
 mod texture_atlas;
+mod on_change;
 mod scroll;
+mod spin_box;
 mod text;
 mod text_box;
 mod tooltip;
@@ -26,7 +28,9 @@ pub use image::*;
 pub use inspector::*;
 pub use nine_patch::*;
 pub use texture_atlas::*;
+pub use on_change::*;
 pub use scroll::*;
+pub use spin_box::*;
 pub use text::*;
 pub use text_box::*;
 pub use tooltip::*;
diff --git a/src/widgets/on_change.rs b/src/widgets/on_change.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b4fdebba15a0ea64cf3730e6eb54f7541c9a320e
--- /dev/null
+++ b/src/widgets/on_change.rs
@@ -0,0 +1,27 @@
+use std::sync::{Arc, RwLock};
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct ChangeEvent {
+    pub value: String,
+}
+
+#[derive(Clone)]
+pub struct OnChange(pub Arc<RwLock<dyn FnMut(ChangeEvent) + Send + Sync + 'static>>);
+
+impl OnChange {
+    pub fn new<F: FnMut(ChangeEvent) + Send + Sync + 'static>(f: F) -> OnChange {
+        OnChange(Arc::new(RwLock::new(f)))
+    }
+}
+
+impl PartialEq for OnChange {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl std::fmt::Debug for OnChange {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_tuple("OnChange").finish()
+    }
+}
diff --git a/src/widgets/spin_box.rs b/src/widgets/spin_box.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1e8317bb24180d22e96091e7e7425acff624f02c
--- /dev/null
+++ b/src/widgets/spin_box.rs
@@ -0,0 +1,352 @@
+use std::{fmt::Debug, fmt::Formatter, sync::Arc};
+
+use crate::{
+    core::{
+        render_command::RenderCommand,
+        rsx,
+        styles::{Corner, Style, Units},
+        widget, Bound, Children, Color, EventType, MutableBound, OnEvent, WidgetProps,
+    },
+    widgets::{Button, ChangeEvent},
+};
+use kayak_core::{
+    styles::{LayoutType, StyleProp},
+    CursorIcon, OnLayout,
+};
+use kayak_render_macros::use_state;
+
+use crate::widgets::{Background, Clip, OnChange, Text};
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub enum SpinBoxStyle {
+    Horizontal,
+    Vertical,
+}
+
+impl Default for SpinBoxStyle {
+    fn default() -> Self {
+        SpinBoxStyle::Horizontal
+    }
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub struct SpinBoxProps {
+    /// If true, prevents the widget from being focused (and consequently edited)
+    pub disabled: bool,
+    /// A callback for when the text value was changed
+    pub on_change: Option<OnChange>,
+    /// The text to display when the user input is empty
+    pub placeholder: Option<String>,
+    /// Whether spinbox is horizontally or vertically aligned.
+    pub spin_button_style: SpinBoxStyle,
+    /// The user input
+    ///
+    /// This is a controlled state. You _must_ set this to the value to you wish to be displayed.
+    /// You can use the [`on_change`] callback to update this prop as the user types.
+    pub value: String,
+    pub styles: Option<Style>,
+    /// Text on increment button defaults to `>`
+    pub incr_str: String,
+    /// Text on decrement button defaults to `<`
+    pub decr_str: String,
+    /// Events on increment button press
+    pub on_incr_event: Option<OnEvent>,
+    /// Events on decrement button press
+    pub on_decr_event: Option<OnEvent>,
+    /// Events for text edit
+    pub on_event: Option<OnEvent>,
+    /// Minimal value
+    pub min_val: f32,
+    /// Maximal value
+    pub max_val: f32,
+    pub children: Option<Children>,
+    pub on_layout: Option<OnLayout>,
+    pub focusable: Option<bool>,
+}
+
+impl SpinBoxProps {
+    pub fn get_float(&self) -> f32 {
+        self.value.parse::<f32>().unwrap_or_default()
+    }
+
+    pub fn get_int(&self) -> i16 {
+        let temp_float = self.get_float();
+        if temp_float > f32::from(i16::MAX) {
+            i16::MAX
+        } else if temp_float < f32::from(i16::MIN) {
+            i16::MIN
+        } else {
+            temp_float.round() as i16
+        }
+    }
+}
+
+impl Default for SpinBoxProps {
+    fn default() -> SpinBoxProps {
+        SpinBoxProps {
+            incr_str: "+".into(),
+            decr_str: "-".into(),
+            disabled: Default::default(),
+            on_change: Default::default(),
+            placeholder: Default::default(),
+            value: Default::default(),
+            styles: Default::default(),
+            spin_button_style: Default::default(),
+            children: Default::default(),
+            on_incr_event: Default::default(),
+            on_decr_event: Default::default(),
+            on_event: Default::default(),
+            min_val: f32::MIN,
+            max_val: f32::MAX,
+            on_layout: Default::default(),
+            focusable: Default::default(),
+        }
+    }
+}
+
+impl WidgetProps for SpinBoxProps {
+    fn get_children(&self) -> Option<Children> {
+        self.children.clone()
+    }
+
+    fn set_children(&mut self, children: Option<Children>) {
+        self.children = children;
+    }
+
+    fn get_styles(&self) -> Option<Style> {
+        self.styles.clone()
+    }
+
+    fn get_on_event(&self) -> Option<OnEvent> {
+        self.on_event.clone()
+    }
+
+    fn get_on_layout(&self) -> Option<OnLayout> {
+        self.on_layout.clone()
+    }
+
+    fn get_focusable(&self) -> Option<bool> {
+        Some(!self.disabled)
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct FocusSpinbox(pub bool);
+
+#[widget]
+/// A widget that displays a spinnable text field
+///
+/// # Props
+///
+/// __Type:__ [`SpinBoxProps`]
+///
+/// | Common Prop | Accepted |
+/// | :---------: | :------: |
+/// | `children`  | ✅        |
+/// | `styles`    | ✅        |
+/// | `on_event`  | ✅        |
+/// | `on_layout` | ✅        |
+/// | `focusable` | ✅        |
+///
+pub fn SpinBox(props: SpinBoxProps) {
+    let SpinBoxProps {
+        on_change,
+        placeholder,
+        value,
+        max_val,
+        min_val,
+        spin_button_style,
+        ..
+    } = props.clone();
+
+    props.styles = Some(
+        Style::default()
+            // Required styles
+            .with_style(Style {
+                render_command: RenderCommand::Layout.into(),
+                ..Default::default()
+            })
+            // Apply any prop-given styles
+            .with_style(&props.styles)
+            // If not set by props, apply these styles
+            .with_style(Style {
+                top: Units::Pixels(0.0).into(),
+                bottom: Units::Pixels(0.0).into(),
+                height: Units::Pixels(26.0).into(),
+                cursor: CursorIcon::Text.into(),
+                ..Default::default()
+            }),
+    );
+
+    let background_styles = Style {
+        background_color: Color::new(0.176, 0.196, 0.215, 1.0).into(),
+        border_radius: Corner::all(5.0).into(),
+        height: Units::Pixels(26.0).into(),
+        padding_left: Units::Pixels(5.0).into(),
+        padding_right: Units::Pixels(5.0).into(),
+        ..Default::default()
+    };
+
+    let has_focus = context.create_state(FocusSpinbox(false)).unwrap();
+
+    let mut current_value = value.clone();
+    let cloned_on_change = on_change.clone();
+    let cloned_has_focus = has_focus.clone();
+
+    props.on_event = Some(OnEvent::new(move |_, event| match event.event_type {
+        EventType::CharInput { c } => {
+            if !cloned_has_focus.get().0 {
+                return;
+            }
+            if is_backspace(c) {
+                if !current_value.is_empty() {
+                    current_value.truncate(current_value.len() - 1);
+                }
+            } else if !c.is_control() {
+                current_value.push(c);
+            }
+            if let Some(on_change) = cloned_on_change.as_ref() {
+                if let Ok(mut on_change) = on_change.0.write() {
+                    on_change(ChangeEvent {
+                        value: current_value.clone(),
+                    });
+                }
+            }
+        }
+        EventType::Focus => cloned_has_focus.set(FocusSpinbox(true)),
+        EventType::Blur => cloned_has_focus.set(FocusSpinbox(false)),
+        _ => {}
+    }));
+
+    let text_styles = if value.is_empty() || (has_focus.get().0 && value.is_empty()) {
+        Style {
+            color: Color::new(0.5, 0.5, 0.5, 1.0).into(),
+            ..Style::default()
+        }
+    } else {
+        Style {
+            width: Units::Stretch(100.0).into(),
+            ..Style::default()
+        }
+    };
+
+    let button_style = match spin_button_style {
+        SpinBoxStyle::Horizontal => Some(Style {
+            height: Units::Pixels(24.0).into(),
+            width: Units::Pixels(24.0).into(),
+            ..Default::default()
+        }),
+        SpinBoxStyle::Vertical => Some(Style {
+            height: Units::Pixels(12.0).into(),
+            width: Units::Pixels(24.0).into(),
+
+            ..Default::default()
+        }),
+    };
+
+    let value = if value.is_empty() {
+        placeholder.unwrap_or_else(|| value.clone())
+    } else {
+        value
+    };
+
+    let row = Style {
+        layout_type: StyleProp::Value(LayoutType::Row),
+        ..Style::default()
+    };
+
+    let col = Style {
+        layout_type: StyleProp::Value(LayoutType::Column),
+        height: Units::Stretch(100.0).into(),
+        width: Units::Pixels(26.0).into(),
+        ..Style::default()
+    };
+
+    let incr_str = props.clone().incr_str;
+    let decr_str = props.clone().decr_str;
+
+    let (spin_value, set_val, _) = use_state!(value);
+    let x = spin_value.parse::<f32>().unwrap_or_default();
+    let decr_fn = set_val.clone();
+    let incr_fn = set_val.clone();
+
+    let incr_event = if let Some(event) = props.clone().on_incr_event {
+        event
+    } else {
+        OnEvent::new(move |_, event| match event.event_type {
+            EventType::Click(_) => {
+                if x >= max_val {
+                    return;
+                }
+                incr_fn((x + 1.0f32).to_string());
+            }
+            _ => {}
+        })
+    };
+
+    let decr_event = if let Some(event) = props.clone().on_decr_event {
+        event
+    } else {
+        OnEvent::new(move |_, event| match event.event_type {
+            EventType::Click(_) => {
+                if x <= min_val {
+                    return;
+                }
+                decr_fn((x - 1.0f32).to_string());
+            }
+            _ => {}
+        })
+    };
+
+    match spin_button_style {
+        SpinBoxStyle::Horizontal => {
+            rsx! {
+                <Background styles={Some(background_styles)}>
+                    <Clip styles={Some(row)}>
+                        <Button styles={button_style} on_event={Some(decr_event)}>
+                            <Text content={decr_str} />
+                        </Button>
+                        <Text
+                            content={spin_value}
+                            size={14.0}
+                            styles={Some(text_styles)}
+                        />
+                        <Button styles={button_style} on_event={Some(incr_event)}>
+                            <Text content={incr_str} />
+                        </Button>
+                    </Clip>
+                </Background>
+            }
+        }
+        SpinBoxStyle::Vertical => {
+            rsx! {
+                <Background styles={Some(background_styles)}>
+
+                    <Clip styles={Some(row)}>
+                        <Text
+                            content={spin_value}
+                            size={14.0}
+                            styles={Some(text_styles)}
+                        />
+                        <Clip styles={Some(col)}>
+
+                            <Button styles={button_style} on_event={Some(incr_event)}>
+                                <Text content={incr_str} size={11.0} />
+                            </Button>
+                            <Button styles={button_style} on_event={Some(decr_event)}>
+                                <Text content={decr_str} size={11.0}/>
+                            </Button>
+                        </Clip>
+                    </Clip>
+                </Background>
+            }
+        }
+    }
+}
+
+/// Checks if the given character contains the "Backspace" sequence
+///
+/// Context: [Wikipedia](https://en.wikipedia.org/wiki/Backspace#Common_use)
+fn is_backspace(c: char) -> bool {
+    c == '\u{8}' || c == '\u{7f}'
+}
diff --git a/src/widgets/text_box.rs b/src/widgets/text_box.rs
index f872d2ec0318624e27c48225a2951f4ca5f82fe6..e9cfc8ad5e4d88e315f0da6d7ff5de0c2424002c 100644
--- a/src/widgets/text_box.rs
+++ b/src/widgets/text_box.rs
@@ -1,13 +1,15 @@
-use crate::core::{
-    render_command::RenderCommand,
-    rsx,
-    styles::{Corner, Style, Units},
-    widget, Bound, Children, Color, EventType, MutableBound, OnEvent, WidgetProps,
+use crate::{
+    core::{
+        render_command::RenderCommand,
+        rsx,
+        styles::{Corner, Style, Units},
+        widget, Bound, Children, Color, EventType, MutableBound, OnEvent, WidgetProps,
+    },
+    widgets::ChangeEvent,
 };
 use kayak_core::{CursorIcon, OnLayout};
-use std::sync::{Arc, RwLock};
 
-use crate::widgets::{Background, Clip, Text};
+use crate::widgets::{Background, Clip, OnChange, Text};
 
 /// Props used by the [`TextBox`] widget
 #[derive(Default, Debug, PartialEq, Clone)]
@@ -56,32 +58,6 @@ impl WidgetProps for TextBoxProps {
     }
 }
 
-#[derive(Debug, Clone, PartialEq)]
-pub struct ChangeEvent {
-    pub value: String,
-}
-
-#[derive(Clone)]
-pub struct OnChange(pub Arc<RwLock<dyn FnMut(ChangeEvent) + Send + Sync + 'static>>);
-
-impl OnChange {
-    pub fn new<F: FnMut(ChangeEvent) + Send + Sync + 'static>(f: F) -> OnChange {
-        OnChange(Arc::new(RwLock::new(f)))
-    }
-}
-
-impl PartialEq for OnChange {
-    fn eq(&self, _other: &Self) -> bool {
-        true
-    }
-}
-
-impl std::fmt::Debug for OnChange {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_tuple("OnChange").finish()
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub struct Focus(pub bool);