Skip to content
21 changes: 14 additions & 7 deletions crates/anyps5-launcher/src/app/panels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,13 +1019,15 @@ impl PanelHost {
let events = self.take_events(wanted);
let kind = QuitKind::CancelUnlock;
if cx.model.cancel_ask.is_none() {
// The question is answered (or gone): the card still has to play its exit, so this
// does not return before `show`. Returning here left the panel in its closing state
// with nothing drawing it, so it vanished at once and, on the next question, showed
// for one frame at full strength, left again and only then opened.
self.cancel_unlock.close();
if wanted {
cx.model.dismiss_overlay();
}
return;
}
if wanted && !self.cancel_unlock.is_active() {
} else if wanted && !self.cancel_unlock.is_active() {
self.cancel_unlock.open(kind);
} else if !wanted && self.cancel_unlock.is_active() {
if cx.model.overlay.is_some_and(Overlay::is_side_panel) {
Expand All @@ -1050,14 +1052,19 @@ impl PanelHost {
/// The question before the window closes while games are unlocked or removed.
fn quit_ui(&mut self, cx: &mut OverlayCx<'_>, wanted: bool) {
let events = self.take_events(wanted);
let Some(kind) = cx.model.quit_ask else {
// Once the question is answered `quit_ask` is gone, but the card still has to play its
// exit, so this does not return before `show` (the card draws from what it showed last;
// the kind only matters while it is open). Returning here left the panel in its closing
// state with nothing drawing it: it vanished at once and, on the next question, showed
// for one frame at full strength, left again and only then opened.
let asked = cx.model.quit_ask;
let kind = asked.unwrap_or(QuitKind::Unlocking);
if asked.is_none() {
self.quit.close();
if wanted {
cx.model.dismiss_overlay();
}
return;
};
if wanted && !self.quit.is_active() {
} else if wanted && !self.quit.is_active() {
self.quit.open(kind);
} else if !wanted && self.quit.is_active() {
if cx.model.overlay.is_some_and(Overlay::is_side_panel) {
Expand Down
17 changes: 13 additions & 4 deletions crates/anyps5-launcher/src/screens/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::ui::glass::{GlassStyle, paint_glass};
use crate::ui::i18n::Language;
use crate::ui::icons::Icon;
use crate::ui::input::Command;
use crate::ui::pageblur;
use crate::ui::sound::Cue;
use crate::ui::text;
use crate::ui::theme::{self, TextStyle, color, radius, shadows, size, space, ty};
Expand Down Expand Up @@ -269,6 +270,7 @@ fn paint(
Motion::Overlay,
);
if v <= 0.001 && !open {
pageblur::release(ctx, id);
return None;
}
let v = v.clamp(0.0, 1.0);
Expand All @@ -286,7 +288,10 @@ fn paint(
// Text carries explicit colours, so only the painter's opacity fades it with the card.
let mut text_painter = painter.clone();
text_painter.set_opacity(v);
// The flat dim holds until the blurred page arrives (a frame or two) and stays under
// High Contrast; the blur then fades in over it.
paint_scrim(&painter, screen, SCRIM * v);
pageblur::paint(ctx, &painter, screen, id, open, v);

let width = card_width(screen.width());
let inner = width - 2.0 * CARD_PADDING;
Expand Down Expand Up @@ -336,10 +341,14 @@ fn paint(
..shadows::toast()
},
);
let mut style = GlassStyle::glass(radius::LARGE, 0.6);
style.black *= v;
style.alpha = v;
paint_glass(ctx, &painter, rect, style);
// The card is a translucent pane over the blurred page; until that page has been
// captured (and under High Contrast) it is the usual glass panel.
if !pageblur::paint_card(ctx, &painter, rect, radius::LARGE, id, v) {
let mut style = GlassStyle::glass(radius::LARGE, 0.6);
style.black *= v;
style.alpha = v;
paint_glass(ctx, &painter, rect, style);
}

let mut y = rect.min.y + CARD_PADDING;
let x = rect.min.x + CARD_PADDING;
Expand Down
6 changes: 5 additions & 1 deletion crates/anyps5-launcher/src/screens/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2656,7 +2656,11 @@ fn draw(
area.max,
);
let mut child = ui.new_child(UiBuilder::new().max_rect(list_rect));
child.set_opacity(fade_in.clamp(0.0, 1.0));
// Multiplied, not set: the panel fades its whole content (title, rail, rows) with its own
// openness, and `set_opacity` would replace that fade with the rows' own. The rows then stayed
// fully opaque while the page closed (the rest of the panel was already gone) and vanished in
// the last frame.
child.multiply_opacity(fade_in.clamp(0.0, 1.0));
let options = ListOptions {
accent,
language,
Expand Down
7 changes: 7 additions & 0 deletions crates/anyps5-launcher/src/ui/background.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ impl Backdrop {
let light = self.theme.is_light() && !self.window_glass;
let t = ctx.animate_to("backdrop/light", f32::from(light), Motion::Fade);
crate::ui::theme::set_light(t);
// The question cards wear the colour of the look on screen (Game Colors: the game's).
let tones = if self.theme == Theme::GameColors {
self.game_palette
} else {
self.theme.palette()
};
crate::ui::theme::set_card_wash(tones.card_wash());
let dt = f64::from(ctx.input(|i| i.unstable_dt));
let paused = self.paused || ctx.reduced_motion() || self.window_glass;
self.clock.advance(dt, paused);
Expand Down
19 changes: 17 additions & 2 deletions crates/anyps5-launcher/src/ui/chrome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,16 @@ pub fn fullscreen_panel<R>(
add_contents: impl FnOnce(&mut Ui, f32) -> R,
) -> Option<R> {
let id = Id::unique(id);
let v = ctx.animate_to((id, "open"), if open { 1.0 } else { 0.0 }, Motion::Overlay);
// `animate_from_to`, not `animate_to`: a panel is only drawn while it is active, so its tracker
// is born on the very frame it opens, and `animate_to` starts a new tracker at its target (no
// entrance). The first opening (the "..." of a game, say) then appeared at once; from the
// second on the tracker existed, parked at 0, and the spring played.
let v = ctx.animate_from_to(
(id, "open"),
0.0,
if open { 1.0 } else { 0.0 },
Motion::Overlay,
);
if v <= 0.001 && !open {
return None;
}
Expand All @@ -1799,6 +1808,10 @@ pub fn fullscreen_panel<R>(
black: style.black * v.clamp(0.0, 1.0),
overlay: fade(style.overlay, v),
material_mix: lerp(0.0, style.material_mix, v.clamp(0.0, 1.0)),
// The glass covers the page it opens over in the first half of the opening and
// lets it show again on the way out; before, it was opaque from the first frame,
// so the page vanished in one frame and the panel seemed to cut in.
alpha: style.alpha * (v * 2.0).clamp(0.0, 1.0),
..style
};
paint_glass(ctx, &painter, screen, faded);
Expand All @@ -1810,7 +1823,9 @@ pub fn fullscreen_panel<R>(
};
let area = scale_rect(screen, scale);
let mut child = ui.new_child(UiBuilder::new().max_rect(area));
child.set_opacity(v.clamp(0.0, 1.0));
// The contents come in once the glass has mostly covered the page, so the two pages'
// texts never overlap.
child.set_opacity(((v - 0.25) / 0.75).clamp(0.0, 1.0));
result = Some(add_contents(&mut child, v));
});
result
Expand Down
1 change: 1 addition & 0 deletions crates/anyps5-launcher/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub mod os_emoji;
pub mod osk;
pub mod pad_hub;
pub mod pad_info;
pub mod pageblur;
pub mod press;
pub mod ps_button;
pub mod reveal;
Expand Down
Loading
Loading