add config options to show/hide timing debug info and power directions

This commit is contained in:
Crispy 2025-04-21 00:23:19 +02:00
parent 440cd7a759
commit c8fc484e9c
7 changed files with 115 additions and 64 deletions

View file

@ -2,7 +2,11 @@
Game store page: https://crispypin.itch.io/marble-machinations
## [unreleased]
### added
- option to display power direction while overlay is enabled
### changed
- hide tick timing numbers by default
- when multiple I/O silos (or multiple directions of one) are activated in the same tick, they will all output the same value instead of pulling input in an arbitrary order
### fixed

View file

@ -16,7 +16,6 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble
- packet routing?
- game of life sim (width;height;steps;grid -> grid)
- show level name in end popup
- hide timing debug info by default
- shrink button
#### 0.4.0
- UI layout engine

View file

@ -1,11 +1,21 @@
use raylib::prelude::*;
use serde::{Deserialize, Serialize};
use crate::{input::Input, theme::FG_CHAPTER_TITLE, ui::text_button, util::Scroll, Globals};
use crate::{
input::Input,
theme::FG_CHAPTER_TITLE,
ui::{text_button, toggle_button},
util::Scroll,
Globals,
};
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub input: Input,
#[serde(default)]
pub show_debug_timing: bool,
#[serde(default)]
pub show_power_direction: bool,
#[serde(skip)]
scroll_offset: u32,
}
@ -25,19 +35,29 @@ impl Config {
Some(Scroll::Up) => self.scroll_offset = self.scroll_offset.saturating_sub(64),
None => (),
}
let y = -(self.scroll_offset as i32);
let mut y = -(self.scroll_offset as i32) + 15;
d.draw_text("Settings", 16, y, 30, FG_CHAPTER_TITLE);
y += 40;
d.draw_text("Settings", 16, y + 16, 30, FG_CHAPTER_TITLE);
if text_button(d, &globals.mouse, 10, y + 60, 80, "apply") {
if text_button(d, &globals.mouse, 10, y, 80, "apply") {
return MenuReturn::StaySave;
}
if text_button(d, &globals.mouse, 100, y + 60, 80, "done") {
if text_button(d, &globals.mouse, 100, y, 80, "done") {
return MenuReturn::ReturnSave;
}
if text_button(d, &globals.mouse, 190, y + 60, 80, "cancel") {
if text_button(d, &globals.mouse, 190, y, 80, "cancel") {
return MenuReturn::ReturnCancel;
}
y += 40;
let mut toggle = |value, text| {
toggle_button((d, &globals.mouse), 10, y, 30, 30, value);
d.draw_text(text, 50, y + 5, 20, Color::WHITE);
y += 40;
};
toggle(&mut self.show_power_direction, "show power directions");
toggle(&mut self.show_debug_timing, "show debug timing");
// self.input.update(d);
self.input.draw_edit(d, globals, y);

View file

@ -74,8 +74,8 @@ pub struct Editor {
undo_history: Vec<Action>,
undo_index: usize,
// debug/profiling
step_time: u128,
max_step_time: u128,
step_time: usize,
max_step_time: usize,
start_time: Instant,
}
@ -472,8 +472,8 @@ impl Editor {
.as_micros()
.checked_div(steps_taken)
.unwrap_or_default();
self.step_time = avg_step_time;
self.max_step_time = avg_step_time.max(self.max_step_time);
self.step_time = avg_step_time as usize;
self.max_step_time = self.step_time.max(self.max_step_time);
}
if globals.is_pressed(ActionId::StepSim) {
self.step_pressed()
@ -575,20 +575,33 @@ impl Editor {
}
fn draw_board(&self, d: &mut RaylibDrawHandle, globals: &Globals) {
let draw_power = globals.config.show_power_direction && self.draw_overlay;
if self.sim_state == SimState::Editing {
self.source_board
.grid
.draw(d, &globals.textures, self.view_offset, self.zoom);
self.source_board.grid.draw(
d,
&globals.textures,
self.view_offset,
self.zoom,
draw_power,
);
} else {
if self.machine.debug_subticks.is_empty() {
self.machine
.grid()
.draw(d, &globals.textures, self.view_offset, self.zoom);
self.machine.grid().draw(
d,
&globals.textures,
self.view_offset,
self.zoom,
draw_power,
);
} else {
let subframe = &self.machine.debug_subticks[self.machine.subtick_index];
subframe
.grid
.draw(d, &globals.textures, self.view_offset, self.zoom);
subframe.grid.draw(
d,
&globals.textures,
self.view_offset,
self.zoom,
draw_power,
);
if let Some(pos) = subframe.pos {
let p = self.pos_to_screen(pos.to_vec());
d.draw_texture_ex(
@ -961,34 +974,22 @@ impl Editor {
draw_usize(d, &globals.textures, total_steps, (420, 44), 9, 2);
}
draw_usize(
d,
&globals.textures,
self.step_time as usize,
(260, 42),
9,
1,
);
draw_usize(
d,
&globals.textures,
self.max_step_time as usize,
(260, 60),
9,
1,
);
#[cfg(debug_assertions)]
{
draw_usize(
d,
&globals.textures,
self.machine.subtick_index,
(260, 80),
9,
1,
);
let subtick_count = self.machine.debug_subticks.len();
draw_usize(d, &globals.textures, subtick_count, (260, 100), 9, 1);
if globals.config.show_debug_timing {
draw_usize(d, &globals.textures, self.step_time, (260, 42), 9, 1);
draw_usize(d, &globals.textures, self.max_step_time, (260, 60), 9, 1);
#[cfg(debug_assertions)]
{
draw_usize(
d,
&globals.textures,
self.machine.subtick_index,
(260, 80),
9,
1,
);
let subtick_count = self.machine.debug_subticks.len();
draw_usize(d, &globals.textures, subtick_count, (260, 100), 9, 1);
}
}
d.draw_text("input:", 603, 8, 10, Color::WHITE);
@ -1380,7 +1381,9 @@ impl Editor {
offset.x -= offset.x.rem(tile_size);
offset.y -= offset.y.rem(tile_size);
offset += view_offset;
board.grid.draw(d, &globals.textures, offset, self.zoom);
board
.grid
.draw(d, &globals.textures, offset, self.zoom, false);
board.draw_comments(d, offset, self.zoom);
if self.mouse.left_click() {
let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size;
@ -1517,7 +1520,9 @@ impl Editor {
offset.x -= offset.x.rem(tile_size);
offset.y -= offset.y.rem(tile_size);
offset += view_offset;
bp.board.grid.draw(d, &globals.textures, offset, self.zoom);
bp.board
.grid
.draw(d, &globals.textures, offset, self.zoom, false);
bp.board.draw_comments(d, offset, self.zoom);
}
if self.mouse.pos().x < SIDEBAR_WIDTH as f32 {

View file

@ -132,8 +132,7 @@ enum BindingEdit {
}
impl Input {
pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals, y: i32) {
let mut y = y + 96;
pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals, mut y: i32) {
if self.editing_binding.is_some() {
globals.mouse.clear();
}

View file

@ -285,7 +285,7 @@ impl Grid {
out
}
pub fn draw(&self, d: &mut RaylibDrawHandle, textures: &Textures, offset: Vector2, scale: f32) {
pub fn draw(&self, d: &mut RaylibDrawHandle, textures: &Textures, offset: Vector2, scale: f32, power_directions: bool) {
let tile_size = (TILE_TEXTURE_SIZE * scale) as i32;
let start_x = (-offset.x as i32) / tile_size - 1;
@ -304,14 +304,14 @@ impl Grid {
}
let texture = textures.get(texname);
draw_scaled_texture(d, texture, px, py, scale);
#[cfg(debug_assertions)]
// todo some in-game option to show power direction
if power_directions
{
if let Tile::Powerable(_, state) = &tile {
for dir in Direction::ALL {
if state.get_dir(dir) {
let texture = textures.get(dir.debug_arrow_texture_name());
draw_scaled_texture(d, texture, px, py, scale);
}
}}
}
}
} else {

View file

@ -2,7 +2,7 @@ use std::ops::Range;
use crate::{
theme::*,
util::{draw_scaled_texture, MouseInput, Scroll, Textures},
util::{draw_scaled_texture, rect, MouseInput, Scroll, Textures},
Globals,
};
use raylib::prelude::*;
@ -160,6 +160,35 @@ impl Tooltip {
}
}
pub fn toggle_button(
(d, mouse): (&mut RaylibDrawHandle, &MouseInput),
x: i32,
y: i32,
width: i32,
height: i32,
val: &mut bool,
) {
let margin = 5;
let mouse_pos = mouse.pos();
let bounds = rect(x, y, width, height);
let hover = bounds.check_collision_point_rec(mouse_pos);
d.draw_rectangle(x, y, width, height, widget_bg(hover));
let pressed = hover && mouse.left_click();
if pressed {
*val = !*val;
}
if *val {
d.draw_rectangle(
x + margin,
y + margin,
width - margin * 2,
height - margin * 2,
Color::WHITE,
);
}
}
pub fn simple_button(
(d, mouse): (&mut RaylibDrawHandle, &MouseInput),
x: i32,
@ -168,12 +197,7 @@ pub fn simple_button(
height: i32,
) -> bool {
let mouse_pos = mouse.pos();
let bounds = Rectangle {
x: x as f32,
y: y as f32,
width: width as f32,
height: height as f32,
};
let bounds = rect(x, y, width, height);
let hover = bounds.check_collision_point_rec(mouse_pos);
let pressed = hover && mouse.left_click();
d.draw_rectangle(x, y, width, height, widget_bg(hover));