mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-11-28 23:36:44 +00:00
add in-game debug command line
This commit is contained in:
parent
b1b3b131e2
commit
4ed7ba66b8
|
|
@ -8,6 +8,7 @@ use std::rc::Rc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use imgui::internal::RawWrapper;
|
use imgui::internal::RawWrapper;
|
||||||
|
use imgui::sys::{ImGuiKey_Backspace, ImGuiKey_Delete, ImGuiKey_Enter};
|
||||||
use imgui::{ConfigFlags, DrawCmd, DrawData, DrawIdx, DrawVert, Key, MouseCursor, TextureId, Ui};
|
use imgui::{ConfigFlags, DrawCmd, DrawData, DrawIdx, DrawVert, Key, MouseCursor, TextureId, Ui};
|
||||||
use sdl2::controller::GameController;
|
use sdl2::controller::GameController;
|
||||||
use sdl2::event::{Event, WindowEvent};
|
use sdl2::event::{Event, WindowEvent};
|
||||||
|
|
@ -424,7 +425,11 @@ impl BackendEventLoop for SDL2EventLoop {
|
||||||
|
|
||||||
#[cfg(feature = "render-opengl")]
|
#[cfg(feature = "render-opengl")]
|
||||||
if *self.opengl_available.borrow() {
|
if *self.opengl_available.borrow() {
|
||||||
let imgui = init_imgui()?;
|
let mut imgui = init_imgui()?;
|
||||||
|
let mut key_map = &mut imgui.io_mut().key_map;
|
||||||
|
key_map[ImGuiKey_Backspace as usize] = Scancode::Backspace as u32;
|
||||||
|
key_map[ImGuiKey_Delete as usize] = Scancode::Delete as u32;
|
||||||
|
key_map[ImGuiKey_Enter as usize] = Scancode::Return as u32;
|
||||||
|
|
||||||
let refs = self.refs.clone();
|
let refs = self.refs.clone();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
//! Error types and conversion functions.
|
//! Error types and conversion functions.
|
||||||
|
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use std::sync::{Arc, PoisonError};
|
|
||||||
use std::sync::mpsc::SendError;
|
use std::sync::mpsc::SendError;
|
||||||
|
use std::sync::{Arc, PoisonError};
|
||||||
|
|
||||||
/// An enum containing all kinds of game framework errors.
|
/// An enum containing all kinds of game framework errors.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -43,6 +42,8 @@ pub enum GameError {
|
||||||
ParseError(String),
|
ParseError(String),
|
||||||
/// Something went wrong while converting a value.
|
/// Something went wrong while converting a value.
|
||||||
InvalidValue(String),
|
InvalidValue(String),
|
||||||
|
/// Something went wrong while executing a debug command line command.
|
||||||
|
CommandLineError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for GameError {
|
impl fmt::Display for GameError {
|
||||||
|
|
@ -50,11 +51,9 @@ impl fmt::Display for GameError {
|
||||||
match *self {
|
match *self {
|
||||||
GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
|
GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
|
||||||
GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
|
GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
|
||||||
GameError::ResourceNotFound(ref s, ref paths) => write!(
|
GameError::ResourceNotFound(ref s, ref paths) => {
|
||||||
f,
|
write!(f, "Resource not found: {}, searched in paths {:?}", s, paths)
|
||||||
"Resource not found: {}, searched in paths {:?}",
|
}
|
||||||
s, paths
|
|
||||||
),
|
|
||||||
GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
|
GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
|
||||||
_ => write!(f, "GameError {:?}", self),
|
_ => write!(f, "GameError {:?}", self),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
293
src/live_debugger/command_line.rs
Normal file
293
src/live_debugger/command_line.rs
Normal file
|
|
@ -0,0 +1,293 @@
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
|
use crate::framework::error::{GameError::CommandLineError, GameResult};
|
||||||
|
use crate::scene::game_scene::GameScene;
|
||||||
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
use crate::weapon::WeaponType;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum CommandLineCommand {
|
||||||
|
AddItem(u16),
|
||||||
|
RemoveItem(u16),
|
||||||
|
AddWeapon(u16, u16),
|
||||||
|
RemoveWeapon(u16),
|
||||||
|
AddWeaponAmmo(u16),
|
||||||
|
SetWeaponMaxAmmo(u16),
|
||||||
|
RefillAmmo,
|
||||||
|
RefillHP,
|
||||||
|
AddXP(u16),
|
||||||
|
RemoveXP(u16),
|
||||||
|
SetMaxHP(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandLineCommand {
|
||||||
|
pub fn from_components(components: Vec<&str>) -> Option<CommandLineCommand> {
|
||||||
|
if components.len() == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let command = components[0];
|
||||||
|
|
||||||
|
match command.replacen("/", "", 1).as_str() {
|
||||||
|
"add_item" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item_id = components[1].parse::<u16>();
|
||||||
|
if item_id.is_ok() {
|
||||||
|
return Some(CommandLineCommand::AddItem(item_id.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"remove_item" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item_id = components[1].parse::<u16>();
|
||||||
|
if item_id.is_ok() {
|
||||||
|
return Some(CommandLineCommand::RemoveItem(item_id.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"add_weapon" => {
|
||||||
|
if components.len() < 3 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let weapon_id = components[1].parse::<u16>();
|
||||||
|
let ammo_count = components[2].parse::<u16>();
|
||||||
|
|
||||||
|
if weapon_id.is_ok() && ammo_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::AddWeapon(weapon_id.unwrap(), ammo_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"remove_weapon" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let weapon_id = components[1].parse::<u16>();
|
||||||
|
if weapon_id.is_ok() {
|
||||||
|
return Some(CommandLineCommand::RemoveWeapon(weapon_id.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"add_weapon_ammo" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ammo_count = components[1].parse::<u16>();
|
||||||
|
if ammo_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::AddWeaponAmmo(ammo_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"set_weapon_max_ammo" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_ammo_count = components[1].parse::<u16>();
|
||||||
|
if max_ammo_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::SetWeaponMaxAmmo(max_ammo_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"refill_ammo" => {
|
||||||
|
return Some(CommandLineCommand::RefillAmmo);
|
||||||
|
}
|
||||||
|
"refill_hp" => {
|
||||||
|
return Some(CommandLineCommand::RefillHP);
|
||||||
|
}
|
||||||
|
"add_xp" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xp_count = components[1].parse::<u16>();
|
||||||
|
if xp_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::AddXP(xp_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"remove_xp" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xp_count = components[1].parse::<u16>();
|
||||||
|
if xp_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::RemoveXP(xp_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"set_max_hp" => {
|
||||||
|
if components.len() < 2 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hp_count = components[1].parse::<u16>();
|
||||||
|
if hp_count.is_ok() {
|
||||||
|
return Some(CommandLineCommand::SetMaxHP(hp_count.unwrap()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(&mut self, game_scene: &mut GameScene, state: &mut SharedGameState) -> GameResult {
|
||||||
|
match *self {
|
||||||
|
CommandLineCommand::AddItem(item_id) => {
|
||||||
|
game_scene.inventory_player1.add_item(item_id);
|
||||||
|
}
|
||||||
|
CommandLineCommand::RemoveItem(item_id) => {
|
||||||
|
if !game_scene.inventory_player1.has_item(item_id) {
|
||||||
|
return Err(CommandLineError(format!("Player does not have item {}", item_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
game_scene.inventory_player1.remove_item(item_id);
|
||||||
|
}
|
||||||
|
CommandLineCommand::AddWeapon(weapon_id, ammo_count) => {
|
||||||
|
let weapon_type: Option<WeaponType> = FromPrimitive::from_u16(weapon_id);
|
||||||
|
match weapon_type {
|
||||||
|
Some(weapon_type) => game_scene.inventory_player1.add_weapon(weapon_type, ammo_count),
|
||||||
|
None => return Err(CommandLineError(format!("Invalid weapon id {}", weapon_id))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommandLineCommand::RemoveWeapon(weapon_id) => {
|
||||||
|
let weapon_type: Option<WeaponType> = FromPrimitive::from_u16(weapon_id);
|
||||||
|
match weapon_type {
|
||||||
|
Some(weapon_type) => {
|
||||||
|
if !game_scene.inventory_player1.has_weapon(weapon_type) {
|
||||||
|
return Err(CommandLineError(format!("Player does not have weapon {:?}", weapon_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
game_scene.inventory_player1.remove_weapon(weapon_type);
|
||||||
|
}
|
||||||
|
None => return Err(CommandLineError(format!("Invalid weapon id {}", weapon_id))),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
CommandLineCommand::AddWeaponAmmo(ammo_count) => {
|
||||||
|
let weapon = game_scene.inventory_player1.get_current_weapon_mut();
|
||||||
|
match weapon {
|
||||||
|
Some(weapon) => weapon.ammo += ammo_count,
|
||||||
|
None => return Err(CommandLineError(format!("Player does not have an active weapon"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommandLineCommand::SetWeaponMaxAmmo(max_ammo) => {
|
||||||
|
let weapon = game_scene.inventory_player1.get_current_weapon_mut();
|
||||||
|
match weapon {
|
||||||
|
Some(weapon) => weapon.max_ammo = max_ammo,
|
||||||
|
None => return Err(CommandLineError(format!("Player does not have an active weapon"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommandLineCommand::RefillAmmo => {
|
||||||
|
game_scene.inventory_player1.refill_all_ammo();
|
||||||
|
}
|
||||||
|
CommandLineCommand::RefillHP => {
|
||||||
|
game_scene.player1.life = game_scene.player1.max_life;
|
||||||
|
}
|
||||||
|
CommandLineCommand::AddXP(xp_count) => {
|
||||||
|
game_scene.inventory_player1.add_xp(xp_count, &mut game_scene.player1, state);
|
||||||
|
}
|
||||||
|
CommandLineCommand::RemoveXP(xp_count) => {
|
||||||
|
game_scene.inventory_player1.take_xp(xp_count, state);
|
||||||
|
}
|
||||||
|
CommandLineCommand::SetMaxHP(hp_count) => {
|
||||||
|
game_scene.player1.max_life = hp_count;
|
||||||
|
game_scene.player1.life = hp_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn to_command(&self) -> String {
|
||||||
|
match self {
|
||||||
|
CommandLineCommand::AddItem(item_id) => format!("/add_item {}", item_id),
|
||||||
|
CommandLineCommand::RemoveItem(item_id) => format!("/remove_item {}", item_id),
|
||||||
|
CommandLineCommand::AddWeapon(weapon_id, ammo_count) => format!("/add_weapon {} {}", weapon_id, ammo_count),
|
||||||
|
CommandLineCommand::RemoveWeapon(weapon_id) => format!("/remove_weapon {}", weapon_id),
|
||||||
|
CommandLineCommand::AddWeaponAmmo(ammo_count) => format!("/add_weapon_ammo {}", ammo_count),
|
||||||
|
CommandLineCommand::SetWeaponMaxAmmo(max_ammo_count) => format!("/set_weapon_max_ammo {}", max_ammo_count),
|
||||||
|
CommandLineCommand::RefillAmmo => "/refill_ammo".to_string(),
|
||||||
|
CommandLineCommand::RefillHP => "/refill_hp".to_string(),
|
||||||
|
CommandLineCommand::AddXP(xp_count) => format!("/add_xp {}", xp_count),
|
||||||
|
CommandLineCommand::RemoveXP(xp_count) => format!("/remove_xp {}", xp_count),
|
||||||
|
CommandLineCommand::SetMaxHP(hp_count) => format!("/set_max_hp {}", hp_count),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn feedback_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
CommandLineCommand::AddItem(item_id) => format!("Added item with ID {}.", item_id),
|
||||||
|
CommandLineCommand::RemoveItem(item_id) => format!("Removed item with ID {}.", item_id),
|
||||||
|
CommandLineCommand::AddWeapon(weapon_id, ammo_count) => {
|
||||||
|
format!("Added weapon with ID {} and {} ammo.", weapon_id, ammo_count)
|
||||||
|
}
|
||||||
|
CommandLineCommand::RemoveWeapon(weapon_id) => format!("Removed weapon with ID {}.", weapon_id),
|
||||||
|
CommandLineCommand::AddWeaponAmmo(ammo_count) => format!("Added {} ammo to current weapon.", ammo_count),
|
||||||
|
CommandLineCommand::SetWeaponMaxAmmo(max_ammo_count) => {
|
||||||
|
format!("Set max ammo of current weapon to {}.", max_ammo_count)
|
||||||
|
}
|
||||||
|
CommandLineCommand::RefillAmmo => "Refilled ammo of all weapons.".to_string(),
|
||||||
|
CommandLineCommand::RefillHP => "Refilled HP of player.".to_string(),
|
||||||
|
CommandLineCommand::AddXP(xp_count) => format!("Added {} XP to current weapon.", xp_count),
|
||||||
|
CommandLineCommand::RemoveXP(xp_count) => format!("Removed {} XP from current weapon.", xp_count),
|
||||||
|
CommandLineCommand::SetMaxHP(hp_count) => format!("Set max HP of player to {}.", hp_count),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CommandLineParser {
|
||||||
|
command_history: Vec<CommandLineCommand>,
|
||||||
|
cursor: usize,
|
||||||
|
pub last_feedback: String,
|
||||||
|
pub last_feedback_color: [f32; 4],
|
||||||
|
pub buffer: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandLineParser {
|
||||||
|
pub fn new() -> CommandLineParser {
|
||||||
|
CommandLineParser {
|
||||||
|
command_history: Vec::new(),
|
||||||
|
last_feedback: "Awaiting command.".to_string(),
|
||||||
|
last_feedback_color: [1.0, 1.0, 1.0, 1.0],
|
||||||
|
cursor: 0,
|
||||||
|
buffer: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, command: String) -> Option<CommandLineCommand> {
|
||||||
|
let components = command.split_whitespace().collect::<Vec<&str>>();
|
||||||
|
let command = CommandLineCommand::from_components(components);
|
||||||
|
|
||||||
|
match command {
|
||||||
|
Some(command) => {
|
||||||
|
self.command_history.push(command);
|
||||||
|
self.cursor = self.command_history.len() - 1;
|
||||||
|
|
||||||
|
Some(command)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn traverse(&mut self, delta: i16) -> Option<&CommandLineCommand> {
|
||||||
|
if self.command_history.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let command = self.command_history.get(self.cursor);
|
||||||
|
|
||||||
|
if delta == -1 && self.cursor == 0 {
|
||||||
|
self.cursor = self.command_history.len() - 1;
|
||||||
|
} else if delta == 1 && self.cursor == self.command_history.len() - 1 {
|
||||||
|
self.cursor = 0;
|
||||||
|
} else {
|
||||||
|
self.cursor = (self.cursor as i16 + delta) as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,10 @@ use crate::scene::game_scene::GameScene;
|
||||||
use crate::scripting::tsc::text_script::TextScriptExecutionState;
|
use crate::scripting::tsc::text_script::TextScriptExecutionState;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
|
||||||
|
use self::command_line::CommandLineParser;
|
||||||
|
|
||||||
|
pub mod command_line;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ScriptType {
|
pub enum ScriptType {
|
||||||
|
|
@ -22,6 +26,7 @@ pub struct LiveDebugger {
|
||||||
flags_visible: bool,
|
flags_visible: bool,
|
||||||
npc_inspector_visible: bool,
|
npc_inspector_visible: bool,
|
||||||
hotkey_list_visible: bool,
|
hotkey_list_visible: bool,
|
||||||
|
command_line_parser: CommandLineParser,
|
||||||
last_stage_id: usize,
|
last_stage_id: usize,
|
||||||
stages: Vec<ImString>,
|
stages: Vec<ImString>,
|
||||||
selected_stage: i32,
|
selected_stage: i32,
|
||||||
|
|
@ -40,6 +45,7 @@ impl LiveDebugger {
|
||||||
flags_visible: false,
|
flags_visible: false,
|
||||||
npc_inspector_visible: false,
|
npc_inspector_visible: false,
|
||||||
hotkey_list_visible: false,
|
hotkey_list_visible: false,
|
||||||
|
command_line_parser: CommandLineParser::new(),
|
||||||
last_stage_id: usize::MAX,
|
last_stage_id: usize::MAX,
|
||||||
stages: Vec::new(),
|
stages: Vec::new(),
|
||||||
selected_stage: -1,
|
selected_stage: -1,
|
||||||
|
|
@ -64,6 +70,60 @@ impl LiveDebugger {
|
||||||
self.selected_event = -1;
|
self.selected_event = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.command_line {
|
||||||
|
let width = state.screen_size.0;
|
||||||
|
let height = 85.0;
|
||||||
|
let x = 0.0 as f32;
|
||||||
|
let y = state.screen_size.1 - height;
|
||||||
|
|
||||||
|
Window::new("Command Line")
|
||||||
|
.position([x, y], Condition::FirstUseEver)
|
||||||
|
.size([width, height], Condition::FirstUseEver)
|
||||||
|
.resizable(false)
|
||||||
|
.collapsible(false)
|
||||||
|
.movable(false)
|
||||||
|
.build(ui, || {
|
||||||
|
ui.text("Command:");
|
||||||
|
ui.same_line();
|
||||||
|
|
||||||
|
ui.input_text("", &mut self.command_line_parser.buffer).build();
|
||||||
|
|
||||||
|
if ui.is_item_active() {
|
||||||
|
state.control_flags.set_tick_world(false);
|
||||||
|
} else {
|
||||||
|
state.control_flags.set_tick_world(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.same_line();
|
||||||
|
if ui.is_key_released(imgui::Key::Enter) || ui.button("Execute") {
|
||||||
|
log::info!("Executing command: {}", self.command_line_parser.buffer);
|
||||||
|
match self.command_line_parser.push(self.command_line_parser.buffer.clone()) {
|
||||||
|
Some(mut command) => match command.execute(game_scene, state) {
|
||||||
|
Ok(()) => {
|
||||||
|
self.command_line_parser.last_feedback = command.feedback_string();
|
||||||
|
self.command_line_parser.last_feedback_color = [0.0, 1.0, 0.0, 1.0];
|
||||||
|
state.sound_manager.play_sfx(5);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.command_line_parser.last_feedback = e.to_string();
|
||||||
|
self.command_line_parser.last_feedback_color = [1.0, 0.0, 0.0, 1.0];
|
||||||
|
state.sound_manager.play_sfx(12);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.command_line_parser.last_feedback = "Invalid command".to_string();
|
||||||
|
self.command_line_parser.last_feedback_color = [1.0, 0.0, 0.0, 1.0];
|
||||||
|
state.sound_manager.play_sfx(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.text_colored(
|
||||||
|
self.command_line_parser.last_feedback_color,
|
||||||
|
self.command_line_parser.last_feedback.clone(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if !state.debugger {
|
if !state.debugger {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +132,7 @@ impl LiveDebugger {
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.collapsed(true, Condition::FirstUseEver)
|
.collapsed(true, Condition::FirstUseEver)
|
||||||
.position([5.0, 5.0], Condition::FirstUseEver)
|
.position([5.0, 5.0], Condition::FirstUseEver)
|
||||||
.size([400.0, 235.0], Condition::FirstUseEver)
|
.size([400.0, 265.0], Condition::FirstUseEver)
|
||||||
.build(ui, || {
|
.build(ui, || {
|
||||||
ui.text(format!(
|
ui.text(format!(
|
||||||
"Player position: ({:.1},{:.1}), velocity: ({:.1},{:.1})",
|
"Player position: ({:.1},{:.1}), velocity: ({:.1},{:.1})",
|
||||||
|
|
@ -164,6 +224,10 @@ impl LiveDebugger {
|
||||||
self.hotkey_list_visible = !self.hotkey_list_visible;
|
self.hotkey_list_visible = !self.hotkey_list_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui.button("Command Line") {
|
||||||
|
state.command_line = !state.command_line;
|
||||||
|
}
|
||||||
|
|
||||||
ui.checkbox("noclip", &mut state.settings.noclip);
|
ui.checkbox("noclip", &mut state.settings.noclip);
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
ui.checkbox("more rust", &mut state.more_rust);
|
ui.checkbox("more rust", &mut state.more_rust);
|
||||||
|
|
@ -405,7 +469,7 @@ impl LiveDebugger {
|
||||||
if self.hotkey_list_visible {
|
if self.hotkey_list_visible {
|
||||||
Window::new("Hotkeys")
|
Window::new("Hotkeys")
|
||||||
.position([400.0, 5.0], Condition::FirstUseEver)
|
.position([400.0, 5.0], Condition::FirstUseEver)
|
||||||
.size([300.0, 280.0], Condition::FirstUseEver)
|
.size([300.0, 300.0], Condition::FirstUseEver)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.build(ui, || {
|
.build(ui, || {
|
||||||
let key = vec![
|
let key = vec![
|
||||||
|
|
@ -420,6 +484,7 @@ impl LiveDebugger {
|
||||||
"F10 > Debug Overlay",
|
"F10 > Debug Overlay",
|
||||||
"F11 > Toggle FPS Counter",
|
"F11 > Toggle FPS Counter",
|
||||||
"F12 > Toggle Debugger",
|
"F12 > Toggle Debugger",
|
||||||
|
"` > Toggle Command Line",
|
||||||
"Ctrl + F3 > Reload Sound Manager",
|
"Ctrl + F3 > Reload Sound Manager",
|
||||||
"Ctrl + S > Quick Save",
|
"Ctrl + S > Quick Save",
|
||||||
];
|
];
|
||||||
|
|
@ -433,6 +498,7 @@ impl LiveDebugger {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut remove = -1;
|
let mut remove = -1;
|
||||||
for (idx, (_, title, contents)) in self.text_windows.iter().enumerate() {
|
for (idx, (_, title, contents)) in self.text_windows.iter().enumerate() {
|
||||||
let mut opened = true;
|
let mut opened = true;
|
||||||
|
|
@ -2358,6 +2358,7 @@ impl Scene for GameScene {
|
||||||
ScanCode::F10 => state.settings.debug_outlines = !state.settings.debug_outlines,
|
ScanCode::F10 => state.settings.debug_outlines = !state.settings.debug_outlines,
|
||||||
ScanCode::F11 => state.settings.fps_counter = !state.settings.fps_counter,
|
ScanCode::F11 => state.settings.fps_counter = !state.settings.fps_counter,
|
||||||
ScanCode::F12 => state.debugger = !state.debugger,
|
ScanCode::F12 => state.debugger = !state.debugger,
|
||||||
|
ScanCode::Grave => state.command_line = !state.command_line,
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,7 @@ pub struct SharedGameState {
|
||||||
pub stages: Vec<StageData>,
|
pub stages: Vec<StageData>,
|
||||||
pub frame_time: f64,
|
pub frame_time: f64,
|
||||||
pub debugger: bool,
|
pub debugger: bool,
|
||||||
|
pub command_line: bool,
|
||||||
pub scale: f32,
|
pub scale: f32,
|
||||||
pub canvas_size: (f32, f32),
|
pub canvas_size: (f32, f32),
|
||||||
pub screen_size: (f32, f32),
|
pub screen_size: (f32, f32),
|
||||||
|
|
@ -459,6 +460,7 @@ impl SharedGameState {
|
||||||
stages: Vec::with_capacity(96),
|
stages: Vec::with_capacity(96),
|
||||||
frame_time: 0.0,
|
frame_time: 0.0,
|
||||||
debugger: false,
|
debugger: false,
|
||||||
|
command_line: false,
|
||||||
scale: 2.0,
|
scale: 2.0,
|
||||||
screen_size: (640.0, 480.0),
|
screen_size: (640.0, 480.0),
|
||||||
canvas_size: (320.0, 240.0),
|
canvas_size: (320.0, 240.0),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue