Merge pull request 'widget-focus' (#4) from widget-focus into master
All checks were successful
Build / Build (push) Successful in 55m46s

Reviewed-on: #4
This commit is contained in:
Silas Bartha 2025-04-02 18:36:10 -04:00
commit 57a76e4e46
7 changed files with 55 additions and 49 deletions

View File

@ -2,7 +2,6 @@
[![Crates](https://img.shields.io/crates/v/bevy_terminal_display)](https://crates.io/crates/bevy_terminal_display)
![License](https://img.shields.io/badge/license-0BSD%2FMIT%2FApache-blue.svg)
![Tag](https://img.shields.io/github/v/tag/exvacuum/bevy_terminal_display)
A (very experimental) plugin for the [Bevy](https://bevyengine.org) engine which allows for rendering to a terminal window.
@ -18,12 +17,12 @@ Features Include:
- Log redirection
## Screenshots
![](https://git.soaos.dev/soaos/bevy_terminal_display/plain/doc/screenshot.png)
![](doc/screenshot.png)
## Compatibility
| Crate Version | Bevy Version |
| ------------- | ------------ |
| 0.6 | 0.15 |
| 0.6-0.7 | 0.15 |
| 0.4 | 0.14 |
| 0.2 | 0.13 |
@ -32,7 +31,7 @@ Features Include:
### crates.io
```toml
[dependencies]
bevy_terminal_display = "0.5"
bevy_terminal_display = "0.7"
```
### Using git URL in Cargo.toml

View File

@ -24,7 +24,6 @@ use ratatui::style::Style;
// #[derive(Component, Debug)]
// pub struct TerminalWindow;
/// Marker component for terminal display
#[derive(Component, Debug)]
#[component(on_add = on_add_terminal_display)]
@ -69,8 +68,8 @@ fn on_add_terminal_display(mut world: DeferredWorld, entity: Entity, _id: Compon
image.resize(size);
let image_handle = asset_server.add(image);
let headless_render_source = HeadlessRenderSource::new(&asset_server, image_handle.clone());
let post_process_settings = DitherPostProcessSettings::new(dither_level, &asset_server);
let headless_render_source = HeadlessRenderSource::new(asset_server, image_handle.clone());
let post_process_settings = DitherPostProcessSettings::new(dither_level, asset_server);
world
.commands()
.entity(entity)

View File

@ -20,9 +20,7 @@ impl Default for Terminal {
stdout().execute(EnterAlternateScreen).unwrap();
stdout().execute(EnableMouseCapture).unwrap();
stdout()
.execute(PushKeyboardEnhancementFlags(
KeyboardEnhancementFlags::all(),
))
.execute(PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::all()))
.unwrap();
enable_raw_mode().unwrap();
let mut terminal = ratatui::Terminal::new(CrosstermBackend::new(stdout()))

View File

@ -7,11 +7,7 @@ use bevy::{
use crossterm::event::{read, Event, KeyEvent, KeyEventKind, MediaKeyCode, ModifierKeyCode};
use smol_str::SmolStr;
use super::{
components::DummyWindow,
events::TerminalInputEvent,
resources::EventQueue,
};
use super::{components::DummyWindow, events::TerminalInputEvent, resources::EventQueue};
/// Initializes event queue and thread
pub fn setup_input(mut commands: Commands, event_queue: Res<EventQueue>) {
@ -294,7 +290,7 @@ fn crossterm_keycode_to_bevy_key(
35 => Some(BKey::F35),
_ => None,
},
CKey::Char(c) => Some(BKey::Character(SmolStr::from(c.encode_utf8(&mut [0;4])))),
CKey::Char(c) => Some(BKey::Character(SmolStr::from(c.encode_utf8(&mut [0; 4])))),
CKey::Null => None,
CKey::Esc => Some(BKey::Escape),
CKey::CapsLock => Some(BKey::CapsLock),

View File

@ -3,21 +3,29 @@
//! Bevy plugin which allows a camera to render to a terminal window.
use std::{
fs::OpenOptions, io::{stdout, Write}, path::PathBuf,
fs::OpenOptions,
io::{stdout, Write},
path::PathBuf,
};
use bevy::{
log::{
tracing_subscriber::{self, layer::SubscriberExt, EnvFilter, Layer, Registry},
Level,
}, prelude::*, utils::tracing::subscriber,
},
prelude::*,
utils::tracing::subscriber,
};
use bevy_dither_post_process::DitherPostProcessPlugin;
use bevy_headless_render::HeadlessRenderPlugin;
use color_eyre::config::HookBuilder;
pub use crossterm;
use crossterm::{event::{DisableMouseCapture, PopKeyboardEnhancementFlags}, terminal::{disable_raw_mode, LeaveAlternateScreen}, ExecutableCommand};
use crossterm::{
event::{DisableMouseCapture, PopKeyboardEnhancementFlags},
terminal::{disable_raw_mode, LeaveAlternateScreen},
ExecutableCommand,
};
pub use ratatui;
/// Functions and types related to capture and display of world to terminal
@ -54,7 +62,11 @@ impl Plugin for TerminalDisplayPlugin {
.unwrap();
let file_layer = tracing_subscriber::fmt::Layer::new()
.with_writer(log_file)
.with_filter(EnvFilter::builder().parse_lossy(format!("{},{}", Level::INFO, "wgpu=error,naga=warn")));
.with_filter(EnvFilter::builder().parse_lossy(format!(
"{},{}",
Level::INFO,
"wgpu=error,naga=warn"
)));
let subscriber = Registry::default().with(file_layer);
subscriber::set_global_default(subscriber).unwrap();
@ -63,43 +75,45 @@ impl Plugin for TerminalDisplayPlugin {
let error = error.into_eyre_hook();
color_eyre::eyre::set_hook(Box::new(move |e| {
let _ = restore_terminal();
restore_terminal();
error(e)
})).unwrap();
}))
.unwrap();
std::panic::set_hook(Box::new(move |info| {
let _ = restore_terminal();
restore_terminal();
error!("{info}");
panic(info);
}));
app.add_plugins((
DitherPostProcessPlugin,
HeadlessRenderPlugin,
))
.add_systems(Startup, input::systems::setup_input)
.add_systems(
Update,
(
input::systems::input_handling,
display::systems::resize_handling,
display::systems::print_to_terminal,
widgets::systems::widget_input_handling,
widgets::systems::update_widgets,
),
)
.insert_resource(display::resources::Terminal::default())
.insert_resource(input::resources::EventQueue::default())
.init_resource::<widgets::resources::FocusedWidget>()
.add_event::<input::events::TerminalInputEvent>();
app.add_plugins((DitherPostProcessPlugin, HeadlessRenderPlugin))
.add_systems(Startup, input::systems::setup_input)
.add_systems(
Update,
(
input::systems::input_handling,
display::systems::resize_handling,
display::systems::print_to_terminal,
widgets::systems::widget_input_handling,
widgets::systems::update_widgets,
),
)
.insert_resource(display::resources::Terminal::default())
.insert_resource(input::resources::EventQueue::default())
.init_resource::<widgets::resources::FocusedWidget>()
.add_event::<input::events::TerminalInputEvent>();
}
}
fn restore_terminal() {
let _ = disable_raw_mode();
let mut stdout = stdout();
let _ = stdout.execute(PopKeyboardEnhancementFlags).unwrap()
.execute(DisableMouseCapture).unwrap()
.execute(LeaveAlternateScreen).unwrap()
let _ = stdout
.execute(PopKeyboardEnhancementFlags)
.unwrap()
.execute(DisableMouseCapture)
.unwrap()
.execute(LeaveAlternateScreen)
.unwrap()
.flush();
}

View File

@ -16,7 +16,7 @@ pub trait TerminalWidgetCommands {
fn focus_widget(&mut self, widget: Entity);
}
impl<'w, 's> TerminalWidgetCommands for Commands<'w,'s> {
impl TerminalWidgetCommands for Commands<'_, '_> {
fn focus_widget(&mut self, widget: Entity) {
self.queue(FocusWidgetCommand(widget));
}

View File

@ -13,7 +13,7 @@ pub fn widget_input_handling(
) {
if let Some(entity) = **focused_widget {
if let Ok(mut widget) = widgets.get_mut(entity) {
if widget.enabled == true {
if widget.enabled {
for event in event_reader.read() {
widget.widget.handle_events(event, &mut commands);
}