mirror of
https://github.com/Dadido3/noita-mapcap.git
synced 2024-11-22 21:17:33 +00:00
Update capturing stuff
- Add ability to capture while normally playing - Calculate capture area based on coordinate transformations - Improve and simplify captureScreenshot function - Move dynamic library wrappers into libraries folder - Update capture.dll to support cropping and resizing - Recompile capture.dll with newer PureBasic compiler that uses C backend - Increase capture.dll worker threads to 6 - Increase capture.dll queue size by one - Add Round and Rounded methods to Vec2 - Split magic number XML files for easier debugging - Fix some EmmyLua annotations - And and fix some comments
This commit is contained in:
parent
f2e582622e
commit
0126e706cb
@ -1,4 +1,4 @@
|
|||||||
; Copyright (c) 2019-2020 David Vogel
|
; Copyright (c) 2019-2022 David Vogel
|
||||||
;
|
;
|
||||||
; This software is released under the MIT License.
|
; This software is released under the MIT License.
|
||||||
; https://opensource.org/licenses/MIT
|
; https://opensource.org/licenses/MIT
|
||||||
@ -11,6 +11,8 @@ Structure QueueElement
|
|||||||
img.i
|
img.i
|
||||||
x.i
|
x.i
|
||||||
y.i
|
y.i
|
||||||
|
sx.i
|
||||||
|
sy.i
|
||||||
EndStructure
|
EndStructure
|
||||||
|
|
||||||
; Source: https://www.purebasic.fr/english/viewtopic.php?f=13&t=29981&start=15
|
; Source: https://www.purebasic.fr/english/viewtopic.php?f=13&t=29981&start=15
|
||||||
@ -62,7 +64,7 @@ ProcedureDLL AttachProcess(Instance)
|
|||||||
|
|
||||||
CreateDirectory("mods/noita-mapcap/output/")
|
CreateDirectory("mods/noita-mapcap/output/")
|
||||||
|
|
||||||
For i = 1 To 4
|
For i = 1 To 6
|
||||||
CreateThread(@Worker(), #Null)
|
CreateThread(@Worker(), #Null)
|
||||||
Next
|
Next
|
||||||
EndProcedure
|
EndProcedure
|
||||||
@ -78,9 +80,15 @@ Procedure Worker(*Dummy)
|
|||||||
img = Queue()\img
|
img = Queue()\img
|
||||||
x = Queue()\x
|
x = Queue()\x
|
||||||
y = Queue()\y
|
y = Queue()\y
|
||||||
|
sx = Queue()\sx
|
||||||
|
sy = Queue()\sy
|
||||||
DeleteElement(Queue())
|
DeleteElement(Queue())
|
||||||
UnlockMutex(Mutex)
|
UnlockMutex(Mutex)
|
||||||
|
|
||||||
|
If sx > 0 And sy > 0
|
||||||
|
ResizeImage(img, sx, sy)
|
||||||
|
EndIf
|
||||||
|
|
||||||
SaveImage(img, "mods/noita-mapcap/output/" + x + "," + y + ".png", #PB_ImagePlugin_PNG)
|
SaveImage(img, "mods/noita-mapcap/output/" + x + "," + y + ".png", #PB_ImagePlugin_PNG)
|
||||||
;SaveImage(img, "" + x + "," + y + ".png", #PB_ImagePlugin_PNG) ; Test
|
;SaveImage(img, "" + x + "," + y + ".png", #PB_ImagePlugin_PNG) ; Test
|
||||||
|
|
||||||
@ -88,7 +96,11 @@ Procedure Worker(*Dummy)
|
|||||||
ForEver
|
ForEver
|
||||||
EndProcedure
|
EndProcedure
|
||||||
|
|
||||||
ProcedureDLL Capture(px.i, py.i)
|
; Takes a screenshot of the client area of this process' active window.
|
||||||
|
; The portion of the client area that is captured is described by capRect, which is in window coordinates and relative to the client area.
|
||||||
|
; x and y defines the top left position of the captured rectangle in scaled world coordinates. The scale depends on the window to world pixel ratio.
|
||||||
|
; sx and sy defines the final dimensions that the screenshot will be resized to. No resize will happen if set to 0.
|
||||||
|
ProcedureDLL Capture(*capRect.RECT, x.l, y.l, sx.l, sy.l)
|
||||||
Protected hWnd.l = GetProcHwnd()
|
Protected hWnd.l = GetProcHwnd()
|
||||||
If Not hWnd
|
If Not hWnd
|
||||||
ProcedureReturn #False
|
ProcedureReturn #False
|
||||||
@ -99,12 +111,18 @@ ProcedureDLL Capture(px.i, py.i)
|
|||||||
ProcedureReturn #False
|
ProcedureReturn #False
|
||||||
EndIf
|
EndIf
|
||||||
|
|
||||||
imageID = CreateImage(#PB_Any, rect\right-rect\left, rect\bottom-rect\top)
|
; Limit the desired capture area to the actual client area of the window.
|
||||||
|
If *capRect\left < 0 : *capRect\left = 0 : EndIf
|
||||||
|
If *capRect\right > rect\right-rect\left : *capRect\right = rect\right-rect\left : EndIf
|
||||||
|
If *capRect\top < 0 : *capRect\top = 0 : EndIf
|
||||||
|
If *capRect\bottom > rect\bottom-rect\top : *capRect\bottom = rect\bottom-rect\top : EndIf
|
||||||
|
|
||||||
|
imageID = CreateImage(#PB_Any, *capRect\right-*capRect\left, *capRect\bottom-*capRect\top)
|
||||||
If Not imageID
|
If Not imageID
|
||||||
ProcedureReturn #False
|
ProcedureReturn #False
|
||||||
EndIf
|
EndIf
|
||||||
|
|
||||||
; Get DC of whole screen
|
; Get DC of window.
|
||||||
windowDC = GetDC_(hWnd)
|
windowDC = GetDC_(hWnd)
|
||||||
If Not windowDC
|
If Not windowDC
|
||||||
FreeImage(imageID)
|
FreeImage(imageID)
|
||||||
@ -117,7 +135,7 @@ ProcedureDLL Capture(px.i, py.i)
|
|||||||
FreeImage(imageID)
|
FreeImage(imageID)
|
||||||
ProcedureReturn #False
|
ProcedureReturn #False
|
||||||
EndIf
|
EndIf
|
||||||
If Not BitBlt_(hDC, 0, 0, rect\right-rect\left, rect\bottom-rect\top, windowDC, 0, 0, #SRCCOPY) ; After some time BitBlt will fail, no idea why. Also, that's moments before noita crashes.
|
If Not BitBlt_(hDC, 0, 0, *capRect\right-*capRect\left, *capRect\bottom-*capRect\top, windowDC, *capRect\left, *capRect\top, #SRCCOPY) ; After some time BitBlt will fail, no idea why. Also, that's moments before noita crashes.
|
||||||
StopDrawing()
|
StopDrawing()
|
||||||
ReleaseDC_(hWnd, windowDC)
|
ReleaseDC_(hWnd, windowDC)
|
||||||
FreeImage(imageID)
|
FreeImage(imageID)
|
||||||
@ -128,17 +146,19 @@ ProcedureDLL Capture(px.i, py.i)
|
|||||||
ReleaseDC_(hWnd, windowDC)
|
ReleaseDC_(hWnd, windowDC)
|
||||||
|
|
||||||
LockMutex(Mutex)
|
LockMutex(Mutex)
|
||||||
; Check if the queue has too many elements, if so, wait. (Simulate go's channels)
|
; Check if the queue has too many elements, if so, wait. (Emulate go's channels)
|
||||||
While ListSize(Queue()) > 0
|
While ListSize(Queue()) > 1
|
||||||
UnlockMutex(Mutex)
|
UnlockMutex(Mutex)
|
||||||
Delay(10)
|
Delay(1)
|
||||||
LockMutex(Mutex)
|
LockMutex(Mutex)
|
||||||
Wend
|
Wend
|
||||||
LastElement(Queue())
|
LastElement(Queue())
|
||||||
AddElement(Queue())
|
AddElement(Queue())
|
||||||
Queue()\img = imageID
|
Queue()\img = imageID
|
||||||
Queue()\x = px
|
Queue()\x = x
|
||||||
Queue()\y = py
|
Queue()\y = y
|
||||||
|
Queue()\sx = sx
|
||||||
|
Queue()\sy = sy
|
||||||
UnlockMutex(Mutex)
|
UnlockMutex(Mutex)
|
||||||
|
|
||||||
SignalSemaphore(Semaphore)
|
SignalSemaphore(Semaphore)
|
||||||
@ -153,12 +173,13 @@ EndProcedure
|
|||||||
;Capture(123, 123)
|
;Capture(123, 123)
|
||||||
;Delay(1000)
|
;Delay(1000)
|
||||||
|
|
||||||
; IDE Options = PureBasic 5.72 (Windows - x64)
|
; IDE Options = PureBasic 6.00 LTS (Windows - x64)
|
||||||
; ExecutableFormat = Shared dll
|
; ExecutableFormat = Shared dll
|
||||||
; CursorPosition = 90
|
; CursorPosition = 94
|
||||||
; FirstLine = 77
|
; FirstLine = 39
|
||||||
; Folding = --
|
; Folding = --
|
||||||
|
; Optimizer
|
||||||
; EnableThread
|
; EnableThread
|
||||||
; EnableXP
|
; EnableXP
|
||||||
; Executable = capture.dll
|
; Executable = capture.dll
|
||||||
; Compiler = PureBasic 5.71 LTS (Windows - x86)
|
; Compiler = PureBasic 6.00 LTS (Windows - x86)
|
Binary file not shown.
@ -7,10 +7,15 @@
|
|||||||
-- Load library modules --
|
-- Load library modules --
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
local JSON = require("noita-api.json")
|
local CameraAPI = require("noita-api.camera")
|
||||||
|
local Coords = require("coordinates")
|
||||||
local EntityAPI = require("noita-api.entity")
|
local EntityAPI = require("noita-api.entity")
|
||||||
local Utils = require("noita-api.utils")
|
|
||||||
local Hilbert = require("hilbert-curve")
|
local Hilbert = require("hilbert-curve")
|
||||||
|
local JSON = require("noita-api.json")
|
||||||
|
local ScreenCapture = require("screen-capture")
|
||||||
|
local Utils = require("noita-api.utils")
|
||||||
|
local Vec2 = require("noita-api.vec2")
|
||||||
|
local MonitorStandby = require("monitor-standby")
|
||||||
|
|
||||||
----------
|
----------
|
||||||
-- Code --
|
-- Code --
|
||||||
@ -194,47 +199,69 @@ function DebugEntityCapture()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Captures a screenshot at the given coordinates.
|
---Returns a capturing rectangle in window coordinates, and also the world coordinates for the same rectangle.
|
||||||
--- This will block until all chunks in the given area are loaded.
|
---@param pos Vec2|nil -- Position of the viewport center in world coordinates. If set to nil, the viewport center will be queried automatically.
|
||||||
---
|
---@return Vec2 topLeftCapture
|
||||||
--- @param x number -- Virtual x coordinate (World pixels) of the screen center.
|
---@return Vec2 bottomRightCapture
|
||||||
--- @param y number -- Virtual y coordinate (World pixels) of the screen center.
|
---@return Vec2 topLeftWorld
|
||||||
--- @param rx number -- Screen x coordinate of the top left corner of the screenshot rectangle.
|
---@return Vec2 bottomRightWorld
|
||||||
--- @param ry number -- Screen y coordinate of the top left corner of the screenshot rectangle.
|
local function GenerateCaptureRectangle(pos)
|
||||||
local function captureScreenshot(x, y, rx, ry)
|
local topLeft, bottomRight = Coords:ValidRenderingRect()
|
||||||
local virtualWidth, virtualHeight =
|
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
||||||
|
|
||||||
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
-- Convert valid rendering rectangle into world coordinates, and round it towards the window center.
|
||||||
local xMin, yMin = x - virtualHalfWidth, y - virtualHalfHeight
|
local topLeftWorld, bottomRightWorld = Coords:ToWorld(topLeft, pos):Rounded("ceil"), Coords:ToWorld(bottomRight, pos):Rounded("floor")
|
||||||
local xMax, yMax = xMin + virtualWidth, yMin + virtualHeight
|
|
||||||
|
-- Convert back into window coordinates, and round to nearest.
|
||||||
|
local topLeftCapture, bottomRightCapture = Coords:ToWindow(topLeftWorld, pos):Rounded(), Coords:ToWindow(bottomRightWorld, pos):Rounded()
|
||||||
|
|
||||||
|
return topLeftCapture, bottomRightCapture, topLeftWorld, bottomRightWorld
|
||||||
|
end
|
||||||
|
|
||||||
|
---Captures a screenshot at the given position in world coordinates.
|
||||||
|
---This will block until all chunks in the virtual rectangle are loaded.
|
||||||
|
---
|
||||||
|
---Don't set `ensureLoaded` to true when `pos` is nil!
|
||||||
|
---@param pos Vec2|nil -- Position of the viewport center in world coordinates. If set to nil, the viewport will not be modified.
|
||||||
|
---@param ensureLoaded boolean|nil -- If true, the function will wait until all chunks in the virtual rectangle are loaded.
|
||||||
|
local function captureScreenshot(pos, ensureLoaded)
|
||||||
|
local topLeftCapture, bottomRightCapture, topLeftWorld, bottomRightWorld = GenerateCaptureRectangle(pos)
|
||||||
|
|
||||||
UiCaptureDelay = 0
|
UiCaptureDelay = 0
|
||||||
GameSetCameraPos(x, y)
|
if pos then CameraAPI.SetPos(pos) end
|
||||||
|
if ensureLoaded then
|
||||||
repeat
|
repeat
|
||||||
if UiCaptureDelay > 100 then
|
if UiCaptureDelay > 100 then
|
||||||
-- Wiggle the screen a bit, as chunks sometimes don't want to load.
|
-- Wiggle the screen a bit, as chunks sometimes don't want to load.
|
||||||
GameSetCameraPos(x + math.random(-100, 100), y + math.random(-100, 100))
|
if pos then CameraAPI.SetPos(pos + Vec2(math.random(-100, 100), math.random(-100, 100))) end
|
||||||
DrawUI()
|
DrawUI()
|
||||||
wait(0)
|
wait(0)
|
||||||
UiCaptureDelay = UiCaptureDelay + 1
|
UiCaptureDelay = UiCaptureDelay + 1
|
||||||
GameSetCameraPos(x, y)
|
if pos then CameraAPI.SetPos(pos) end
|
||||||
end
|
end
|
||||||
|
|
||||||
DrawUI()
|
DrawUI()
|
||||||
wait(0)
|
wait(0)
|
||||||
UiCaptureDelay = UiCaptureDelay + 1
|
UiCaptureDelay = UiCaptureDelay + 1
|
||||||
|
|
||||||
until DoesWorldExistAt(xMin, yMin, xMax, yMax) -- Chunks will be drawn on the *next* frame.
|
until DoesWorldExistAt(topLeftWorld.x, topLeftWorld.y, bottomRightWorld.x, bottomRightWorld.y)
|
||||||
|
-- Chunks are loaded an will be drawn on the *next* frame.
|
||||||
|
end
|
||||||
|
|
||||||
wait(0) -- Without this line empty chunks may still appear, also it's needed for the UI to disappear.
|
wait(0) -- Without this line empty chunks may still appear, also it's needed for the UI to disappear.
|
||||||
if not TriggerCapture(rx, ry) then
|
|
||||||
|
-- Fetch coordinates again, as they may have changed.
|
||||||
|
local topLeftCapture, bottomRightCapture, topLeftWorld, bottomRightWorld = GenerateCaptureRectangle(pos)
|
||||||
|
|
||||||
|
local outputPixelScale = 4
|
||||||
|
|
||||||
|
-- The top left world position needs to be upscaled by the pixel scale.
|
||||||
|
-- Otherwise it's not possible to stitch the images correctly.
|
||||||
|
if not ScreenCapture.Capture(topLeftCapture, bottomRightCapture, (topLeftWorld * outputPixelScale):Rounded(), (bottomRightWorld - topLeftWorld) * outputPixelScale) then
|
||||||
UiCaptureProblem = "Screen capture failed. Please restart Noita."
|
UiCaptureProblem = "Screen capture failed. Please restart Noita."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reset monitor and PC standby each screenshot.
|
-- Reset monitor and PC standby every screenshot.
|
||||||
ResetStandbyTimer()
|
MonitorStandby.ResetTimer()
|
||||||
end
|
end
|
||||||
|
|
||||||
function startCapturingSpiral()
|
function startCapturingSpiral()
|
||||||
@ -245,9 +272,7 @@ function startCapturingSpiral()
|
|||||||
ox, oy = ox + 256, oy + 256 -- Align screen with ingame chunk grid that is 512x512.
|
ox, oy = ox + 256, oy + 256 -- Align screen with ingame chunk grid that is 512x512.
|
||||||
local x, y = ox, oy
|
local x, y = ox, oy
|
||||||
|
|
||||||
local virtualWidth, virtualHeight =
|
local virtualWidth, virtualHeight = tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")), tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
||||||
|
|
||||||
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
||||||
|
|
||||||
@ -272,7 +297,7 @@ function startCapturingSpiral()
|
|||||||
for i = 1, i, 1 do
|
for i = 1, i, 1 do
|
||||||
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
||||||
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
||||||
captureScreenshot(x, y, rx, ry, entityFile)
|
captureScreenshot(Vec2(x, y), true)
|
||||||
end
|
end
|
||||||
x, y = x + CAPTURE_GRID_SIZE, y
|
x, y = x + CAPTURE_GRID_SIZE, y
|
||||||
end
|
end
|
||||||
@ -280,7 +305,7 @@ function startCapturingSpiral()
|
|||||||
for i = 1, i, 1 do
|
for i = 1, i, 1 do
|
||||||
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
||||||
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
||||||
captureScreenshot(x, y, rx, ry, entityFile)
|
captureScreenshot(Vec2(x, y), true)
|
||||||
end
|
end
|
||||||
x, y = x, y + CAPTURE_GRID_SIZE
|
x, y = x, y + CAPTURE_GRID_SIZE
|
||||||
end
|
end
|
||||||
@ -289,7 +314,7 @@ function startCapturingSpiral()
|
|||||||
for i = 1, i, 1 do
|
for i = 1, i, 1 do
|
||||||
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
||||||
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
||||||
captureScreenshot(x, y, rx, ry, entityFile)
|
captureScreenshot(Vec2(x, y), true)
|
||||||
end
|
end
|
||||||
x, y = x - CAPTURE_GRID_SIZE, y
|
x, y = x - CAPTURE_GRID_SIZE, y
|
||||||
end
|
end
|
||||||
@ -297,7 +322,7 @@ function startCapturingSpiral()
|
|||||||
for i = 1, i, 1 do
|
for i = 1, i, 1 do
|
||||||
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
||||||
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
||||||
captureScreenshot(x, y, rx, ry, entityFile)
|
captureScreenshot(Vec2(x, y), true)
|
||||||
end
|
end
|
||||||
x, y = x, y - CAPTURE_GRID_SIZE
|
x, y = x, y - CAPTURE_GRID_SIZE
|
||||||
end
|
end
|
||||||
@ -311,9 +336,7 @@ function startCapturingHilbert(area)
|
|||||||
|
|
||||||
local ox, oy = GameGetCameraPos()
|
local ox, oy = GameGetCameraPos()
|
||||||
|
|
||||||
local virtualWidth, virtualHeight =
|
local virtualWidth, virtualHeight = tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")), tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
||||||
|
|
||||||
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
||||||
|
|
||||||
@ -367,7 +390,7 @@ function startCapturingHilbert(area)
|
|||||||
x, y = x + 256, y + 256 -- Align screen with ingame chunk grid that is 512x512.
|
x, y = x + 256, y + 256 -- Align screen with ingame chunk grid that is 512x512.
|
||||||
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
local rx, ry = (x - virtualHalfWidth) * CAPTURE_PIXEL_SIZE, (y - virtualHalfHeight) * CAPTURE_PIXEL_SIZE
|
||||||
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
if not Utils.FileExists(string.format("mods/noita-mapcap/output/%d,%d.png", rx, ry)) then
|
||||||
captureScreenshot(x, y, rx, ry, entityFile)
|
captureScreenshot(Vec2(x, y), true)
|
||||||
end
|
end
|
||||||
UiProgress.Progress = UiProgress.Progress + 1
|
UiProgress.Progress = UiProgress.Progress + 1
|
||||||
end
|
end
|
||||||
@ -379,3 +402,46 @@ function startCapturingHilbert(area)
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Starts the capturing screenshots at the given interval.
|
||||||
|
---This will not move the viewport and is meant to capture the player while playing.
|
||||||
|
---@param interval integer|nil -- The interval length in frames. Defaults to 60.
|
||||||
|
---@param minDistance number|nil -- The minimum distance between screenshots. This will prevent screenshots if the player doesn't move much.
|
||||||
|
---@param maxDistance number|nil -- The maximum distance between screenshots. This will allow more screenshots per interval if the player moves fast.
|
||||||
|
function StartCapturingLive(interval, minDistance, maxDistance)
|
||||||
|
interval = interval or 60
|
||||||
|
minDistance = minDistance or 10
|
||||||
|
maxDistance = maxDistance or 50
|
||||||
|
|
||||||
|
local minDistanceSqr, maxDistanceSqr = minDistance ^ 2, maxDistance ^ 2
|
||||||
|
|
||||||
|
--local entityFile = createOrOpenEntityCaptureFile()
|
||||||
|
|
||||||
|
-- Coroutine to capture all entities around the viewport every frame.
|
||||||
|
--[[async_loop(function()
|
||||||
|
local pos = CameraAPI:GetPos() -- Returns the virtual coordinates of the screen center.
|
||||||
|
-- Call the protected function and catch any errors.
|
||||||
|
local ok, err = pcall(captureEntities, entityFile, pos.x, pos.y, 5000)
|
||||||
|
if not ok then
|
||||||
|
print(string.format("Entity capture error: %s", err))
|
||||||
|
end
|
||||||
|
wait(0)
|
||||||
|
end)]]
|
||||||
|
|
||||||
|
local oldPos
|
||||||
|
|
||||||
|
-- Coroutine to calculate next coordinate, and trigger screenshots.
|
||||||
|
async_loop(function()
|
||||||
|
local frames = 0
|
||||||
|
repeat
|
||||||
|
wait(0)
|
||||||
|
frames = frames + 1
|
||||||
|
|
||||||
|
local distanceSqr
|
||||||
|
if oldPos then distanceSqr = CameraAPI.GetPos():DistanceSqr(oldPos) else distanceSqr = math.huge end
|
||||||
|
until (frames >= interval or distanceSqr >= maxDistanceSqr) and distanceSqr >= minDistanceSqr
|
||||||
|
|
||||||
|
captureScreenshot()
|
||||||
|
oldPos = CameraAPI.GetPos()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
-- Copyright (c) 2019-2022 David Vogel
|
|
||||||
--
|
|
||||||
-- This software is released under the MIT License.
|
|
||||||
-- https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
local ffi = ffi or _G.ffi or require("ffi")
|
|
||||||
|
|
||||||
local status, caplib = pcall(ffi.load, "mods/noita-mapcap/bin/capture-b/capture")
|
|
||||||
if not status then
|
|
||||||
print("Error loading capture lib: " .. caplib)
|
|
||||||
end
|
|
||||||
ffi.cdef [[
|
|
||||||
typedef long LONG;
|
|
||||||
typedef struct {
|
|
||||||
LONG left;
|
|
||||||
LONG top;
|
|
||||||
LONG right;
|
|
||||||
LONG bottom;
|
|
||||||
} RECT;
|
|
||||||
|
|
||||||
bool GetRect(RECT* rect);
|
|
||||||
bool Capture(int x, int y);
|
|
||||||
|
|
||||||
int SetThreadExecutionState(int esFlags);
|
|
||||||
]]
|
|
||||||
|
|
||||||
function TriggerCapture(x, y)
|
|
||||||
return caplib.Capture(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get the client rectangle of the "Main" window of this process in screen coordinates
|
|
||||||
function GetRect()
|
|
||||||
local rect = ffi.new("RECT", 0, 0, 0, 0)
|
|
||||||
if not caplib.GetRect(rect) then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return rect
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Reset computer and monitor standby timer
|
|
||||||
function ResetStandbyTimer()
|
|
||||||
ffi.C.SetThreadExecutionState(3) -- ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED
|
|
||||||
end
|
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
-- Viewport coordinates transformation (world <-> window) for Noita.
|
-- Viewport coordinates transformation (world <-> window) for Noita.
|
||||||
|
|
||||||
|
-- For it to work, you have to:
|
||||||
|
-- - Put Coords:ReadResolutions() inside of the OnMagicNumbersAndWorldSeedInitialized() hook.
|
||||||
|
|
||||||
--------------------------
|
--------------------------
|
||||||
-- Load library modules --
|
-- Load library modules --
|
||||||
--------------------------
|
--------------------------
|
||||||
@ -19,9 +22,9 @@ local Vec2 = require("noita-api.vec2")
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
---@class Coords
|
---@class Coords
|
||||||
---@field InternalResolution Vec2
|
---@field InternalResolution Vec2 -- Size of the internal rectangle in window pixels.
|
||||||
---@field WindowResolution Vec2
|
---@field WindowResolution Vec2 -- Size of the window client area in window pixels.
|
||||||
---@field VirtualResolution Vec2
|
---@field VirtualResolution Vec2 -- Size of the virtual rectangle in world/virtual pixels.
|
||||||
local Coords = {
|
local Coords = {
|
||||||
InternalResolution = Vec2(0, 0),
|
InternalResolution = Vec2(0, 0),
|
||||||
WindowResolution = Vec2(0, 0),
|
WindowResolution = Vec2(0, 0),
|
||||||
|
19
files/libraries/monitor-standby.lua
Normal file
19
files/libraries/monitor-standby.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- Copyright (c) 2019-2022 David Vogel
|
||||||
|
--
|
||||||
|
-- This software is released under the MIT License.
|
||||||
|
-- https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
|
||||||
|
local MonitorStandby = {}
|
||||||
|
|
||||||
|
ffi.cdef([[
|
||||||
|
int SetThreadExecutionState(int esFlags);
|
||||||
|
]])
|
||||||
|
|
||||||
|
-- Reset computer and monitor standby timer
|
||||||
|
function MonitorStandby.ResetTimer()
|
||||||
|
ffi.C.SetThreadExecutionState(3) -- ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED
|
||||||
|
end
|
||||||
|
|
||||||
|
return MonitorStandby
|
@ -237,12 +237,14 @@ end
|
|||||||
|
|
||||||
---Returns the squared distance of self to the given vector.
|
---Returns the squared distance of self to the given vector.
|
||||||
---@param v Vec2
|
---@param v Vec2
|
||||||
|
---@return number
|
||||||
function Vec2:DistanceSqr(v)
|
function Vec2:DistanceSqr(v)
|
||||||
return (v - self):LengthSqr()
|
return (v - self):LengthSqr()
|
||||||
end
|
end
|
||||||
|
|
||||||
---Returns the distance of self to the given vector.
|
---Returns the distance of self to the given vector.
|
||||||
---@param v Vec2
|
---@param v Vec2
|
||||||
|
---@return number
|
||||||
function Vec2:Distance(v)
|
function Vec2:Distance(v)
|
||||||
return (v - self):Length()
|
return (v - self):Length()
|
||||||
end
|
end
|
||||||
@ -272,6 +274,49 @@ function Vec2:EqualTo(v, tolerance)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Round returns v rounded by the given method.
|
||||||
|
---@param x number
|
||||||
|
---@param method "nearest"|"floor"|"ceil"|"to-zero"|"away-zero"|nil -- Defaults to "nearest".
|
||||||
|
---@return integer
|
||||||
|
local function round(x, method)
|
||||||
|
method = method or "nearest"
|
||||||
|
|
||||||
|
if method == "nearest" then
|
||||||
|
return math.floor(x + 0.5)
|
||||||
|
elseif method == "floor" then
|
||||||
|
return math.floor(x)
|
||||||
|
elseif method == "ceil" then
|
||||||
|
return math.ceil(x)
|
||||||
|
elseif method == "to-zero" then
|
||||||
|
if x >= 0 then
|
||||||
|
return math.floor(x)
|
||||||
|
else
|
||||||
|
return math.ceil(x)
|
||||||
|
end
|
||||||
|
elseif method == "away-zero" then
|
||||||
|
if x >= 0 then
|
||||||
|
return math.ceil(x)
|
||||||
|
else
|
||||||
|
return math.floor(x)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error(string.format("invalid rounding method %q", method))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Round rounds all vector fields individually by the given rounding method.
|
||||||
|
---@param method "nearest"|"floor"|"ceil"|"to-zero"|"away-zero"|nil -- Defaults to "nearest".
|
||||||
|
function Vec2:Round(method)
|
||||||
|
self[1], self[2] = round(self[1], method), round(self[2], method)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Round rounds all vector fields individually by the given rounding method.
|
||||||
|
---@param method "nearest"|"floor"|"ceil"|"to-zero"|"away-zero"|nil -- Defaults to "nearest".
|
||||||
|
---@return Vec2
|
||||||
|
function Vec2:Rounded(method)
|
||||||
|
return Vec2(round(self[1], method), round(self[2], method))
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
-- JSON Implementation --
|
-- JSON Implementation --
|
||||||
-------------------------
|
-------------------------
|
||||||
|
55
files/libraries/screen-capture.lua
Normal file
55
files/libraries/screen-capture.lua
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
-- Copyright (c) 2019-2022 David Vogel
|
||||||
|
--
|
||||||
|
-- This software is released under the MIT License.
|
||||||
|
-- https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
local Vec2 = require("noita-api.vec2")
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
|
||||||
|
local ScreenCap = {}
|
||||||
|
|
||||||
|
local status, res = pcall(ffi.load, "mods/noita-mapcap/bin/capture-b/capture")
|
||||||
|
if not status then
|
||||||
|
print(string.format("Error loading capture lib: %s", res))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
ffi.cdef([[
|
||||||
|
typedef long LONG;
|
||||||
|
typedef struct {
|
||||||
|
LONG left;
|
||||||
|
LONG top;
|
||||||
|
LONG right;
|
||||||
|
LONG bottom;
|
||||||
|
} RECT;
|
||||||
|
|
||||||
|
bool GetRect(RECT* rect);
|
||||||
|
bool Capture(RECT* rect, int x, int y, int sx, int sy);
|
||||||
|
]])
|
||||||
|
|
||||||
|
---Takes a screenshot of the client area of this process' active window.
|
||||||
|
---@param topLeft Vec2 -- Screenshot rectangle's top left coordinate relative to the window's client area in screen pixels.
|
||||||
|
---@param bottomRight Vec2 -- Screenshot rectangle's bottom right coordinate relative to the window's client area in screen pixels. The pixel is not included in the screenshot area.
|
||||||
|
---@param topLeftWorld Vec2 -- The corresponding scaled world coordinates of the screenshot rectangles' top left corner.
|
||||||
|
---@param finalDimensions Vec2|nil -- The final dimensions that the screenshot will be resized to. If set to zero, no resize will happen.
|
||||||
|
---@return boolean
|
||||||
|
function ScreenCap.Capture(topLeft, bottomRight, topLeftWorld, finalDimensions)
|
||||||
|
finalDimensions = finalDimensions or Vec2(0, 0)
|
||||||
|
|
||||||
|
local rect = ffi.new("RECT", { math.floor(topLeft.x + 0.5), math.floor(topLeft.y + 0.5), math.floor(bottomRight.x + 0.5), math.floor(bottomRight.y + 0.5) })
|
||||||
|
return res.Capture(rect, math.floor(topLeftWorld.x + 0.5), math.floor(topLeftWorld.y + 0.5), math.floor(finalDimensions.x + 0.5), math.floor(finalDimensions.y + 0.5))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Returns the client rectangle of the "Main" window of this process in screen coordinates.
|
||||||
|
---@return any
|
||||||
|
function ScreenCap.GetRect()
|
||||||
|
local rect = ffi.new("RECT")
|
||||||
|
if not res.GetRect(rect) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return rect
|
||||||
|
end
|
||||||
|
|
||||||
|
return ScreenCap
|
4
files/magic-numbers/1024.xml
Normal file
4
files/magic-numbers/1024.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<MagicNumbers
|
||||||
|
VIRTUAL_RESOLUTION_X="1024"
|
||||||
|
VIRTUAL_RESOLUTION_Y="1024"
|
||||||
|
></MagicNumbers>
|
4
files/magic-numbers/512.xml
Normal file
4
files/magic-numbers/512.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<MagicNumbers
|
||||||
|
VIRTUAL_RESOLUTION_X="512"
|
||||||
|
VIRTUAL_RESOLUTION_Y="512"
|
||||||
|
></MagicNumbers>
|
4
files/magic-numbers/64.xml
Normal file
4
files/magic-numbers/64.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<MagicNumbers
|
||||||
|
VIRTUAL_RESOLUTION_X="64"
|
||||||
|
VIRTUAL_RESOLUTION_Y="64"
|
||||||
|
></MagicNumbers>
|
3
files/magic-numbers/fast-cam.xml
Normal file
3
files/magic-numbers/fast-cam.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<MagicNumbers
|
||||||
|
DEBUG_FREE_CAMERA_SPEED="1"
|
||||||
|
></MagicNumbers>
|
@ -1,9 +1,5 @@
|
|||||||
<MagicNumbers VIRTUAL_RESOLUTION_X="1280"
|
<MagicNumbers
|
||||||
VIRTUAL_RESOLUTION_Y="720"
|
|
||||||
VIRTUAL_RESOLUTION_OFFSET_X="-2"
|
|
||||||
VIRTUAL_RESOLUTION_OFFSET_Y="0"
|
|
||||||
DRAW_PARALLAX_BACKGROUND="0"
|
DRAW_PARALLAX_BACKGROUND="0"
|
||||||
DEBUG_FREE_CAMERA_SPEED="10"
|
|
||||||
DEBUG_NO_LOGO_SPLASHES="1"
|
DEBUG_NO_LOGO_SPLASHES="1"
|
||||||
DEBUG_PAUSE_GRID_UPDATE="1"
|
DEBUG_PAUSE_GRID_UPDATE="1"
|
||||||
DEBUG_PAUSE_BOX2D="1"
|
DEBUG_PAUSE_BOX2D="1"
|
||||||
@ -16,5 +12,5 @@
|
|||||||
UI_QUICKBAR_OFFSET_X="2000"
|
UI_QUICKBAR_OFFSET_X="2000"
|
||||||
UI_QUICKBAR_OFFSET_Y="2000"
|
UI_QUICKBAR_OFFSET_Y="2000"
|
||||||
UI_BARS_POS_X="2000"
|
UI_BARS_POS_X="2000"
|
||||||
UI_BARS_POS_Y="2000">
|
UI_BARS_POS_Y="2000"
|
||||||
</MagicNumbers>
|
></MagicNumbers>
|
4
files/magic-numbers/offset.xml
Normal file
4
files/magic-numbers/offset.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<MagicNumbers
|
||||||
|
VIRTUAL_RESOLUTION_OFFSET_X="-2"
|
||||||
|
VIRTUAL_RESOLUTION_OFFSET_Y="0"
|
||||||
|
></MagicNumbers>
|
42
files/ui.lua
42
files/ui.lua
@ -8,6 +8,7 @@
|
|||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
local Utils = require("noita-api.utils")
|
local Utils = require("noita-api.utils")
|
||||||
|
local ScreenCap = require("screen-capture")
|
||||||
|
|
||||||
----------
|
----------
|
||||||
-- Code --
|
-- Code --
|
||||||
@ -33,7 +34,7 @@ function DrawUI()
|
|||||||
if not UiProgress then
|
if not UiProgress then
|
||||||
-- Show informations
|
-- Show informations
|
||||||
local problem
|
local problem
|
||||||
local rect = GetRect()
|
local rect = ScreenCap.GetRect()
|
||||||
|
|
||||||
if not rect then
|
if not rect then
|
||||||
GuiTextCentered(modGUI, 0, 0, '!!! WARNING !!! You are not using "Windowed" mode.')
|
GuiTextCentered(modGUI, 0, 0, '!!! WARNING !!! You are not using "Windowed" mode.')
|
||||||
@ -45,9 +46,7 @@ function DrawUI()
|
|||||||
|
|
||||||
if rect then
|
if rect then
|
||||||
local screenWidth, screenHeight = rect.right - rect.left, rect.bottom - rect.top
|
local screenWidth, screenHeight = rect.right - rect.left, rect.bottom - rect.top
|
||||||
local virtualWidth, virtualHeight =
|
local virtualWidth, virtualHeight = tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")), tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
|
||||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
|
||||||
local ratioX, ratioY = screenWidth / virtualWidth, screenHeight / virtualHeight
|
local ratioX, ratioY = screenWidth / virtualWidth, screenHeight / virtualHeight
|
||||||
--GuiTextCentered(modGUI, 0, 0, string.format("SCREEN_RESOLUTION_*: %d, %d", screenWidth, screenHeight))
|
--GuiTextCentered(modGUI, 0, 0, string.format("SCREEN_RESOLUTION_*: %d, %d", screenWidth, screenHeight))
|
||||||
--GuiTextCentered(modGUI, 0, 0, string.format("VIRTUAL_RESOLUTION_*: %d, %d", virtualWidth, virtualHeight))
|
--GuiTextCentered(modGUI, 0, 0, string.format("VIRTUAL_RESOLUTION_*: %d, %d", virtualWidth, virtualHeight))
|
||||||
@ -108,19 +107,14 @@ function DrawUI()
|
|||||||
GuiTextCentered(modGUI, 0, 0, "You can freely look around and search a place to start capturing.")
|
GuiTextCentered(modGUI, 0, 0, "You can freely look around and search a place to start capturing.")
|
||||||
GuiTextCentered(modGUI, 0, 0, "When started the mod will take pictures automatically.")
|
GuiTextCentered(modGUI, 0, 0, "When started the mod will take pictures automatically.")
|
||||||
GuiTextCentered(modGUI, 0, 0, "Use ESC to pause, and close the game to stop the process.")
|
GuiTextCentered(modGUI, 0, 0, "Use ESC to pause, and close the game to stop the process.")
|
||||||
GuiTextCentered(
|
GuiTextCentered(modGUI, 0, 0, 'You can resume capturing just by restarting noita and pressing "Start capturing map" again,')
|
||||||
modGUI,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'You can resume capturing just by restarting noita and pressing "Start capturing map" again,'
|
|
||||||
)
|
|
||||||
GuiTextCentered(modGUI, 0, 0, "the mod will skip already captured files.")
|
GuiTextCentered(modGUI, 0, 0, "the mod will skip already captured files.")
|
||||||
GuiTextCentered(
|
GuiTextCentered(modGUI, 0, 0, 'If you want to start a new map, you have to delete all images from the "output" folder!')
|
||||||
modGUI,
|
--GuiTextCentered(modGUI, 0, 0, " ")
|
||||||
0,
|
--GuiTextCentered(modGUI, 0, 0, MagicNumbersGetValue("VIRTUAL_RESOLUTION_X"))
|
||||||
0,
|
--GuiTextCentered(modGUI, 0, 0, MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||||
'If you want to start a new map, you have to delete all images from the "output" folder!'
|
--GuiTextCentered(modGUI, 0, 0, MagicNumbersGetValue("VIRTUAL_RESOLUTION_OFFSET_X"))
|
||||||
)
|
--GuiTextCentered(modGUI, 0, 0, MagicNumbersGetValue("VIRTUAL_RESOLUTION_OFFSET_Y"))
|
||||||
GuiTextCentered(modGUI, 0, 0, " ")
|
GuiTextCentered(modGUI, 0, 0, " ")
|
||||||
if GuiButton(modGUI, 0, 0, ">> Start capturing map around view <<", 1) then
|
if GuiButton(modGUI, 0, 0, ">> Start capturing map around view <<", 1) then
|
||||||
UiProgress = {}
|
UiProgress = {}
|
||||||
@ -139,6 +133,10 @@ function DrawUI()
|
|||||||
UiProgress = {}
|
UiProgress = {}
|
||||||
startCapturingHilbert(CAPTURE_AREA_EXTENDED)
|
startCapturingHilbert(CAPTURE_AREA_EXTENDED)
|
||||||
end
|
end
|
||||||
|
if GuiButton(modGUI, 0, 0, ">> Start capturing run live <<", 1) then
|
||||||
|
UiProgress = {}
|
||||||
|
StartCapturingLive()
|
||||||
|
end
|
||||||
GuiTextCentered(modGUI, 0, 0, " ")
|
GuiTextCentered(modGUI, 0, 0, " ")
|
||||||
elseif not UiProgress.Done then
|
elseif not UiProgress.Done then
|
||||||
-- Show progress
|
-- Show progress
|
||||||
@ -146,15 +144,9 @@ function DrawUI()
|
|||||||
GuiTextCentered(modGUI, 0, 0, string.format("Coordinates: %d, %d", x, y))
|
GuiTextCentered(modGUI, 0, 0, string.format("Coordinates: %d, %d", x, y))
|
||||||
GuiTextCentered(modGUI, 0, 0, string.format("Waiting %d frames...", UiCaptureDelay))
|
GuiTextCentered(modGUI, 0, 0, string.format("Waiting %d frames...", UiCaptureDelay))
|
||||||
if UiProgress.Progress then
|
if UiProgress.Progress then
|
||||||
GuiTextCentered(
|
GuiTextCentered(modGUI, 0, 0, progressBarString(
|
||||||
modGUI,
|
UiProgress, { BarLength = 100, CharFull = "l", CharEmpty = ".", Format = "|%s| [%d / %d] [%1.2f%%]" }
|
||||||
0,
|
))
|
||||||
0,
|
|
||||||
progressBarString(
|
|
||||||
UiProgress,
|
|
||||||
{BarLength = 100, CharFull = "l", CharEmpty = ".", Format = "|%s| [%d / %d] [%1.2f%%]"}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
if UiCaptureProblem then
|
if UiCaptureProblem then
|
||||||
GuiTextCentered(modGUI, 0, 0, string.format("A problem occurred while capturing: %s", UiCaptureProblem))
|
GuiTextCentered(modGUI, 0, 0, string.format("A problem occurred while capturing: %s", UiCaptureProblem))
|
||||||
|
25
init.lua
25
init.lua
@ -21,12 +21,14 @@ end
|
|||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
local Coords = require("coordinates")
|
local Coords = require("coordinates")
|
||||||
|
local CameraAPI = require("noita-api.camera")
|
||||||
|
local DebugAPI = require("noita-api.debug")
|
||||||
|
local Vec2 = require("noita-api.vec2")
|
||||||
|
|
||||||
-------------------------------
|
-------------------------------
|
||||||
-- Load and run script files --
|
-- Load and run script files --
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
dofile("mods/noita-mapcap/files/external.lua")
|
|
||||||
dofile("mods/noita-mapcap/files/capture.lua")
|
dofile("mods/noita-mapcap/files/capture.lua")
|
||||||
dofile("mods/noita-mapcap/files/ui.lua")
|
dofile("mods/noita-mapcap/files/ui.lua")
|
||||||
--dofile("mods/noita-mapcap/files/blablabla.lua")
|
--dofile("mods/noita-mapcap/files/blablabla.lua")
|
||||||
@ -52,10 +54,24 @@ end
|
|||||||
---@param playerEntityID integer
|
---@param playerEntityID integer
|
||||||
function OnPlayerSpawned(playerEntityID)
|
function OnPlayerSpawned(playerEntityID)
|
||||||
modGUI = GuiCreate()
|
modGUI = GuiCreate()
|
||||||
GameSetCameraFree(true)
|
|
||||||
|
|
||||||
-- Start entity capturing right when the player spawn.
|
-- Start entity capturing right when the player spawn.
|
||||||
--DebugEntityCapture()
|
--DebugEntityCapture()
|
||||||
|
|
||||||
|
--[[async(function()
|
||||||
|
wait(0)
|
||||||
|
CameraAPI.SetCameraFree(true)
|
||||||
|
|
||||||
|
local origin = Vec2(512, -512)
|
||||||
|
CameraAPI.SetPos(origin)
|
||||||
|
|
||||||
|
DebugAPI.Mark(origin, "origin")
|
||||||
|
|
||||||
|
local tl, br = Coords:ValidRenderingRect()
|
||||||
|
local tlWorld, brWorld = Coords:ToWorld(tl), Coords:ToWorld(br)
|
||||||
|
DebugAPI.Mark(tlWorld, "tl")
|
||||||
|
DebugAPI.Mark(brWorld, "br")
|
||||||
|
end)]]
|
||||||
end
|
end
|
||||||
|
|
||||||
---Called when the player dies.
|
---Called when the player dies.
|
||||||
@ -110,7 +126,10 @@ end
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
-- Override virtual resolution and some other stuff.
|
-- Override virtual resolution and some other stuff.
|
||||||
ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic_numbers.xml")
|
--ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic-numbers/1024.xml")
|
||||||
|
ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic-numbers/fast-cam.xml")
|
||||||
|
--ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic-numbers/no-ui.xml")
|
||||||
|
ModMagicNumbersFileAdd("mods/noita-mapcap/files/magic-numbers/offset.xml")
|
||||||
|
|
||||||
-- Remove hover animation of newly created perks.
|
-- Remove hover animation of newly created perks.
|
||||||
ModLuaFileAppend("data/scripts/perks/perk.lua", "mods/noita-mapcap/files/overrides/perks/perk.lua")
|
ModLuaFileAppend("data/scripts/perks/perk.lua", "mods/noita-mapcap/files/overrides/perks/perk.lua")
|
||||||
|
Loading…
Reference in New Issue
Block a user