use bevy::{ input::mouse::{MouseScrollUnit, MouseWheel}, input_focus::InputFocus, picking::hover::HoverMap, prelude::*, }; mod components; #[derive(Component)] pub(super) struct DebugConsole; #[derive(Component)] struct TextInput; use bevy_ui_text_input::TextSubmitEvent; pub(super) use components::console; use components::{Content, Prompt}; use crate::game::debug::DebugEvent; use super::{ConsoleEvent, ConsoleLog, ConsoleState, OPEN_CONSOLE_DEFAULT, cli::respond}; // stolen from scrolling example pub fn update_scroll_position( mut mouse_wheel_events: EventReader, hover_map: Res, mut scrolled_node_query: Query<&mut ScrollPosition>, ) { for mouse_wheel_event in mouse_wheel_events.read() { let (dx, dy) = match mouse_wheel_event.unit { MouseScrollUnit::Line => (mouse_wheel_event.x * 18., mouse_wheel_event.y * 18.), MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y), }; for (_pointer, pointer_map) in hover_map.iter() { for (entity, _hit) in pointer_map.iter() { if let Ok(mut scroll_position) = scrolled_node_query.get_mut(*entity) { scroll_position.offset_x -= dx; scroll_position.offset_y -= dy; } } } } } pub fn autofocus(mut input_focus: ResMut, prompt: Single>) { input_focus.set(*prompt); } pub fn autoscroll(mut scrollables: Single<&mut ScrollPosition, With>) { scrollables.offset_y = f32::MAX; } pub fn handle_open_console( kb_input: Res>, mut console_open_state: ResMut>, ) { if kb_input.pressed(OPEN_CONSOLE_DEFAULT) { console_open_state.set(ConsoleState::Open); } } pub fn process_prompt( mut log: ResMut, mut submit_reader: EventReader, mut debug_event_writer: EventWriter, prompt: Single>, ) { for submit in submit_reader.read() { if submit.entity == *prompt && !submit.text.trim().is_empty() { if submit.text.trim() != "close" { log.input(&submit.text); } match respond(&submit.text) { Ok(debug_ev) => { debug_event_writer.write(debug_ev); } Err(e) => log.error(&e), } } } } pub fn update_content( mut c: Commands, content: Single>, mut log: ResMut, asset_server: Res, mut scrollables: Single<&mut ScrollPosition, With>, ) { c.entity(*content).with_children(|parent| { for item in log.unread() { match dbg!(item) { ConsoleEvent::Input(s) => { parent.spawn(components::input(s.to_string(), &asset_server)); } ConsoleEvent::Output(s) => { parent.spawn(components::output(s.to_string(), &asset_server)); } ConsoleEvent::Error(s) => { parent.spawn(components::error( // dirty hack so they're not called subcommands s.replace("subcommand", "command").to_string(), &asset_server, )); } _ => {} }; } }); scrollables.offset_y = f32::MAX; }