drain object queues after each object

This commit is contained in:
2026-07-10 01:20:26 -05:00
parent 386967e936
commit 325d2c27dd
13 changed files with 259 additions and 106 deletions
+19 -1
View File
@@ -36,7 +36,7 @@ use crate::input::{
use crate::log::{LogWidget, log_preview_line};
use crate::menu::MenuWidget;
use crate::mode::{Mode, PendingMode};
use crate::scroll_overlay::ScrollOverlayWidget;
use crate::scroll_overlay::{ScrollOpenAnimation, ScrollOverlayWidget};
use crate::speech::SpeechBubblesWidget;
use crate::status::StatusSidebarWidget;
use crate::ui::Ui;
@@ -142,6 +142,11 @@ fn run(terminal: &mut ratatui::DefaultTerminal, mode: &mut Mode, ui: &mut Ui) ->
// only changed cells are actually written to the terminal.
terminal.draw(|frame| draw(frame, mode, ui))?;
// Remember whether a scroll overlay was already open, so we can detect one
// that opens this frame — from a player bump during input *or* from a tick —
// and play its open animation exactly once (see after the tick below).
let scroll_active_before = matches!(mode, Mode::Play(g) if g.active_scroll.is_some());
// Wait for input only up to the next frame deadline so the loop wakes to
// tick even with no keypresses.
let timeout = FRAME.saturating_sub(last_tick.elapsed());
@@ -194,6 +199,19 @@ fn run(terminal: &mut ratatui::DefaultTerminal, mode: &mut Mode, ui: &mut Ui) ->
ui.tick(dt, mode);
}
// A scroll can be opened either by a script tick or by a player bump during
// input handling (bump reactions now resolve within try_move). Start its open
// animation once, whichever opened it — detected by the scroll appearing since
// the top of this frame while no animation is running.
if ui.active_animation.is_none()
&& !scroll_active_before
&& let Mode::Play(game) = &*mode
&& let Some(scroll) = &game.active_scroll
{
let lines = scroll.lines.clone();
ui.active_animation = Some(Box::new(ScrollOpenAnimation::new(lines)));
}
// Apply any Play↔Edit switch a menu action requested this frame.
apply_pending_mode(mode, ui);
+4 -7
View File
@@ -3,7 +3,7 @@ use crate::editor::EditorState;
use crate::log::LogState;
use crate::menu::{MenuCloseAnimation, MenuItem, MenuOpenAnimation, MenuState};
use crate::mode::{Mode, PendingMode};
use crate::scroll_overlay::{ScrollCloseAnimation, ScrollOpenAnimation, ScrollOverlayState};
use crate::scroll_overlay::{ScrollCloseAnimation, ScrollOverlayState};
use crate::transition::TransitionAnimation;
use kiln_core::Board;
use kiln_core::game::GameState;
@@ -137,15 +137,12 @@ impl Ui {
// scroll the instant its open animation finished.
let input_mode = crate::input::current_input_mode(mode, self);
match mode {
// Play: tick the game (only in Board mode), then check whether a scroll
// overlay appeared as a result of this tick.
// Play: tick the game only in Board mode (a scroll/menu overlay pauses
// it). The run loop starts the scroll open animation when one appears,
// whether from this tick or from a player bump during input.
Mode::Play(game) => {
if matches!(input_mode, crate::input::InputMode::Board) {
game.tick(dt);
if let Some(scroll) = &game.active_scroll {
let lines = scroll.lines.clone();
self.active_animation = Some(Box::new(ScrollOpenAnimation::new(lines)));
}
}
}
// Edit: only the cursor blink advances; the game does not exist here.