diff --git a/CHANGELOG.md b/CHANGELOG.md index 15eb4425..c5b813dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## Unreleased - Add `bevy_flair` stylesheets +- Add `bevy-inspector-egui` +- Update state management to use bevy `State` instead of a custom `StateMachine` ## 0.1.1 diff --git a/Cargo.lock b/Cargo.lock index a4190f03..394b8042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,22 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ab_glyph" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + [[package]] name = "accesskit" version = "0.17.1" @@ -194,6 +210,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arboard" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" +dependencies = [ + "clipboard-win", + "core-graphics", + "image", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "parking_lot", + "windows-sys 0.48.0", + "x11rb", +] + [[package]] name = "ariadne" version = "0.5.0" @@ -344,6 +378,51 @@ dependencies = [ "bevy_internal", ] +[[package]] +name = "bevy-inspector-egui" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36172627eb6fd8586600972bcbba2880ed6f59e4e243dcf2ed7ff68d987577ce" +dependencies = [ + "bevy-inspector-egui-derive", + "bevy_app", + "bevy_asset", + "bevy_color", + "bevy_core", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_egui", + "bevy_hierarchy", + "bevy_image", + "bevy_log", + "bevy_math", + "bevy_pbr", + "bevy_reflect", + "bevy_render", + "bevy_state", + "bevy_time", + "bevy_utils", + "bevy_window", + "bytemuck", + "disqualified", + "egui", + "fuzzy-matcher", + "image", + "smallvec", + "winit", +] + +[[package]] +name = "bevy-inspector-egui-derive" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afc67826e0a4347414545e022e748f42550a577a502b26af44e6d03742c9266" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bevy_a11y" version = "0.15.1" @@ -595,6 +674,41 @@ dependencies = [ "syn", ] +[[package]] +name = "bevy_egui" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "954fbe8551af4b40767ea9390ec7d32fe1070a6ab55d524cf0868c17f8469a55" +dependencies = [ + "arboard", + "bevy_app", + "bevy_asset", + "bevy_derive", + "bevy_ecs", + "bevy_image", + "bevy_input", + "bevy_log", + "bevy_math", + "bevy_reflect", + "bevy_render", + "bevy_time", + "bevy_utils", + "bevy_window", + "bevy_winit", + "bytemuck", + "crossbeam-channel", + "egui", + "encase", + "js-sys", + "log", + "thread_local", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-types", + "winit", +] + [[package]] name = "bevy_encase_derive" version = "0.15.1" @@ -1572,6 +1686,18 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cc" version = "1.2.10" @@ -1686,6 +1812,15 @@ dependencies = [ "libloading", ] +[[package]] +name = "clipboard-win" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +dependencies = [ + "error-code", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -2134,12 +2269,43 @@ dependencies = [ "dtoa", ] +[[package]] +name = "ecolor" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775cfde491852059e386c4e1deb4aef381c617dc364184c6f6afee99b87c402b" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "egui" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53eafabcce0cb2325a59a98736efe0bf060585b437763f8c476957fb274bb974" +dependencies = [ + "ahash", + "emath", + "epaint", + "nohash-hasher", +] + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "emath" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1fe0049ce51d0fb414d029e668dd72eb30bc2b739bf34296ed97bd33df544f3" +dependencies = [ + "bytemuck", +] + [[package]] name = "ena" version = "0.14.3" @@ -2181,6 +2347,28 @@ dependencies = [ "syn", ] +[[package]] +name = "epaint" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a32af8da821bd4f43f2c137e295459ee2e1661d87ca8779dfa0eaf45d870e20f" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "nohash-hasher", + "parking_lot", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483440db0b7993cf77a20314f08311dbe95675092405518c0677aa08c151a3ea" + [[package]] name = "equivalent" version = "1.0.1" @@ -2207,6 +2395,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "error-code" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + [[package]] name = "euclid" version = "0.22.11" @@ -2385,6 +2579,15 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -2708,6 +2911,7 @@ dependencies = [ "byteorder-lite", "num-traits", "png", + "tiff", ] [[package]] @@ -2830,6 +3034,12 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.77" @@ -3178,6 +3388,12 @@ dependencies = [ "libc", ] +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "noise" version = "0.9.0" @@ -3601,6 +3817,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "owned_ttf_parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +dependencies = [ + "ttf-parser 0.25.1", +] + [[package]] name = "parking" version = "2.2.1" @@ -3878,6 +4103,15 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.38" @@ -4167,6 +4401,7 @@ name = "rsmc" version = "0.1.1" dependencies = [ "bevy", + "bevy-inspector-egui", "bevy_flair", "bevy_fps_controller", "bevy_mod_raycast", @@ -4276,12 +4511,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "selectors" version = "0.26.0" @@ -4440,6 +4694,31 @@ dependencies = [ "serde", ] +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.8.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + [[package]] name = "smol_str" version = "0.2.2" @@ -4488,6 +4767,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + [[package]] name = "subtle" version = "2.6.1" @@ -4616,6 +4901,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -4625,6 +4921,31 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinyvec" version = "1.8.1" @@ -4756,6 +5077,12 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + [[package]] name = "twox-hash" version = "1.6.3" @@ -4963,6 +5290,115 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.8.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.8.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" +dependencies = [ + "rustix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" +dependencies = [ + "bitflags 2.8.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" +dependencies = [ + "bitflags 2.8.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" +dependencies = [ + "bitflags 2.8.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.77" @@ -4983,6 +5419,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "wgpu" version = "23.0.1" @@ -5348,6 +5790,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5614,6 +6065,7 @@ version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d74280aabb958072864bff6cfbcf9025cf8bfacdde5e32b5e12920ef703b0f" dependencies = [ + "ahash", "android-activity", "atomic-waker", "bitflags 2.8.0", @@ -5628,6 +6080,7 @@ dependencies = [ "dpi", "js-sys", "libc", + "memmap2", "ndk 0.9.0", "objc2", "objc2-app-kit", @@ -5639,11 +6092,17 @@ dependencies = [ "raw-window-handle", "redox_syscall 0.4.1", "rustix", + "sctk-adwaita", + "smithay-client-toolkit", "smol_str", "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", "web-sys", "web-time", "windows-sys 0.52.0", @@ -5693,6 +6152,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +[[package]] +name = "xcursor" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" + [[package]] name = "xkbcommon-dl" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index f8bc0570..1c307505 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ serde-big-array = "0.5.1" chrono = "0.4.38" rayon = "1.10.0" bevy_flair = "0.1.0" +bevy-inspector-egui = "0.28.1" [profile.dev.package."*"] opt-level = 3 @@ -38,4 +39,5 @@ path = "src/server/main.rs" [features] wireframe = [] +debug_ui = [] diff --git a/assets/chat.css b/assets/chat.css index b2314fdf..0c590f74 100644 --- a/assets/chat.css +++ b/assets/chat.css @@ -17,6 +17,7 @@ #chat_message_input { margin: 0px; + margin-top: 15px; padding: 10px; height: 20px; display: flex; diff --git a/src/client/chat/components.rs b/src/client/chat/components.rs index c2569eb0..c93cf7fe 100644 --- a/src/client/chat/components.rs +++ b/src/client/chat/components.rs @@ -1,14 +1,10 @@ use crate::prelude::*; #[derive(Component)] -pub struct ChatMessageContainer { - pub focused: bool, -} +pub struct ChatMessageContainer; #[derive(Component)] -pub struct ChatMessageInputElement { - pub focused: bool, -} +pub struct ChatMessageInputElement; #[derive(Component)] pub struct ChatMessageElement; diff --git a/src/client/chat/events.rs b/src/client/chat/events.rs index 03fcb6b2..12799a5a 100644 --- a/src/client/chat/events.rs +++ b/src/client/chat/events.rs @@ -11,13 +11,3 @@ pub struct ChatMessageSendEvent(pub String); #[derive(Event)] pub struct ChatClearEvent; - -pub enum FocusState { - Focus, - Unfocus, -} - -#[derive(Event)] -pub struct ChatFocusStateChangeEvent { - pub state: FocusState, -} diff --git a/src/client/chat/mod.rs b/src/client/chat/mod.rs index 66eeb96d..76887ac9 100644 --- a/src/client/chat/mod.rs +++ b/src/client/chat/mod.rs @@ -15,21 +15,28 @@ impl Plugin for ChatPlugin { app.add_systems( Update, ( - systems::process_chat_input_system, - systems::handle_chat_focus_player_controller_events, - systems::handle_window_focus_events, - systems::focus_chat_input_system, - systems::send_messages_system, - systems::handle_focus_events, systems::handle_chat_message_sync_event, systems::add_message_to_chat_container_system, - systems::handle_chat_clear_events_system, + systems::chat_state_transition_system, ), ); + app.add_systems( + Update, + ( + systems::process_chat_input_system, + systems::send_messages_system, + systems::handle_chat_clear_events_system, + ) + .run_if(in_state(GameState::Chatting)), + ); + + app.add_systems(OnEnter(GameState::Chatting), systems::focus_chat_system); + app.add_systems(OnExit(GameState::Chatting), systems::unfocus_chat_system); + app.insert_resource(resources::ChatHistory::default()); app.insert_resource(resources::ChatState::default()); + app.add_event::(); - app.add_event::(); app.add_event::(); app.add_event::(); app.add_event::(); diff --git a/src/client/chat/systems.rs b/src/client/chat/systems.rs index 0c3bed07..3c724c12 100644 --- a/src/client/chat/systems.rs +++ b/src/client/chat/systems.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use bevy::input::{keyboard::KeyboardInput, ButtonState}; use bevy_flair::style::components::{ClassList, NodeStyleSheet}; -use chat_events::{ChatFocusStateChangeEvent, ChatMessageSendEvent, FocusState}; +use chat_events::ChatMessageSendEvent; const MESSAGE_PROMPT: &str = "> "; @@ -17,7 +17,7 @@ pub fn setup_chat_container(mut commands: Commands, asset_server: Res, - mut chat_container_query: Query< - (&mut ClassList, &mut chat_components::ChatMessageContainer), - Without, - >, - mut chat_input_query: Query< - ( - &mut ClassList, - &mut chat_components::ChatMessageInputElement, - ), - Without, - >, - mut controller_query: Query<&mut FpsController>, - mut window_query: Query<&mut Window>, -) { - if let Ok(mut window) = window_query.get_single_mut() { - if let ( - Ok((mut container_classes, mut chat_container)), - Ok((mut input_classes, mut chat_input)), - ) = ( - chat_container_query.get_single_mut(), - chat_input_query.get_single_mut(), - ) { - for event in focus_change_events.read() { - match event.state { - FocusState::Focus => { - info!("Handling focus state"); - container_classes.add_class("focused"); - container_classes.remove_class("unfocused"); - chat_container.focused = true; - - input_classes.add_class("focused"); - input_classes.remove_class("unfocused"); - chat_input.focused = true; - - for mut controller in &mut controller_query.iter_mut() { - controller.enable_input = false; - } - } - FocusState::Unfocus => { - info!("Handling unfocus state"); - container_classes.remove_class("focused"); - container_classes.add_class("unfocused"); - chat_container.focused = false; - - input_classes.remove_class("focused"); - input_classes.add_class("unfocused"); - chat_input.focused = false; - - for mut controller in &mut controller_query.iter_mut() { - controller.enable_input = true; - } - - window.cursor_options.grab_mode = CursorGrabMode::Locked; - window.cursor_options.visible = false; - } - } - } - } - } -} - pub fn send_messages_system( mut client: ResMut, mut event_reader: EventReader, @@ -110,83 +47,38 @@ pub fn send_messages_system( } } -pub fn focus_chat_input_system( - mouse_button_input: Res>, +pub fn chat_state_transition_system( keyboard_input: Res>, - mut chat_input_query: Query<&mut chat_components::ChatMessageInputElement>, - mut focus_change_events: EventWriter, + current_state: Res>, + mut next_state: ResMut>, mut chat_state: ResMut, ) { - if let Ok(chat_input_component) = chat_input_query.get_single_mut() { - if mouse_button_input.just_pressed(MouseButton::Left) { - info!("Unfocusing chat via Left click"); - focus_change_events.send(ChatFocusStateChangeEvent { - state: FocusState::Unfocus, - }); - } - if keyboard_input.just_pressed(KeyCode::KeyT) && !chat_input_component.focused { - info!("Focusing chat via KeyT"); - focus_change_events.send(ChatFocusStateChangeEvent { - state: FocusState::Focus, - }); + let current_state_value = current_state.get(); + let mut next_state_value = current_state_value.clone(); + + if keyboard_input.just_pressed(KeyCode::KeyT) { + info!("Focusing chat via KeyT"); + if *current_state_value == GameState::Playing { chat_state.just_focused = true; - } - if keyboard_input.just_pressed(KeyCode::Escape) && chat_input_component.focused { - info!("Unfocusing chat via Escape"); - focus_change_events.send(ChatFocusStateChangeEvent { - state: FocusState::Unfocus, - }); + next_state_value = GameState::Chatting; } } -} - -pub fn handle_window_focus_events( - mut window_query: Query<&mut Window>, - mut focus_events: EventReader, -) { - if let Ok(mut window) = window_query.get_single_mut() { - for event in focus_events.read() { - match event.state { - FocusState::Unfocus => { - window.cursor_options.grab_mode = CursorGrabMode::Locked; - window.cursor_options.visible = false; - } - FocusState::Focus => {} - } - } + if keyboard_input.just_pressed(KeyCode::Escape) && *current_state_value == GameState::Chatting { + info!("Unfocusing chat via Escape"); + next_state_value = GameState::Playing; } -} - -pub fn handle_chat_focus_player_controller_events( - mut focus_change_events: EventReader, - mut controller_query: Query<&mut FpsController>, -) { - for event in focus_change_events.read() { - info!("Received event to change player controller focus"); - let enable_input = match event.state { - FocusState::Focus => false, - FocusState::Unfocus => true, - }; - - for mut controller in &mut controller_query.iter_mut() { - controller.enable_input = enable_input; - } - } + next_state.set(next_state_value); } pub fn process_chat_input_system( mut evr_kbd: EventReader, - mut chat_input_query: Query<(&mut Text, &mut chat_components::ChatMessageInputElement)>, + mut chat_input_query: Query<&mut Text, With>, mut send_event_writer: EventWriter, mut chat_state: ResMut, mut chat_clear_writer: EventWriter, ) { - if let Ok((mut text, input_component)) = chat_input_query.get_single_mut() { - if !input_component.focused { - return; - } - + if let Ok(mut text) = chat_input_query.get_single_mut() { let mut chat_input_value = text.0.clone(); for event in evr_kbd.read() { @@ -195,6 +87,7 @@ pub fn process_chat_input_system( } if chat_state.just_focused { + // Hack to prevent 'T' from being added to the chat input upon focus chat_state.just_focused = false; continue; } @@ -287,6 +180,64 @@ pub fn handle_chat_clear_events_system( } } +pub fn unfocus_chat_system( + mut chat_container_query: Query< + &mut ClassList, + ( + With, + Without, + ), + >, + mut chat_input_query: Query< + &mut ClassList, + ( + With, + Without, + ), + >, +) { + if let (Ok(mut container_classes), Ok(mut input_classes)) = ( + chat_container_query.get_single_mut(), + chat_input_query.get_single_mut(), + ) { + info!("Handling unfocus state"); + container_classes.remove_class("focused"); + container_classes.add_class("unfocused"); + + input_classes.remove_class("focused"); + input_classes.add_class("unfocused"); + } +} + +pub fn focus_chat_system( + mut chat_container_query: Query< + &mut ClassList, + ( + With, + Without, + ), + >, + mut chat_input_query: Query< + &mut ClassList, + ( + With, + Without, + ), + >, +) { + if let (Ok(mut container_classes), Ok(mut input_classes)) = ( + chat_container_query.get_single_mut(), + chat_input_query.get_single_mut(), + ) { + info!("Handling focus state"); + container_classes.add_class("focused"); + container_classes.remove_class("unfocused"); + + input_classes.add_class("focused"); + input_classes.remove_class("unfocused"); + } +} + #[cfg(test)] mod tests { use super::*; @@ -304,7 +255,7 @@ mod tests { app.world_mut().spawn(( ScrollPosition::default(), - chat_components::ChatMessageContainer { focused: false }, + chat_components::ChatMessageContainer, )); let mut event_writer = app @@ -353,7 +304,7 @@ mod tests { .insert_resource(Events::::default()); app.world_mut() - .spawn((chat_components::ChatMessageContainer { focused: false },)) + .spawn(chat_components::ChatMessageContainer) .with_children(|parent| { parent.spawn(( Node::default(), diff --git a/src/client/gui/mod.rs b/src/client/gui/mod.rs index 58dc9a94..6394826e 100644 --- a/src/client/gui/mod.rs +++ b/src/client/gui/mod.rs @@ -2,6 +2,9 @@ pub mod components; pub mod events; pub mod systems; +#[cfg(feature = "debug_ui")] +use bevy_inspector_egui::quick::WorldInspectorPlugin; + use crate::prelude::*; pub struct GuiPlugin; @@ -9,5 +12,16 @@ pub struct GuiPlugin; impl Plugin for GuiPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, gui_systems::setup_gui_system); + + #[cfg(feature = "debug_ui")] + { + app.add_plugins(WorldInspectorPlugin::default()); + app.add_systems(Update, gui_systems::handle_debug_state_transition_system); + + app.add_systems( + OnEnter(GameState::Debugging), + gui_systems::handle_enter_debug_state_system, + ); + } } } diff --git a/src/client/gui/systems.rs b/src/client/gui/systems.rs index 78330317..64293b45 100644 --- a/src/client/gui/systems.rs +++ b/src/client/gui/systems.rs @@ -20,3 +20,24 @@ pub fn setup_gui_system(mut commands: Commands, asset_server: Res) parent.spawn((Text::new("RSMC - Pre Alpha"), Name::new("menu_title"))); }); } + +pub fn handle_debug_state_transition_system( + current_state: Res>, + mut next_state: ResMut>, + key_input: Res>, +) { + if key_input.just_pressed(KeyCode::Tab) { + match *current_state.get() { + GameState::Playing => next_state.set(GameState::Debugging), + GameState::Chatting => next_state.set(GameState::Debugging), + GameState::Debugging => next_state.set(GameState::Playing), + } + } +} + +pub fn handle_enter_debug_state_system(mut window_query: Query<&mut Window>) { + if let Ok(mut window) = window_query.get_single_mut() { + window.cursor_options.grab_mode = CursorGrabMode::None; + window.cursor_options.visible = true; + } +} diff --git a/src/client/main.rs b/src/client/main.rs index c509141d..dd5c141f 100644 --- a/src/client/main.rs +++ b/src/client/main.rs @@ -9,6 +9,7 @@ mod networking; mod player; mod remote_player; mod scene; +mod states; mod terrain; use bevy::color::palettes::css::WHITE; @@ -48,6 +49,7 @@ fn main() { remote_player::RemotePlayerPlugin, chat::ChatPlugin, )) + .insert_state(GameState::Playing) .insert_resource(WireframeConfig { #[cfg(not(feature = "wireframe"))] global: false, diff --git a/src/client/player/mod.rs b/src/client/player/mod.rs index 55528fc3..69b79ac2 100644 --- a/src/client/player/mod.rs +++ b/src/client/player/mod.rs @@ -35,15 +35,35 @@ impl Plugin for PlayerPlugin { Update, ( player_systems::handle_controller_movement_system, + player_systems::handle_player_collider_events_system, + ) + .run_if(player_resources::PlayerSpawned::is_spawned), + ); + app.add_systems( + Update, + ( player_systems::manage_cursor_system, player_systems::handle_mouse_events_system, player_systems::handle_keyboard_events_system, player_systems::raycast_system, player_systems::handle_block_update_events, player_systems::broadcast_player_attributes_system, - player_systems::handle_player_collider_events_system, ) - .run_if(player_resources::PlayerSpawned::is_spawned), + .run_if(player_resources::PlayerSpawned::is_spawned) + .run_if(in_state(GameState::Playing)), + ); + + app.add_systems( + OnEnter(GameState::Playing), + ( + player_systems::activate_fps_controller_system, + player_systems::lock_cursor_system, + ), + ); + + app.add_systems( + OnExit(GameState::Playing), + player_systems::deactivate_fps_controller_system, ); } } diff --git a/src/client/player/systems/controller.rs b/src/client/player/systems/controller.rs index 882a6c0a..9a39c41a 100644 --- a/src/client/player/systems/controller.rs +++ b/src/client/player/systems/controller.rs @@ -83,3 +83,22 @@ pub fn handle_controller_movement_system( last_position.0 = controller_position.floor(); } } + +pub fn activate_fps_controller_system(mut controller_query: Query<&mut FpsController>) { + for mut controller in &mut controller_query.iter_mut() { + controller.enable_input = true; + } +} + +pub fn lock_cursor_system(mut window_query: Query<&mut Window>) { + if let Ok(mut window) = window_query.get_single_mut() { + window.cursor_options.grab_mode = CursorGrabMode::Locked; + window.cursor_options.visible = false; + } +} + +pub fn deactivate_fps_controller_system(mut controller_query: Query<&mut FpsController>) { + for mut controller in &mut controller_query.iter_mut() { + controller.enable_input = false; + } +} diff --git a/src/client/player/systems/mouse.rs b/src/client/player/systems/mouse.rs index 58f1c7be..ce81f744 100644 --- a/src/client/player/systems/mouse.rs +++ b/src/client/player/systems/mouse.rs @@ -5,9 +5,10 @@ pub fn manage_cursor_system( key: Res>, mut window_query: Query<&mut Window>, mut controller_query: Query<&mut FpsController>, + current_state: Res>, ) { let mut window = window_query.single_mut(); - if btn.just_pressed(MouseButton::Left) { + if btn.just_pressed(MouseButton::Left) && *current_state.get() != GameState::Debugging { window.cursor_options.grab_mode = CursorGrabMode::Locked; window.cursor_options.visible = false; for mut controller in &mut controller_query { diff --git a/src/client/prelude.rs b/src/client/prelude.rs index 56f903d3..7680f8b5 100644 --- a/src/client/prelude.rs +++ b/src/client/prelude.rs @@ -42,6 +42,7 @@ pub use noise::Perlin; pub use terrain_util::CubeFace; // my crates +pub use crate::states::GameState; pub use rsmc as lib; pub use rsmc::BlockId; pub use rsmc::NetworkingMessage; diff --git a/src/client/states.rs b/src/client/states.rs new file mode 100644 index 00000000..a3f2c4ff --- /dev/null +++ b/src/client/states.rs @@ -0,0 +1,8 @@ +use bevy::prelude::States; + +#[derive(States, Debug, Clone, PartialEq, Eq, Hash)] +pub enum GameState { + Chatting, + Debugging, + Playing, +}