From d0c4abd38b00ef16c77d914da14236bcb7e261ad Mon Sep 17 00:00:00 2001 From: Elias Stepanik <40958815+eliasstepanik@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:07:12 +0200 Subject: [PATCH] Add JSON-configurable options menu --- client/Cargo.toml | 1 + client/assets/options_menu.json | 8 ++ client/src/plugins/ui/mod.rs | 2 + client/src/plugins/ui/options/mod.rs | 118 +++++++++++++++++++++++++++ client/src/plugins/ui/ui_plugin.rs | 2 + 5 files changed, 131 insertions(+) create mode 100644 client/assets/options_menu.json create mode 100644 client/src/plugins/ui/options/mod.rs diff --git a/client/Cargo.toml b/client/Cargo.toml index a373ba7..83422ff 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -12,6 +12,7 @@ build = "build.rs" bevy = { version = "0.16.1", features = ["jpeg", "trace_tracy", "trace_tracy_memory", "serialize"] } rand = "0.8.5" serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" toml = "0.8" big_space = { git = "https://github.com/aevyrie/big_space.git", rev = "5345af11d4ce138bacf5a9a3ab53d1c3b3b103c7" } noise = "0.9.0" diff --git a/client/assets/options_menu.json b/client/assets/options_menu.json new file mode 100644 index 0000000..635424c --- /dev/null +++ b/client/assets/options_menu.json @@ -0,0 +1,8 @@ +{ + "items": [ + { "label": "Toggle Wireframe", "action": "toggle_wireframe" }, + { "label": "Toggle Grid", "action": "toggle_grid" }, + { "label": "Toggle Edit Mode", "action": "toggle_edit_mode" }, + { "label": "Exit", "action": "exit" } + ] +} diff --git a/client/src/plugins/ui/mod.rs b/client/src/plugins/ui/mod.rs index 5eb42ed..6b6388d 100644 --- a/client/src/plugins/ui/mod.rs +++ b/client/src/plugins/ui/mod.rs @@ -1,2 +1,4 @@ pub mod systems; pub mod ui_plugin; + +pub mod options; diff --git a/client/src/plugins/ui/options/mod.rs b/client/src/plugins/ui/options/mod.rs new file mode 100644 index 0000000..2b983f6 --- /dev/null +++ b/client/src/plugins/ui/options/mod.rs @@ -0,0 +1,118 @@ +use crate::plugins::environment::systems::voxels::structure::SparseVoxelOctree; +use crate::plugins::input::systems::voxels::VoxelEditMode; +use bevy::prelude::*; +use serde::Deserialize; + +#[derive(Deserialize, Resource)] +pub struct OptionsMenuConfig { + pub items: Vec, +} + +#[derive(Deserialize, Clone)] +pub struct OptionItem { + pub label: String, + pub action: String, +} + +#[derive(Component)] +struct MenuButton { + action: String, +} + +pub struct OptionsMenuPlugin; +impl Plugin for OptionsMenuPlugin { + fn build(&self, app: &mut App) { + let config: OptionsMenuConfig = load_config(); + app.insert_resource(config); + app.add_systems(Startup, setup_menu); + app.add_systems(Update, handle_buttons); + } +} + +fn load_config() -> OptionsMenuConfig { + let path = "client/assets/options_menu.json"; + let data = std::fs::read_to_string(path).expect("failed to read options_menu.json"); + serde_json::from_str(&data).expect("invalid options_menu.json") +} + +fn setup_menu( + mut commands: Commands, + config: Res, + asset_server: Res, +) { + commands + .spawn(NodeBundle { + style: Style { + position_type: PositionType::Absolute, + left: Val::Px(10.0), + top: Val::Px(10.0), + flex_direction: FlexDirection::Column, + ..default() + }, + background_color: Color::rgba(0.1, 0.1, 0.1, 0.5).into(), + ..default() + }) + .with_children(|parent| { + for item in config.items.iter() { + parent + .spawn(( + ButtonBundle { + style: Style { + margin: UiRect::all(Val::Px(2.0)), + padding: UiRect::all(Val::Px(4.0)), + ..default() + }, + background_color: Color::GRAY.into(), + ..default() + }, + MenuButton { + action: item.action.clone(), + }, + )) + .with_children(|p| { + p.spawn(TextBundle::from_section( + item.label.clone(), + TextStyle { + font: asset_server.load("fonts/minecraft_font.ttf"), + font_size: 16.0, + color: Color::WHITE, + }, + )); + }); + } + }); +} + +fn handle_buttons( + mut interactions: Query<(&Interaction, &MenuButton), (Changed, With