Interface size in finer percent steps; fixed sizes no longer double the interface

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-07 20:22:56 +01:00
1 parent d8aa0e5fc1
commit 361e1e4108
4 files changed
+52 -24

No files matched your search

+5 -5
View File
@@ -475,7 +475,6 @@ fn next_seed(seed: u32) -> u32 {
fn apply_settings(s: &Settings, r3d: &mut R3d) {
i18n::set_language(&s.language);
ui::set_ui_factor(s.ui_factor);
r3d.outlines = s.outlines;
r3d.set_wall_detail(s.wall_subdivisions());
r3d.max_lights = s.max_lights as usize;
@@ -993,10 +992,11 @@ async fn main() {
let need: u32 = 900;
// measured on the shorter side: upright (portrait) the width gets those pixels and the
// height grows with the screen, so the world and the menus keep their size. The setting
// "interface size" picks the interface pixels per world pixel: large 2, medium 3, small 4
let short = match app.settings.ui_factor {
k @ 2..=4 => rows * k as u32,
_ => rows * need.div_ceil(rows),
// "interface size" picks the interface rows in percent of the standard (100% = 1080 rows);
// on a screen with fewer rows the interface stays at the screen's rows
let short = match app.settings.ui_size {
0 => rows * need.div_ceil(rows),
p => settings::ui_size_rows(p).min((screen_width().min(screen_height()) * screen_dpi_scale()).max(1.0) as u32),
};
let (w, h) = (screen_width().max(1.0), screen_height().max(1.0));
let vrows = if h > w { (short as f32 * h / w).round() as u32 } else { short };
+5 -7
View File
@@ -141,12 +141,10 @@ fn item_value(it: Item, s: &Settings) -> String {
_ => "val.medium",
}),
Item::Lights => s.max_lights.to_string(),
Item::UiScale => tr(match s.ui_factor {
2 => "val.large",
3 => "val.medium",
4 => "val.small",
_ => "val.auto_plain",
}),
Item::UiScale => match s.ui_size {
0 => tr("val.auto_plain"),
p => format!("{p}%"),
},
Item::DebugFps => onoff(s.debug_fps),
Item::DebugFrameTime => onoff(s.debug_frame_time),
Item::DebugPing => onoff(s.debug_ping),
@@ -201,7 +199,7 @@ fn item_change(it: Item, s: &mut Settings, d: i32) {
Item::Outlines => s.outlines = !s.outlines,
Item::WallDetail => s.wall_detail = cycle(&[1u8, 2, 3], s.wall_detail, d),
Item::Lights => s.max_lights = cycle(&[8u8, 16, 24], s.max_lights, d),
Item::UiScale => s.ui_factor = cycle(&[0u8, 2, 3, 4], if [0, 2, 3, 4].contains(&s.ui_factor) { s.ui_factor } else { 0 }, d),
Item::UiScale => s.ui_size = cycle(&crate::settings::UI_SIZES, s.ui_size, d),
Item::RenderScale => s.pixel_rows = cycle(&[270u16, 360, 480], if [270, 360, 480].contains(&s.pixel_rows) { s.pixel_rows } else { 360 }, d),
Item::DebugFps => s.debug_fps = !s.debug_fps,
Item::DebugFrameTime => s.debug_frame_time = !s.debug_frame_time,
+40 -2
View File
@@ -148,7 +148,8 @@ pub struct Settings {
pub outlines: bool,
pub wall_detail: u8, // 1 low, 2 medium, 3 high
pub max_lights: u8, // 8, 16 or 24
pub ui_factor: u8, // interface size: 0 = automatic, 2 large, 3 medium, 4 small (interface pixels per world pixel)
pub ui_factor: u8, // old interface size (2 large, 3 medium, 4 small; only read to carry old settings over)
pub ui_size: u16, // interface size in percent of the standard (100 = 1080 interface rows), 0 = automatic
pub render_scale: u8, // old pixel-look divisor (no longer used, kept for old settings files)
pub pixel_rows: u16, // pixel look: rows of the world on every screen (270, 360, 480)
pub touch_ui: u8, // touch interface: 0 = automatic (after the first touch), 1 = on, 2 = off
@@ -189,6 +190,7 @@ impl Default for Settings {
wall_detail: 2,
max_lights: 24,
ui_factor: 0,
ui_size: 0,
render_scale: 1,
pixel_rows: 360,
touch_ui: 0,
@@ -244,8 +246,30 @@ impl Settings {
}
pub fn from_json(s: &str) -> Option<Settings> {
serde_json::from_str(s).ok()
let mut st: Settings = serde_json::from_str(s).ok()?;
// old interface sizes (pixels per world pixel) become percentages
if st.ui_size == 0 {
st.ui_size = match st.ui_factor {
2 => 150,
3 => 100,
4 => 75,
_ => 0,
};
}
st.ui_factor = 0;
if st.ui_size != 0 && !UI_SIZES.contains(&st.ui_size) {
st.ui_size = 0;
}
Some(st)
}
}
// the interface sizes of the settings menu in percent (0 = automatic), from small to large
pub const UI_SIZES: [u16; 9] = [0, 75, 85, 100, 115, 130, 150, 175, 200];
// interface rows of the virtual screen for a size in percent (100% = 1080 rows)
pub fn ui_size_rows(percent: u16) -> u32 {
(1080.0 * 100.0 / percent.max(1) as f32).round() as u32
}
#[cfg(test)]
@@ -273,4 +297,18 @@ mod tests {
assert!(!old.debug_trigger_zones);
assert!(!old.debug_command_markers);
}
#[test]
fn interface_size_percent() {
let old = Settings::from_json(r#"{"ui_factor":2}"#).unwrap();
assert_eq!(old.ui_size, 150);
assert_eq!(old.ui_factor, 0);
let mut s = Settings::default();
s.ui_size = 115;
assert_eq!(Settings::from_json(&s.to_json()).unwrap().ui_size, 115);
assert_eq!(Settings::from_json(r#"{"ui_size":123}"#).unwrap().ui_size, 0);
assert_eq!(ui_size_rows(100), 1080);
assert_eq!(ui_size_rows(150), 720);
assert!(ui_size_rows(200) < ui_size_rows(175));
}
}
+2 -10
View File
@@ -15,9 +15,9 @@ use macroquad::prelude::*;
// the frame (see begin_ui, end_frame) - on every device the same pixel grid. Small screens
// draw in device pixels. Every size is an integer multiple
// of the font's 6x8 pixel glyphs: small text = 1*F, normal text = 2*F, titles = 4*F, where F
// is the interface factor (automatic from the resolution or fixed in the settings).
// is the interface factor (1 on the virtual screen, whose rows follow the "interface size"
// setting; automatic from the resolution in device pixels).
thread_local! {
static UI_FACTOR_SETTING: std::cell::Cell<u8> = std::cell::Cell::new(0);
static TOUCH: std::cell::Cell<bool> = std::cell::Cell::new(false);
static POINTER: std::cell::Cell<(f32, f32)> = std::cell::Cell::new((-1e5, -1e5));
static VIRTUAL_ROWS: std::cell::Cell<u32> = std::cell::Cell::new(0);
@@ -43,10 +43,6 @@ pub fn device_dpr() -> f32 {
screen_dpi_scale()
}
pub fn set_ui_factor(f: u8) {
UI_FACTOR_SETTING.with(|c| c.set(f));
}
// touch interface active (bigger interface, category toolbar, gestures)
pub fn set_touch(on: bool) {
TOUCH.with(|c| c.set(on));
@@ -84,10 +80,6 @@ pub fn mouse() -> (f32, f32) {
// interface factor (integer)
#[allow(non_snake_case)]
pub fn F() -> u32 {
let set = UI_FACTOR_SETTING.with(|c| c.get());
if set > 0 {
return set as u32;
}
// the virtual screen already has the right size for the interface
if virtual_rows() > 0 {
return 1;