fix: adjust pet size to screen resolution
This commit is contained in:
+26
-19
@@ -6,6 +6,7 @@ mod climbing;
|
||||
pub use climbing::ClimbState;
|
||||
|
||||
pub const SPRITE_SCALE: f64 = 3.0;
|
||||
const REFERENCE_SCREEN_HEIGHT: f64 = 1080.0;
|
||||
const WALK_SPEED: f64 = 2.0 / 0.03;
|
||||
const GRAVITY: f64 = 900.0;
|
||||
const SNAP_DISTANCE: f64 = 30.0;
|
||||
@@ -350,6 +351,7 @@ pub struct World {
|
||||
pub quit_requested: bool,
|
||||
pub sounds: Vec<&'static str>,
|
||||
pub quitting: Option<f64>,
|
||||
screen_scale: f64,
|
||||
rng: StdRng,
|
||||
next_id: i32,
|
||||
menu_actor: Option<i32>,
|
||||
@@ -378,6 +380,7 @@ impl World {
|
||||
quit_requested: false,
|
||||
sounds: Vec::with_capacity(8),
|
||||
quitting: None,
|
||||
screen_scale: 1.0,
|
||||
rng,
|
||||
next_id: 2,
|
||||
menu_actor: None,
|
||||
@@ -389,6 +392,7 @@ impl World {
|
||||
|
||||
pub fn update_desktop(&mut self, snapshot: DesktopSnapshot) {
|
||||
let first = self.pets.is_empty();
|
||||
self.screen_scale = (snapshot.screen.height / REFERENCE_SCREEN_HEIGHT).clamp(0.5, 2.0);
|
||||
self.bounds = snapshot
|
||||
.work_area
|
||||
.intersection(snapshot.screen)
|
||||
@@ -422,7 +426,7 @@ impl World {
|
||||
self.pets.push(pet);
|
||||
}
|
||||
for pet in &mut self.pets {
|
||||
fit_scale(pet, self.bounds);
|
||||
fit_scale(pet, self.bounds, self.screen_scale, self.sitting);
|
||||
reconcile_pet(
|
||||
pet,
|
||||
self.sitting,
|
||||
@@ -524,23 +528,11 @@ impl World {
|
||||
return;
|
||||
}
|
||||
let previous_scale = pet.scale;
|
||||
let (previous_width, _) = pet.size(self.sitting, None);
|
||||
let previous_anchor = pet.attachment_height(self.sitting);
|
||||
pet.requested_scale = requested_scale;
|
||||
fit_scale(pet, self.bounds);
|
||||
fit_scale(pet, self.bounds, self.screen_scale, self.sitting);
|
||||
if pet.scale == previous_scale {
|
||||
return;
|
||||
}
|
||||
let ratio = pet.scale / previous_scale;
|
||||
if pet.dragging {
|
||||
let (offset_x, offset_y) = pet.drag_offset;
|
||||
pet.drag_offset = (offset_x * ratio, offset_y * ratio);
|
||||
pet.x += offset_x - pet.drag_offset.0;
|
||||
pet.y += offset_y - pet.drag_offset.1;
|
||||
} else {
|
||||
pet.x += previous_width * (1.0 - ratio) / 2.0;
|
||||
pet.y += previous_anchor * (1.0 - ratio);
|
||||
}
|
||||
reconcile_pet(
|
||||
pet,
|
||||
self.sitting,
|
||||
@@ -600,7 +592,7 @@ impl World {
|
||||
self.bounds.y + self.rng.random_range(0.1..0.7) * self.bounds.height,
|
||||
);
|
||||
self.next_id += 1;
|
||||
fit_scale(&mut pet, self.bounds);
|
||||
fit_scale(&mut pet, self.bounds, self.screen_scale, false);
|
||||
let (width, height) = pet.size(false, None);
|
||||
(pet.x, pet.y) = constrain_position(self.bounds, &self.panels, pet.x, pet.y, width, height);
|
||||
self.pets.push(pet);
|
||||
@@ -655,7 +647,7 @@ impl World {
|
||||
velocity_y: 0.0,
|
||||
});
|
||||
self.next_id += 1;
|
||||
fit_scale(main, self.bounds);
|
||||
fit_scale(main, self.bounds, self.screen_scale, self.sitting);
|
||||
reconcile_pet(
|
||||
main,
|
||||
self.sitting,
|
||||
@@ -955,13 +947,28 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
fn fit_scale(pet: &mut PetState, bounds: Rectangle) {
|
||||
fn fit_scale(pet: &mut PetState, bounds: Rectangle, screen_scale: f64, sitting: bool) {
|
||||
let previous_scale = pet.scale;
|
||||
let (previous_width, _) = pet.size(sitting, None);
|
||||
let previous_anchor = pet.attachment_height(sitting);
|
||||
let image = pet.image(false, None);
|
||||
pet.scale = pet
|
||||
.requested_scale
|
||||
pet.scale = (screen_scale * pet.requested_scale)
|
||||
.min(bounds.width / image.width)
|
||||
.min(bounds.height / image.height)
|
||||
.max(0.01);
|
||||
if pet.scale == previous_scale {
|
||||
return;
|
||||
}
|
||||
let ratio = pet.scale / previous_scale;
|
||||
if pet.dragging {
|
||||
let (offset_x, offset_y) = pet.drag_offset;
|
||||
pet.drag_offset = (offset_x * ratio, offset_y * ratio);
|
||||
pet.x += offset_x - pet.drag_offset.0;
|
||||
pet.y += offset_y - pet.drag_offset.1;
|
||||
} else {
|
||||
pet.x += previous_width * (1.0 - ratio) / 2.0;
|
||||
pet.y += previous_anchor * (1.0 - ratio);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visible_surfaces(windows: &[WindowRecord], bounds: Rectangle) -> Vec<Surface> {
|
||||
|
||||
+85
-1
@@ -11,7 +11,7 @@ fn rectangle(x: f64, y: f64, width: f64, height: f64) -> Rectangle {
|
||||
|
||||
fn snapshot(windows: Vec<WindowRecord>) -> DesktopSnapshot {
|
||||
DesktopSnapshot {
|
||||
screen: rectangle(0.0, 0.0, 1280.0, 800.0),
|
||||
screen: rectangle(0.0, 0.0, 1280.0, 1080.0),
|
||||
work_area: rectangle(40.0, 24.0, 1240.0, 728.0),
|
||||
windows,
|
||||
panels: vec![rectangle(0.0, 752.0, 1280.0, 48.0)],
|
||||
@@ -470,6 +470,90 @@ fn bicycle_doubles_vertical_climbing_speed() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initial_size_tracks_screen_height_and_not_panel_size() {
|
||||
for (screen_width, screen_height, expected_size) in [
|
||||
(1280.0, 720.0, (48.0, 64.0)),
|
||||
(1920.0, 1080.0, (72.0, 96.0)),
|
||||
(3840.0, 2160.0, (144.0, 192.0)),
|
||||
] {
|
||||
let mut desktop = snapshot(Vec::new());
|
||||
desktop.screen = rectangle(0.0, 0.0, screen_width, screen_height);
|
||||
desktop.work_area = desktop.screen;
|
||||
desktop.panels.clear();
|
||||
let mut world = World::with_rng(StdRng::seed_from_u64(9));
|
||||
world.update_desktop(desktop);
|
||||
assert_eq!(world.pets[0].size(false, None), expected_size);
|
||||
|
||||
let mut desktop = snapshot(Vec::new());
|
||||
desktop.screen = rectangle(0.0, 0.0, screen_width, screen_height);
|
||||
desktop.work_area = rectangle(0.0, 0.0, screen_width, screen_height - 48.0);
|
||||
desktop.panels.clear();
|
||||
world.update_desktop(desktop);
|
||||
assert_eq!(world.pets[0].size(false, None), expected_size);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_limits_follow_the_screen_relative_default() {
|
||||
let mut desktop = snapshot(Vec::new());
|
||||
desktop.screen = rectangle(0.0, 0.0, 1280.0, 720.0);
|
||||
desktop.work_area = desktop.screen;
|
||||
desktop.panels.clear();
|
||||
let mut world = World::with_rng(StdRng::seed_from_u64(9));
|
||||
world.update_desktop(desktop);
|
||||
for _ in 0..6 {
|
||||
world.resize_pet(1, -1.0);
|
||||
}
|
||||
assert_eq!(world.pets[0].size(false, None), (24.0, 32.0));
|
||||
for _ in 0..18 {
|
||||
world.resize_pet(1, 1.0);
|
||||
}
|
||||
assert_eq!(world.pets[0].size(false, None), (96.0, 128.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn screen_resize_preserves_user_scale_and_drag_grip() {
|
||||
let mut world = world();
|
||||
world.pets[0].x = 300.0;
|
||||
world.pets[0].y = 350.0;
|
||||
let cursor = (318.0, 380.0);
|
||||
world.begin_drag(1, cursor.0, cursor.1);
|
||||
world.resize_pet(1, 6.0);
|
||||
assert_eq!(world.pets[0].size(false, None), (108.0, 144.0));
|
||||
|
||||
let mut desktop = snapshot(Vec::new());
|
||||
desktop.screen.height = 720.0;
|
||||
world.update_desktop(desktop);
|
||||
let pet = &world.pets[0];
|
||||
assert_eq!(pet.size(false, None), (72.0, 96.0));
|
||||
assert_eq!(
|
||||
(pet.x + pet.drag_offset.0, pet.y + pet.drag_offset.1),
|
||||
cursor
|
||||
);
|
||||
|
||||
world.update_desktop(snapshot(Vec::new()));
|
||||
let pet = &world.pets[0];
|
||||
assert_eq!(pet.size(false, None), (108.0, 144.0));
|
||||
assert_eq!(
|
||||
(pet.x + pet.drag_offset.0, pet.y + pet.drag_offset.1),
|
||||
cursor
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn screen_resize_keeps_the_pet_on_its_titlebar() {
|
||||
let mut world = world();
|
||||
attach_to_target(&mut world);
|
||||
let mut desktop = snapshot(vec![window("target", 100.0, 320.0, 800.0, 1)]);
|
||||
desktop.screen.height = 720.0;
|
||||
world.update_desktop(desktop);
|
||||
let pet = &world.pets[0];
|
||||
assert_eq!(pet.size(false, None), (48.0, 64.0));
|
||||
assert_eq!(pet.y + pet.attachment_height(false), 320.0);
|
||||
assert!(matches!(&pet.support, Some(Support::Window { id, .. }) if id == "target"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resize_limits_survive_desktop_and_effect_changes() {
|
||||
let mut world = world();
|
||||
|
||||
Reference in New Issue
Block a user