Compare commits

..

No commits in common. "d43b5b64e17b076b40a25aa51e7e62a7c4075b48" and "cf05050c955e283c6e7435bec5921008b1e3e354" have entirely different histories.

14 changed files with 95 additions and 225 deletions

Binary file not shown.

View file

@ -1,118 +0,0 @@
//! Seperate out debugging uis/plugins in it's own module for cleanliness.
use std::{fs, path::PathBuf};
use bevy::prelude::*;
use bevy_inspector_egui::bevy_egui::EguiPlugin;
use clap::Subcommand;
use console::{ConsoleLog, exec_script};
use crate::AppState;
mod console;
/// Debug system set.
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct DebugSet;
pub fn plugin(app: &mut App) {
app.add_plugins(EguiPlugin {
enable_multipass_for_primary_context: true,
})
.add_event::<DebugEvent>()
.add_systems(
Update,
(handle_debug_logs, start_game, run_file.pipe(exec_script)).in_set(DebugSet),
)
.add_systems(Startup, startup_file.pipe(exec_script))
.add_plugins(console::plugin);
}
#[derive(Event, Debug, Subcommand, PartialEq, Eq)]
enum DebugEvent {
/// Close the debug console.
#[command(name = "close", aliases = ["close-console"])]
CloseDebugConsole,
/// Output a string to the console.
///
/// Needed for logging in startup scripts, since the console isn't initialized yet.
#[command(name = "echo", aliases = ["print", "print-to-console"])]
PrintToConsole {
/// Print as error.
#[arg(short, long)]
error: bool,
/// The text to be printed in the console.
text: String,
},
/// Log as INFO or ERROR to stdout.
Log {
/// Log as error.
#[arg(short, long)]
error: bool,
/// The text to be logged.
text: String,
},
/// Start the game
StartGame,
/// Run a tx file (the games debug scripting lang :3)
#[command(name = "run")]
RunFile { file: PathBuf },
}
fn start_game(
mut dbg_reader: EventReader<DebugEvent>,
mut log: ResMut<ConsoleLog>,
cur_state: Res<State<AppState>>,
mut next_state: ResMut<NextState<AppState>>,
) {
for ev in dbg_reader.read() {
if *ev == DebugEvent::StartGame {
if *cur_state == AppState::Ingame {
log.err("Can't start game since it's already started.");
} else {
log.write("Starting game...");
next_state.set(AppState::Ingame);
}
}
}
}
fn handle_debug_logs(mut dbg_reader: EventReader<DebugEvent>) {
for ev in dbg_reader.read() {
if let DebugEvent::Log { error, text } = ev {
if *error {
error!("{text}")
} else {
info!("{text}")
};
}
}
}
fn run_file(mut dbg_reader: EventReader<DebugEvent>) -> Option<(String, String)> {
for ev in dbg_reader.read() {
if let DebugEvent::RunFile { file } = ev {
let f = std::fs::read_to_string(file);
if let Ok(f) = f {
return Some((f, String::from(file.file_name().unwrap().to_string_lossy())));
}
}
}
None
}
fn startup_file() -> Option<(String, String)> {
let path: PathBuf = "./startup.tx".into();
fs::exists(&path).unwrap_or(false).then(|| {
Some((
fs::read_to_string(&path).unwrap(),
path.file_name().unwrap().to_string_lossy().to_string(),
))
})?
}

View file

@ -1,31 +0,0 @@
use bevy::prelude::*;
use clap::{Parser, Subcommand};
use crate::debug::DebugEvent;
use super::ConsoleLog;
pub(super) fn respond(line: &str) -> Result<DebugEvent, String> {
let args = shlex::split(line).ok_or("Invalid Quoting")?;
let cli = Cli::try_parse_from(args).map_err(|e| e.to_string());
// help detection
let command_contains_help = line.contains("help") || line.contains("-h");
let some_line_starts_with_usage = cli
.as_ref()
.is_err_and(|item| item.lines().any(|line| line.starts_with("Usage: ")));
if command_contains_help && some_line_starts_with_usage {
let Err(text) = cli else { unreachable!() };
return Ok(DebugEvent::PrintToConsole { text, error: false });
}
Ok(cli?.cmd)
}
#[derive(Debug, Parser)]
#[command(multicall = true)]
struct Cli {
#[command(subcommand)]
cmd: DebugEvent,
}

14
src/debugging.rs Normal file
View file

@ -0,0 +1,14 @@
//! Seperate out debugging uis/plugins in it's own module for cleanliness.
use bevy::prelude::*;
use bevy_inspector_egui::bevy_egui::EguiPlugin;
pub fn plugin(app: &mut App) {
app.add_plugins(EguiPlugin {
enable_multipass_for_primary_context: true,
})
.add_plugins((
// WorldInspectorPlugin::new(),
// StateInspectorPlugin::<AppState>::new(),
// StateInspectorPlugin::<menus::CurrentMenu>::new(),
));
}

View file

@ -6,7 +6,18 @@ use crate::{
};
mod camera;
mod debug;
mod scene;
mod tram {
use bevy::prelude::*;
fn spawn_tram(
mut c: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
}
}
/// Gameplay system set. All functions in this control the gameplay (duh).
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
@ -18,6 +29,6 @@ pub fn plugin(app: &mut App) {
OnExit(AppState::Ingame),
despawn::<cleanup::Scene>.in_set(GameplaySet),
)
.add_plugins(camera::plugin);
.add_plugins((debug::plugin, camera::plugin));
app.configure_sets(Update, GameplaySet.run_if(in_state(AppState::Ingame)));
}

13
src/game/debug.rs Normal file
View file

@ -0,0 +1,13 @@
use bevy::prelude::*;
mod console;
#[derive(Event)]
enum DebugEvent {
CloseDebugConsole,
PrintToConsole(String),
}
pub(super) fn plugin(app: &mut App) {
app.add_plugins(console::plugin).add_event::<DebugEvent>();
}

View file

@ -1,15 +1,12 @@
use std::panic::Location;
use bevy::prelude::*;
use cli::respond;
use ui::{
DebugConsole, autofocus, autoscroll, handle_open_console, process_prompt, update_content,
update_scroll_position,
};
use crate::{AppState, cleanup::despawn};
use crate::{AppState, cleanup::despawn, game::GameplaySet};
use super::{DebugEvent, DebugSet};
use super::DebugEvent;
mod cli;
mod ui;
@ -18,12 +15,14 @@ pub(super) fn plugin(app: &mut App) {
app.init_state::<ConsoleState>()
.add_systems(
OnEnter(ConsoleState::Open),
(open_console, (autofocus, autoscroll).after(open_console)).in_set(DebugSet),
(open_console, (autofocus, autoscroll).after(open_console)),
)
.add_systems(
Update,
(
handle_open_console.run_if(in_state(ConsoleState::Closed)),
handle_open_console
.in_set(GameplaySet)
.run_if(in_state(ConsoleState::Closed).and(in_state(AppState::Ingame))),
update_content.run_if(resource_changed::<ConsoleLog>),
(
update_scroll_position,
@ -31,27 +30,21 @@ pub(super) fn plugin(app: &mut App) {
execute_console_events,
)
.run_if(in_state(ConsoleState::Open)),
)
.in_set(DebugSet),
)
.add_systems(
OnExit(ConsoleState::Open),
despawn::<DebugConsole>.in_set(DebugSet),
),
)
.add_systems(OnExit(ConsoleState::Open), despawn::<DebugConsole>)
.insert_resource::<ConsoleLog>(ConsoleLog::new());
}
/// the usize is a read index
#[derive(Resource, Clone)]
pub struct ConsoleLog(Vec<ConsoleEvent>, usize);
struct ConsoleLog(Vec<ConsoleEvent>, usize);
impl ConsoleLog {
fn new() -> Self {
Self(
vec![ConsoleEvent::Output(format!(
"Running {} ({})\nMeow!! :3",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
vec![ConsoleEvent::Output(String::from(
"Welcome to the dev console :3\n (i should probably put some proper info into this some time)",
))],
1,
)
@ -63,15 +56,15 @@ impl ConsoleLog {
res
}
fn input(&mut self, content: &str) {
pub fn input(&mut self, content: &str) {
self.0.push(ConsoleEvent::Input(content.to_string()))
}
pub fn write(&mut self, content: &str) {
pub fn output(&mut self, content: &str) {
self.0.push(ConsoleEvent::Output(content.to_string()))
}
pub fn err(&mut self, content: &str) {
pub fn error(&mut self, content: &str) {
self.0.push(ConsoleEvent::Error(content.to_string()))
}
}
@ -105,30 +98,8 @@ fn execute_console_events(
for ev in ev_reader.read() {
match ev {
DebugEvent::CloseDebugConsole => next_state.set(ConsoleState::Closed),
DebugEvent::PrintToConsole { text, error: false } => log.write(text),
DebugEvent::PrintToConsole { text, error: true } => log.err(text),
_ => {}
DebugEvent::PrintToConsole(s) => log.output(s),
_ => todo!(),
};
}
}
pub fn exec_script(
file: In<Option<(String, String)>>,
mut dbg_writer: EventWriter<DebugEvent>,
mut logger: ResMut<ConsoleLog>,
) {
let Some((file, file_name)) = &*file else {
return;
};
for (line_nr, line) in file.lines().enumerate() {
if !line.trim().is_empty() && !line.trim().starts_with("//") {
match respond(line) {
Ok(ev) => {
dbg_writer.write(ev);
}
Err(err) => logger.err(&format!("{err}\n\n({file_name}:{line_nr})")),
}
}
}
}

View file

@ -0,0 +1,32 @@
use clap::{Parser, Subcommand};
use crate::game::debug::DebugEvent;
pub(super) fn respond(line: &str) -> Result<DebugEvent, String> {
let might_be_help_call = line.contains("help") || line.contains("-h");
let args = shlex::split(line).ok_or("Invalid Quoting")?;
let cli = Cli::try_parse_from(args).map_err(|e| e.to_string());
if might_be_help_call && cli.as_ref().is_err_and(|item| item.starts_with("Usage: ")) {
let Err(s) = cli else { unreachable!() };
return Ok(DebugEvent::PrintToConsole(s));
}
Ok(match cli?.cmd {
Commands::Close => DebugEvent::CloseDebugConsole,
Commands::Echo { text } => DebugEvent::PrintToConsole(text),
})
}
#[derive(Debug, Parser)]
#[command(multicall = true)]
struct Cli {
#[command(subcommand)]
cmd: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
Close,
Echo { text: String },
}

View file

@ -16,7 +16,7 @@ use bevy_ui_text_input::TextSubmitEvent;
pub(super) use components::console;
use components::{Content, Prompt};
use crate::debug::DebugEvent;
use crate::game::debug::DebugEvent;
use super::{ConsoleEvent, ConsoleLog, ConsoleState, OPEN_CONSOLE_DEFAULT, cli::respond};
@ -75,7 +75,7 @@ pub fn process_prompt(
Ok(debug_ev) => {
debug_event_writer.write(debug_ev);
}
Err(e) => log.err(&e),
Err(e) => log.error(&e),
}
}
}
@ -90,7 +90,7 @@ pub fn update_content(
) {
c.entity(*content).with_children(|parent| {
for item in log.unread() {
match item {
match dbg!(item) {
ConsoleEvent::Input(s) => {
parent.spawn(components::input(s.to_string(), &asset_server));
}

View file

@ -1,7 +1,7 @@
use bevy::{ecs::spawn::SpawnWith, prelude::*};
use bevy_ui_text_input::{TextInputMode, TextInputNode, TextInputPrompt};
use crate::debug::console::{ConsoleEvent, ConsoleLog};
use crate::game::debug::console::{ConsoleEvent, ConsoleLog};
use super::DebugConsole;
@ -26,7 +26,6 @@ pub fn console(data: ConsoleLog, asset_server: AssetServer) -> impl Bundle {
},
..default()
},
BorderRadius::bottom(Val::Px(10.)),
BorderColor(Color::BLACK),
ZIndex(i32::MAX),
BackgroundColor(Color::Srgba(Srgba::BLACK.with_alpha(0.2))),

View file

@ -2,15 +2,14 @@
use bevy::prelude::*;
use bevy_skein::SkeinPlugin;
use bevy_ui_text_input::TextInputPlugin;
use clap::ValueEnum;
mod camera;
mod cleanup;
mod debug;
mod debugging;
mod game;
mod menus;
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash, Reflect, ValueEnum)]
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash, Reflect)]
#[allow(unused)]
enum AppState {
#[default]
@ -24,7 +23,7 @@ fn main() {
.register_type::<TPCTarget>()
.add_systems(Startup, camera::setup)
.add_plugins((DefaultPlugins, TextInputPlugin))
.add_plugins((game::plugin, menus::plugin, debug::plugin))
.add_plugins((game::plugin, menus::plugin, debugging::plugin))
.add_plugins(SkeinPlugin::default())
.init_state::<AppState>()
.register_type::<AppState>()

View file

@ -5,8 +5,6 @@ use bevy::{
state::state::FreelyMutableState,
};
use crate::cleanup::despawn;
use super::{
ItemPosition, MenuItemInternal, MenuItemType, OnPressAction,
menus::{Menu, Menus},
@ -32,8 +30,7 @@ where
update_ui_trigger::<NavState>,
handle_press_actions::<NavState>.run_if(in_state(self.trigger.clone())),
),
)
.add_systems(OnExit(self.trigger.clone()), close_menu::<NavState>);
);
}
}
@ -56,15 +53,6 @@ impl<T: States, S: States> Menus<T, S> {
}
}
fn close_menu<S: States + FreelyMutableState>(
mut c: Commands,
mut nav_state: ResMut<NextState<S>>,
closed_when: Res<MenusClosedWhen<S>>,
) {
c.run_system_cached(despawn::<UiParent<S>>);
nav_state.set(closed_when.0.clone());
}
#[derive(Resource)]
struct MenusStore<S: States>(HashMap<S, Menu<S>>);
#[derive(Resource)]

View file

@ -1,2 +0,0 @@
log "hello from startup script!!"
start-game

View file

@ -1,6 +0,0 @@
// test comment
echo hii
echo "meow"
echo 42
start-game