Skip to content

Commit 8bb8adf

Browse files
committed
Scan world line by line instead of using hilbert curve
This should prevent some glitches due to the way Noita generates the world.
1 parent 355521b commit 8bb8adf

File tree

1 file changed

+60
-5
lines changed

1 file changed

+60
-5
lines changed

files/capture.lua

+60-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- Copyright (c) 2019-2022 David Vogel
1+
-- Copyright (c) 2019-2023 David Vogel
22
--
33
-- This software is released under the MIT License.
44
-- https://opensource.org/licenses/MIT
@@ -200,13 +200,13 @@ function Capture:StartCapturingSpiral(origin, captureGridSize, outputPixelScale)
200200
self.MapCapturingCtx:Run(nil, handleDo, handleEnd, mapCapturingCtxErrHandler)
201201
end
202202

203-
---Starts the capturing process of the given area.
203+
---Starts the capturing process of the given area using a hilbert curve.
204204
---Use `Capture.MapCapturingCtx` to stop, control or view the process.
205205
---@param topLeft Vec2 -- Top left of the to be captured rectangle.
206206
---@param bottomRight Vec2 -- Non included bottom left of the to be captured rectangle.
207207
---@param captureGridSize number -- The grid size in world pixels.
208208
---@param outputPixelScale number|nil -- The resulting image pixel to world pixel ratio.
209-
function Capture:StartCapturingArea(topLeft, bottomRight, captureGridSize, outputPixelScale)
209+
function Capture:StartCapturingAreaHilbert(topLeft, bottomRight, captureGridSize, outputPixelScale)
210210

211211
-- Create file that signals that there are files in the output directory.
212212
local file = io.open("mods/noita-mapcap/output/nonempty", "a")
@@ -268,6 +268,61 @@ function Capture:StartCapturingArea(topLeft, bottomRight, captureGridSize, outpu
268268
self.MapCapturingCtx:Run(nil, handleDo, handleEnd, mapCapturingCtxErrHandler)
269269
end
270270

271+
---Starts the capturing process of the given area by scanning from left to right, and top to bottom.
272+
---Use `Capture.MapCapturingCtx` to stop, control or view the process.
273+
---@param topLeft Vec2 -- Top left of the to be captured rectangle.
274+
---@param bottomRight Vec2 -- Non included bottom left of the to be captured rectangle.
275+
---@param captureGridSize number -- The grid size in world pixels.
276+
---@param outputPixelScale number|nil -- The resulting image pixel to world pixel ratio.
277+
function Capture:StartCapturingAreaScan(topLeft, bottomRight, captureGridSize, outputPixelScale)
278+
279+
-- Create file that signals that there are files in the output directory.
280+
local file = io.open("mods/noita-mapcap/output/nonempty", "a")
281+
if file ~= nil then file:close() end
282+
283+
---The rectangle in grid coordinates.
284+
---@type Vec2, Vec2
285+
local gridTopLeft, gridBottomRight = (topLeft / captureGridSize):Rounded("floor"), (bottomRight / captureGridSize):Rounded("floor")
286+
287+
---Size of the rectangle in grid coordinates.
288+
---@type Vec2
289+
local gridSize = gridBottomRight - gridTopLeft
290+
291+
---Process main callback.
292+
---@param ctx ProcessRunnerCtx
293+
local function handleDo(ctx)
294+
Modification.SetCameraFree(true)
295+
ctx.state = { Current = 0, Max = gridSize.x * gridSize.y }
296+
297+
for gridY = gridTopLeft.y, gridBottomRight.y-1, 1 do
298+
for gridX = gridTopLeft.x, gridBottomRight.x-1, 1 do
299+
-- Prematurely stop capturing if that is requested by the context.
300+
if ctx:IsStopping() then return end
301+
302+
---Position in grid coordinates.
303+
---@type Vec2
304+
local gridPos = Vec2(gridX, gridY)
305+
306+
---Position in world coordinates.
307+
---@type Vec2
308+
local pos = gridPos * captureGridSize
309+
pos:Add(Vec2(captureGridSize / 2, captureGridSize / 2)) -- Move to center of grid cell.
310+
captureScreenshot(pos, true, true, ctx, outputPixelScale)
311+
ctx.state.Current = ctx.state.Current + 1
312+
end
313+
end
314+
end
315+
316+
---Process end callback.
317+
---@param ctx ProcessRunnerCtx
318+
local function handleEnd(ctx)
319+
Modification.SetCameraFree()
320+
end
321+
322+
-- Run process, if there is no other running right now.
323+
self.MapCapturingCtx:Run(nil, handleDo, handleEnd, mapCapturingCtxErrHandler)
324+
end
325+
271326
---Starts the live capturing process.
272327
---Use `Capture.MapCapturingCtx` to stop, control or view the process.
273328
---@param outputPixelScale number|nil -- The resulting image pixel to world pixel ratio.
@@ -661,11 +716,11 @@ function Capture:StartCapturing()
661716
local topLeft = Vec2(ModSettingGet("noita-mapcap.area-top-left"))
662717
local bottomRight = Vec2(ModSettingGet("noita-mapcap.area-bottom-right"))
663718

664-
self:StartCapturingArea(topLeft, bottomRight, captureGridSize, outputPixelScale)
719+
self:StartCapturingAreaScan(topLeft, bottomRight, captureGridSize, outputPixelScale)
665720
else
666721
local predefinedArea = Config.CaptureArea[area]
667722
if predefinedArea then
668-
self:StartCapturingArea(predefinedArea.TopLeft, predefinedArea.BottomRight, captureGridSize, outputPixelScale)
723+
self:StartCapturingAreaScan(predefinedArea.TopLeft, predefinedArea.BottomRight, captureGridSize, outputPixelScale)
669724
else
670725
Message:ShowRuntimeError("PredefinedArea", string.format("Unknown predefined capturing area %q", tostring(area)))
671726
end

0 commit comments

Comments
 (0)