Interface on the pixel grid: a virtual screen of whole multiples of the world's rows, sharp-scaled to every device; compact title menu on short screens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-06 07:33:25 +01:00
1 parent aa39e66da9
commit e7fc0a4751
5 files changed
+142 -66

No files matched your search

+14 -9
View File
@@ -7,6 +7,11 @@ use macroquad::prelude::*;
const LONG_PRESS: f64 = 0.5; // seconds without moving
const DOUBLE_TAP: f64 = 0.3; // max. time between two taps
// touches come in device pixels; everything here works in interface units (see ui::dpr)
fn ui_pos(p: Vec2) -> Vec2 {
p * crate::ui::dpr() / crate::ui::device_dpr()
}
const DRAG_CSS: f32 = 10.0; // movement (CSS pixels) that turns a press into a drag
#[derive(Clone, Copy, Debug)]
@@ -92,13 +97,13 @@ impl TouchInput {
if active.len() >= 2 {
self.start_two(active[0], active[1]);
} else if let Some(t) = active.first() {
out.push(Gesture::Press(t.position));
self.st = St::One { id: t.id, start: t.position, pos: t.position, t0: now, drag: false, long: false };
out.push(Gesture::Press(ui_pos(t.position)));
self.st = St::One { id: t.id, start: ui_pos(t.position), pos: ui_pos(t.position), t0: now, drag: false, long: false };
} else if let Some(t) = ts.iter().find(|t| ended(t.phase)) {
// started and ended between two frames
out.push(Gesture::Press(t.position));
self.tap(t.position, now, want_double, &mut out);
out.push(Gesture::Release(t.position));
out.push(Gesture::Press(ui_pos(t.position)));
self.tap(ui_pos(t.position), now, want_double, &mut out);
out.push(Gesture::Release(ui_pos(t.position)));
}
}
St::One { id, start, t0, mut drag, mut long, .. } => {
@@ -108,7 +113,7 @@ impl TouchInput {
} else {
match find(id) {
Some(t) if !ended(t.phase) => {
let pos = t.position;
let pos = ui_pos(t.position);
if !drag && pos.distance(start) > drag_px {
drag = true;
out.push(Gesture::DragStart(start));
@@ -122,7 +127,7 @@ impl TouchInput {
self.st = St::One { id, start, pos, t0, drag, long };
}
other => {
let pos = other.map(|t| t.position).unwrap_or(start);
let pos = other.map(|t| ui_pos(t.position)).unwrap_or(start);
if drag {
out.push(Gesture::DragEnd);
} else if !long {
@@ -136,7 +141,7 @@ impl TouchInput {
}
St::Two { a, b, center, dist, angle } => match (find(a).filter(|t| !ended(t.phase)), find(b).filter(|t| !ended(t.phase))) {
(Some(ta), Some(tb)) => {
let (c, d, an) = Self::geometry(ta.position, tb.position);
let (c, d, an) = Self::geometry(ui_pos(ta.position), ui_pos(tb.position));
let mut rot = an - angle;
if rot > std::f32::consts::PI {
rot -= std::f32::consts::TAU;
@@ -169,7 +174,7 @@ impl TouchInput {
}
fn start_two(&mut self, a: &Touch, b: &Touch) {
let (center, dist, angle) = Self::geometry(a.position, b.position);
let (center, dist, angle) = Self::geometry(ui_pos(a.position), ui_pos(b.position));
self.pending_tap = None;
self.st = St::Two { a: a.id, b: b.id, center, dist, angle };
}