From ab5ba3f3e5f4f1f1583d798ace26683cb572ed18 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 15 Sep 2023 11:13:04 -0700 Subject: [PATCH] assume starty can be nil in update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a backport of a bugfix in pensieve.love. It's not _technically_ a bug here in lines.love, but it seems worth establishing an architectural invariant (or rather lack of invariant). LÖVE's standard event loop performs the following sequence of operations in a single frame: * process events * update * draw Ideally any mutations to global state happen during the first two phases, while drawing includes no mutation. However, there is a special case: `starty`, the top y coordinate for each each line in the editor. This is used all over the place, and the cheapest way to compute it is to simply save it while drawing. However, draw by definition only updates `starty` for lines that are drawn on screen. To avoid stale data on lines off screen, say after scrolling, events often clear `starty` for all lines, leaving it to the next draw phase to repopulate the right lines. Sandwiched between the above two "however"s, the update phase needs to gracefully handle `starty` being nil in the occasional frame right after an event. I think I've audited all our uses of `starty`, and this commit fixes the only place that violates this rule. --- drawing.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drawing.lua b/drawing.lua index ac4990a..a98f5b2 100644 --- a/drawing.lua +++ b/drawing.lua @@ -249,6 +249,12 @@ function Drawing.update(State) if State.lines.current_drawing == nil then return end local drawing = State.lines.current_drawing local line_cache = State.line_cache[State.lines.current_drawing_index] + if line_cache.starty == nil then + -- some event cleared starty just this frame + -- draw in this frame will soon set starty + -- just skip this frame + return + end assert(drawing.mode == 'drawing') local pmx, pmy = App.mouse_x(), App.mouse_y() local mx = Drawing.coord(pmx-State.left, State.width)