doukutsu-rs/src/live_debugger.rs

203 lines
8.0 KiB
Rust
Raw Normal View History

2020-09-10 23:40:45 +00:00
use imgui::{CollapsingHeader, Condition, im_str, ImStr, ImString, Window};
2020-08-19 13:11:34 +00:00
use itertools::Itertools;
2020-08-19 11:21:40 +00:00
2020-08-20 18:31:47 +00:00
use crate::ggez::{Context, GameResult};
2020-08-19 13:11:34 +00:00
use crate::scene::game_scene::GameScene;
use crate::shared_game_state::SharedGameState;
2020-08-19 11:21:40 +00:00
pub struct LiveDebugger {
2020-08-20 18:31:47 +00:00
map_selector_visible: bool,
2020-08-27 02:43:21 +00:00
events_visible: bool,
2020-08-23 02:16:31 +00:00
hacks_visible: bool,
2020-09-10 23:40:45 +00:00
flags_visible: bool,
2020-08-27 02:43:21 +00:00
last_stage_id: usize,
2020-08-19 13:11:34 +00:00
stages: Vec<ImString>,
2020-08-27 02:43:21 +00:00
selected_stage: i32,
events: Vec<ImString>,
event_ids: Vec<u16>,
selected_event: i32,
2020-08-19 13:11:34 +00:00
error: Option<ImString>,
2020-08-19 11:21:40 +00:00
}
impl LiveDebugger {
pub fn new() -> Self {
Self {
2020-08-20 18:31:47 +00:00
map_selector_visible: false,
2020-08-27 02:43:21 +00:00
events_visible: false,
2020-08-23 02:16:31 +00:00
hacks_visible: false,
2020-09-10 23:40:45 +00:00
flags_visible: false,
2020-08-27 02:43:21 +00:00
last_stage_id: usize::MAX,
stages: Vec::new(),
selected_stage: -1,
events: Vec::new(),
event_ids: Vec::new(),
selected_event: -1,
2020-08-19 13:11:34 +00:00
error: None,
2020-08-19 11:21:40 +00:00
}
}
2020-08-19 13:11:34 +00:00
pub fn run_ingame(&mut self, game_scene: &mut GameScene, state: &mut SharedGameState, ctx: &mut Context, ui: &mut imgui::Ui) -> GameResult {
2020-08-27 02:43:21 +00:00
if self.last_stage_id != game_scene.stage_id {
self.last_stage_id = game_scene.stage_id;
self.events.clear();
self.selected_event = -1;
}
2020-08-23 02:16:31 +00:00
Window::new(im_str!("Debugger"))
2020-08-20 18:31:47 +00:00
.position([5.0, 5.0], Condition::FirstUseEver)
2020-08-23 02:16:31 +00:00
.size([300.0, 120.0], Condition::FirstUseEver)
2020-08-19 11:21:40 +00:00
.build(ui, || {
ui.text(format!(
"Player position: ({:.1},{:.1})",
2020-08-20 18:31:47 +00:00
game_scene.player.x as f32 / 512.0,
game_scene.player.y as f32 / 512.0,
));
ui.text(format!(
"Player velocity: ({:.1},{:.1})",
game_scene.player.vel_x as f32 / 512.0,
game_scene.player.vel_y as f32 / 512.0,
));
ui.text(format!(
"Booster fuel: ({})", game_scene.player.booster_fuel
2020-08-19 11:21:40 +00:00
));
2020-08-20 18:31:47 +00:00
if ui.button(im_str!("Map Selector"), [0.0, 0.0]) {
self.map_selector_visible = !self.map_selector_visible;
2020-08-20 18:31:47 +00:00
}
2020-08-23 02:16:31 +00:00
2020-08-27 02:43:21 +00:00
ui.same_line(0.0);
if ui.button(im_str!("Events"), [0.0, 0.0]) {
self.events_visible = !self.events_visible;
2020-08-27 02:43:21 +00:00
}
ui.same_line(0.0);
2020-08-23 02:16:31 +00:00
if ui.button(im_str!("Hacks"), [0.0, 0.0]) {
self.hacks_visible = !self.hacks_visible;
2020-08-23 02:16:31 +00:00
}
2020-09-10 23:40:45 +00:00
ui.same_line(0.0);
if ui.button(im_str!("Flags"), [0.0, 0.0]) {
self.flags_visible = !self.flags_visible;
}
2020-08-20 18:31:47 +00:00
});
2020-08-19 13:11:34 +00:00
if self.error.is_some() {
Window::new(im_str!("Error!"))
.resizable(false)
.collapsible(false)
2020-08-19 19:11:32 +00:00
.position([((state.screen_size.0 - 300.0) / 2.0).floor(), ((state.screen_size.1 - 100.0) / 2.0).floor()], Condition::Appearing)
.size([300.0, 100.0], Condition::Appearing)
2020-08-19 13:11:34 +00:00
.build(ui, || {
ui.push_item_width(-1.0);
ui.text_wrapped(self.error.as_ref().unwrap());
2020-08-19 13:11:34 +00:00
if ui.button(im_str!("OK"), [0.0, 0.0]) {
self.error = None;
}
});
}
2020-08-19 11:21:40 +00:00
2020-08-20 18:31:47 +00:00
if self.map_selector_visible {
Window::new(im_str!("Map selector"))
.resizable(false)
2020-08-27 02:43:21 +00:00
.position([80.0, 80.0], Condition::FirstUseEver)
2020-08-20 18:31:47 +00:00
.size([240.0, 280.0], Condition::FirstUseEver)
.build(ui, || {
if self.stages.is_empty() {
for s in state.stages.iter() {
self.stages.push(ImString::new(s.name.to_owned()));
}
2020-08-19 13:11:34 +00:00
2020-08-27 02:43:21 +00:00
self.selected_stage = match state.stages.iter().find_position(|s| s.name == game_scene.stage.data.name) {
2020-08-20 18:31:47 +00:00
Some((pos, _)) => { pos as i32 }
_ => { -1 }
};
}
let stages: Vec<&ImStr> = self.stages.iter().map(|e| e.as_ref()).collect();
2020-08-19 13:11:34 +00:00
2020-08-20 18:31:47 +00:00
ui.push_item_width(-1.0);
2020-08-27 02:43:21 +00:00
ui.list_box(im_str!(""), &mut self.selected_stage, &stages, 10);
2020-08-19 13:11:34 +00:00
2020-08-20 18:31:47 +00:00
if ui.button(im_str!("Load"), [0.0, 0.0]) {
2020-08-27 02:43:21 +00:00
match GameScene::new(state, ctx, self.selected_stage as usize) {
2020-08-20 18:31:47 +00:00
Ok(mut scene) => {
2020-09-19 13:19:00 +00:00
scene.inventory = game_scene.inventory.clone();
2020-09-10 23:40:45 +00:00
scene.player = game_scene.player.clone();
2020-08-20 18:31:47 +00:00
scene.player.x = (scene.stage.map.width / 2 * 16 * 0x200) as isize;
scene.player.y = (scene.stage.map.height / 2 * 16 * 0x200) as isize;
2020-09-10 23:40:45 +00:00
if scene.player.life == 0 {
scene.player.life = scene.player.max_life;
}
2020-08-20 18:31:47 +00:00
state.next_scene = Some(Box::new(scene));
}
Err(e) => {
log::error!("Error loading map: {:?}", e);
2020-08-20 18:31:47 +00:00
self.error = Some(ImString::new(e.to_string()));
}
2020-08-19 13:11:34 +00:00
}
}
2020-08-20 18:31:47 +00:00
});
}
2020-08-19 11:21:40 +00:00
2020-08-27 02:43:21 +00:00
if self.events_visible {
Window::new(im_str!("Events"))
.resizable(false)
.position([80.0, 80.0], Condition::FirstUseEver)
.size([280.0, 300.0], Condition::FirstUseEver)
2020-08-27 02:43:21 +00:00
.build(ui, || {
if self.events.is_empty() {
self.event_ids.clear();
let vm = &state.textscript_vm;
for event in vm.scripts.global_script.get_event_ids() {
2020-08-27 02:43:21 +00:00
self.events.push(ImString::new(format!("Global: #{:04}", event)));
self.event_ids.push(event);
}
for event in vm.scripts.scene_script.get_event_ids() {
2020-08-27 02:43:21 +00:00
self.events.push(ImString::new(format!("Scene: #{:04}", event)));
self.event_ids.push(event);
}
}
let events: Vec<&ImStr> = self.events.iter().map(|e| e.as_ref()).collect();
ui.text_wrapped(&ImString::new(format!("Execution state: {:?}", state.textscript_vm.state)));
2020-08-27 02:43:21 +00:00
ui.push_item_width(-1.0);
ui.list_box(im_str!(""), &mut self.selected_event, &events, 10);
if ui.button(im_str!("Execute"), [0.0, 0.0]) {
assert_eq!(self.event_ids.len(), self.events.len());
if let Some(&event_num) = self.event_ids.get(self.selected_event as usize) {
2020-09-21 23:53:46 +00:00
state.control_flags.set_flag_x01(true);
state.control_flags.set_interactions_disabled(true);
2020-08-27 02:43:21 +00:00
state.textscript_vm.start_script(event_num);
}
}
});
}
2020-09-10 23:40:45 +00:00
if self.flags_visible {
Window::new(im_str!("Flags"))
.position([80.0, 80.0], Condition::FirstUseEver)
.size([280.0, 300.0], Condition::FirstUseEver)
.build(ui, || {
if CollapsingHeader::new(im_str!("Control flags")).default_open(true).build(&ui)
{
ui.checkbox_flags(im_str!("Flag 0x01"), &mut state.control_flags.0, 1);
ui.checkbox_flags(im_str!("Control enabled"), &mut state.control_flags.0, 2);
ui.checkbox_flags(im_str!("Interactions disabled"), &mut state.control_flags.0, 4);
}
});
}
2020-08-19 11:21:40 +00:00
Ok(())
}
}