mirror of
https://github.com/Dadido3/noita-mapcap.git
synced 2024-12-22 02:17:33 +00:00
Use DoesWorldExistAt() to speed up capturing
- Remove any delays - Move UI rendering into capture coroutine, so wait(...) can be reduced - Use wait(0) instead of wait(1) in coroutines - Use default value of STREAMING_CHUNK_TARGET - Don't suggest to change framerate to 600 Hz - Don't suggest to disable mTrailerMode - Add "Done!" screen - Update README.md fixes #1 fixes #5
This commit is contained in:
parent
8cf480dc37
commit
151d1d88bd
29
README.md
29
README.md
@ -4,16 +4,17 @@ Addon that captures the map and saves it as image.
|
||||
|
||||
![missing image](images/example1.png)
|
||||
|
||||
A resulting image with 3.8 gigapixels can be [seen here](https://easyzoom.com/image/159431) (Warning: Spoilers).
|
||||
A resulting image with 3.8 gigapixels can be [seen here](https://easyzoom.com/image/203402) (Warning: Spoilers).
|
||||
|
||||
## System requirements
|
||||
|
||||
- Windows Vista, ..., 10 (64 bit version)
|
||||
- A few GB of free drive space
|
||||
- 16-32 GB of RAM (But works with less as long as the software doesn't run out of virtual memory)
|
||||
- A processor
|
||||
- Optionally a monitor, keyboard and mouse to interact with the mod/software
|
||||
- A sound card to listen to music while it's grabbing screenshots
|
||||
- Windows Vista, ..., 10. (64 bit version)
|
||||
- A few GB of free drive space.
|
||||
- 4 or more GB of RAM for gigapixel images. (But it works with less as long as the software doesn't run out of virtual memory)
|
||||
- A processor.
|
||||
- Optionally a monitor, keyboard and mouse to interact with the mod/software.
|
||||
- A sound card to listen to music while it's grabbing screenshots.
|
||||
Capturing and stitching will take about 180 minutes (160 + 20).
|
||||
|
||||
## Usage
|
||||
|
||||
@ -30,6 +31,7 @@ A resulting image with 3.8 gigapixels can be [seen here](https://easyzoom.com/im
|
||||
- Don't cover the game window.
|
||||
- Don't move the game window outside of screen space.
|
||||
- If you need to pause, use the ESC menu.
|
||||
- Also, make sure that the console window isn't selected, as you will end up with screenshots of the console instead of the game. You can select and use any other window while it's capturing screenshots, though.
|
||||
8. When you think you are done, close noita.
|
||||
9. Start `.../Noita/mods/noita-mapcap/bin/stitch/stitch.exe`.
|
||||
- Use the default values to create a complete stitch.
|
||||
@ -50,15 +52,11 @@ Here is a step by step explanation how to do so:
|
||||
<MagicNumbers
|
||||
VIRTUAL_RESOLUTION_X="840"
|
||||
VIRTUAL_RESOLUTION_Y="840"
|
||||
STREAMING_CHUNK_TARGET="22"
|
||||
...
|
||||
>
|
||||
```
|
||||
|
||||
`STREAMING_CHUNK_TARGET` seems to have some influence on missing chunks while grabbing screenshots.
|
||||
If you have problems with not generated (only background) areas, modify this value.
|
||||
|
||||
3. Change the following values inside of `.../Noita/save_shared/config.xml` (Not the one in AppData!) to
|
||||
3. Change the following values inside of `.../Noita/save_shared/config.xml` (Not the one in AppData!) to
|
||||
|
||||
``` xml
|
||||
<Config
|
||||
@ -70,7 +68,6 @@ Here is a step by step explanation how to do so:
|
||||
window_h="840"
|
||||
window_w="840"
|
||||
fullscreen="0"
|
||||
framerate="600"
|
||||
...
|
||||
>
|
||||
```
|
||||
@ -84,8 +81,6 @@ Here is a step by step explanation how to do so:
|
||||
|
||||
6. When the game is loaded (When you can control your character):
|
||||
- Press `F5`, `F8` and `F12` (In that order).
|
||||
- Press `F7`, and disable `mTrailerMode` in the menu. (This should reduce chunk loading problems)
|
||||
- Press `F7` again to close the menu.
|
||||
|
||||
7. Press the `>> Start capturing full map <<` button.
|
||||
|
||||
@ -95,10 +90,6 @@ Here is a step by step explanation how to do so:
|
||||
|
||||
## Advanced stuff
|
||||
|
||||
You can increase the "countdown" time in `.../Noita/mods/noita-mapcap/files/capture.lua`.
|
||||
`CAPTURE_DELAY` is the time in frames the script has to wait until it can take a screenshot.
|
||||
Also, when a chunk is captured, which is not a neighbor of the previous chunk, `CAPTURE_BIGJUMP_DELAY` gets added to the countdown.
|
||||
|
||||
If you use `noita_dev.exe`, you can enable the debug mode by pressing `F5`. Once in debug mode, you can use `F8` to toggle shaders (Includes fog of war), and you can use `F12` to disable the UI. There are some more options in the `F7` and `Shift + F7` menu.
|
||||
|
||||
You can capture in a different resolution if you want or need to. If you do so, you have to adjust some values inside of the mod.
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
CAPTURE_PIXEL_SIZE = 1 -- Screen to virtual pixel ratio
|
||||
CAPTURE_GRID_SIZE = 420 -- in ingame pixels. There will always be 3 to 6 images overlapping
|
||||
CAPTURE_DELAY = 8 -- in frames
|
||||
CAPTURE_BIGJUMP_DELAY = 20 -- in frames. Additional delay after doing a "larger than grid jump"
|
||||
CAPTURE_FORCE_HP = 4 -- * 25HP
|
||||
|
||||
CAPTURE_LEFT = -25000 -- in ingame pixels. Left edge of the full map capture rectangle
|
||||
@ -26,31 +24,37 @@ local function preparePlayer()
|
||||
setPlayerHP(CAPTURE_FORCE_HP)
|
||||
end
|
||||
|
||||
local xOld, yOld = 0, 0
|
||||
local function captureScreenshot(x, y, rx, ry)
|
||||
-- "Larger than grid jump" delay
|
||||
local delay = CAPTURE_DELAY - 1
|
||||
if math.abs(x - xOld) > CAPTURE_GRID_SIZE or math.abs(y - yOld) > CAPTURE_GRID_SIZE then
|
||||
delay = delay + CAPTURE_BIGJUMP_DELAY
|
||||
end
|
||||
xOld, yOld = x, y
|
||||
local virtualWidth, virtualHeight =
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||
|
||||
-- Set pos several times, so that chunks will load even if nothing happens in the surrounding
|
||||
-- This prevents black blocks in areas without entites
|
||||
UiHideCountdown = delay
|
||||
for i = 1, delay, 1 do
|
||||
GameSetCameraPos(x, y)
|
||||
wait(1)
|
||||
UiHideCountdown = UiHideCountdown - 1
|
||||
end
|
||||
local virtualHalfWidth, virtualHalfHeight = math.floor(virtualWidth / 2), math.floor(virtualHeight / 2)
|
||||
local xMin, yMin = x - virtualHalfWidth, y - virtualHalfHeight
|
||||
local xMax, yMax = xMin + virtualWidth, yMin + virtualHeight
|
||||
|
||||
UiCaptureDelay = 0
|
||||
GameSetCameraPos(x, y)
|
||||
repeat
|
||||
if UiCaptureDelay > 100 then
|
||||
-- Wiggle the screen a bit, as chunks sometimes don't want to load
|
||||
GameSetCameraPos(x+math.random(-100, 100), y+math.random(-100, 100))
|
||||
DrawUI()
|
||||
wait(0)
|
||||
UiCaptureDelay = UiCaptureDelay + 1
|
||||
GameSetCameraPos(x, y)
|
||||
end
|
||||
|
||||
DrawUI()
|
||||
wait(0)
|
||||
UiCaptureDelay = UiCaptureDelay + 1
|
||||
|
||||
UiHide = true -- Hide UI while capturing the screenshot
|
||||
wait(1)
|
||||
until DoesWorldExistAt(xMin, yMin, xMax, yMax) -- Chunks will be drawn on the *next* frame
|
||||
|
||||
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
|
||||
UiCaptureProblem = "Screen capture failed. Please restart Noita."
|
||||
end
|
||||
UiHide = false
|
||||
|
||||
-- Reset monitor and PC standby each screenshot
|
||||
ResetStandbyTimer()
|
||||
@ -161,6 +165,8 @@ function startCapturingHilbert()
|
||||
|
||||
t = t + 1
|
||||
end
|
||||
|
||||
UiProgress.Done = true
|
||||
end
|
||||
)
|
||||
end
|
||||
|
@ -1,6 +1,5 @@
|
||||
<MagicNumbers VIRTUAL_RESOLUTION_X="1280"
|
||||
VIRTUAL_RESOLUTION_Y="720"
|
||||
STREAMING_CHUNK_TARGET="22"
|
||||
DRAW_PARALLAX_BACKGROUND="0"
|
||||
DEBUG_FREE_CAMERA_SPEED="10"
|
||||
DEBUG_NO_LOGO_SPLASHES="1"
|
||||
|
243
files/ui.lua
243
files/ui.lua
@ -3,140 +3,147 @@
|
||||
-- This software is released under the MIT License.
|
||||
-- https://opensource.org/licenses/MIT
|
||||
|
||||
UiHide = false
|
||||
UiHideCountdown = 0
|
||||
local UiReduce = false
|
||||
UiCaptureDelay = 0 -- Waiting time in frames
|
||||
UiProgress = nil
|
||||
UiCaptureProblem = nil
|
||||
|
||||
async_loop(
|
||||
function()
|
||||
if modGUI ~= nil then
|
||||
GuiStartFrame(modGUI)
|
||||
function DrawUI()
|
||||
if modGUI ~= nil then
|
||||
GuiStartFrame(modGUI)
|
||||
|
||||
GuiLayoutBeginVertical(modGUI, 50, 50)
|
||||
if not UiReduce then
|
||||
local problem
|
||||
local rect = GetRect()
|
||||
GuiLayoutBeginVertical(modGUI, 50, 50)
|
||||
if not UiProgress then
|
||||
-- Show informations
|
||||
local problem
|
||||
local rect = GetRect()
|
||||
|
||||
if not rect then
|
||||
GuiTextCentered(modGUI, 0, 0, '!!! WARNING !!! You are not using "Windowed" mode.')
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, '- Change the window mode in the game options to "Windowed"')
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
|
||||
if rect then
|
||||
local screenWidth, screenHeight = rect.right - rect.left, rect.bottom - rect.top
|
||||
local virtualWidth, virtualHeight =
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||
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("VIRTUAL_RESOLUTION_*: %d, %d", virtualWidth, virtualHeight))
|
||||
if math.abs(ratioX - CAPTURE_PIXEL_SIZE) > 0.0001 or math.abs(ratioY - CAPTURE_PIXEL_SIZE) > 0.0001 then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Screen and virtual resolution differ.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(
|
||||
modGUI,
|
||||
0,
|
||||
0,
|
||||
string.format(
|
||||
"- Change the resolution in the game options to %dx%d",
|
||||
virtualWidth * CAPTURE_PIXEL_SIZE,
|
||||
virtualHeight * CAPTURE_PIXEL_SIZE
|
||||
)
|
||||
)
|
||||
GuiTextCentered(
|
||||
modGUI,
|
||||
0,
|
||||
0,
|
||||
string.format(
|
||||
"- Change the virtual resolution in the mod to %dx%d",
|
||||
screenWidth / CAPTURE_PIXEL_SIZE,
|
||||
screenHeight / CAPTURE_PIXEL_SIZE
|
||||
)
|
||||
)
|
||||
if math.abs(ratioX - ratioY) < 0.0001 then
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("- Change the CAPTURE_PIXEL_SIZE in the mod to %f", ratioX))
|
||||
end
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
end
|
||||
|
||||
if not fileExists("mods/noita-mapcap/bin/capture-b/capture.dll") then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find library for screenshots.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, "- Redownload a release of this mod from GitHub, don't download the sourcecode")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
|
||||
if not fileExists("mods/noita-mapcap/bin/stitch/stitch.exe") then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find software for stitching.")
|
||||
GuiTextCentered(modGUI, 0, 0, "You can still take screenshots, but you won't be able to stitch those screenshots.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, "- Redownload a release of this mod from GitHub, don't download the sourcecode")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
|
||||
if not problem then
|
||||
GuiTextCentered(modGUI, 0, 0, "No problems found.")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
end
|
||||
|
||||
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, "Use ESC to pause, and close the game to stop the process.")
|
||||
GuiTextCentered(
|
||||
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,
|
||||
'If you want to start a new map, you have to delete all images from the "output" folder!'
|
||||
)
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
if GuiButton(modGUI, 0, 0, ">> Start capturing map around view <<", 1) then
|
||||
startCapturingSpiral()
|
||||
UiReduce = true
|
||||
end
|
||||
if GuiButton(modGUI, 0, 0, ">> Start capturing full map <<", 1) then
|
||||
startCapturingHilbert()
|
||||
UiReduce = true
|
||||
end
|
||||
if not rect then
|
||||
GuiTextCentered(modGUI, 0, 0, '!!! WARNING !!! You are not using "Windowed" mode.')
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, '- Change the window mode in the game options to "Windowed"')
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
if not UiHide then
|
||||
local x, y = GameGetCameraPos()
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("Coordinates: %d, %d", x, y))
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("Countdown: %d", UiHideCountdown))
|
||||
if UiProgress then
|
||||
|
||||
if rect then
|
||||
local screenWidth, screenHeight = rect.right - rect.left, rect.bottom - rect.top
|
||||
local virtualWidth, virtualHeight =
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")),
|
||||
tonumber(MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y"))
|
||||
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("VIRTUAL_RESOLUTION_*: %d, %d", virtualWidth, virtualHeight))
|
||||
if math.abs(ratioX - CAPTURE_PIXEL_SIZE) > 0.0001 or math.abs(ratioY - CAPTURE_PIXEL_SIZE) > 0.0001 then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Screen and virtual resolution differ.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(
|
||||
modGUI,
|
||||
0,
|
||||
0,
|
||||
progressBarString(
|
||||
UiProgress,
|
||||
{BarLength = 100, CharFull = "l", CharEmpty = ".", Format = "|%s| [%d / %d] [%1.2f%%]"}
|
||||
string.format(
|
||||
"- Change the resolution in the game options to %dx%d",
|
||||
virtualWidth * CAPTURE_PIXEL_SIZE,
|
||||
virtualHeight * CAPTURE_PIXEL_SIZE
|
||||
)
|
||||
)
|
||||
end
|
||||
if UiCaptureProblem then
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("A problem occurred while capturing: %s", UiCaptureProblem))
|
||||
GuiTextCentered(
|
||||
modGUI,
|
||||
0,
|
||||
0,
|
||||
string.format(
|
||||
"- Change the virtual resolution in the mod to %dx%d",
|
||||
screenWidth / CAPTURE_PIXEL_SIZE,
|
||||
screenHeight / CAPTURE_PIXEL_SIZE
|
||||
)
|
||||
)
|
||||
if math.abs(ratioX - ratioY) < 0.0001 then
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("- Change the CAPTURE_PIXEL_SIZE in the mod to %f", ratioX))
|
||||
end
|
||||
GuiTextCentered(modGUI, 0, 0, '- Make sure that the console is not selected')
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
end
|
||||
GuiLayoutEnd(modGUI)
|
||||
end
|
||||
|
||||
if not fileExists("mods/noita-mapcap/bin/capture-b/capture.dll") then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find library for screenshots.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, "- Redownload a release of this mod from GitHub, don't download the sourcecode")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
|
||||
if not fileExists("mods/noita-mapcap/bin/stitch/stitch.exe") then
|
||||
GuiTextCentered(modGUI, 0, 0, "!!! WARNING !!! Can't find software for stitching.")
|
||||
GuiTextCentered(modGUI, 0, 0, "You can still take screenshots, but you won't be able to stitch those screenshots.")
|
||||
GuiTextCentered(modGUI, 0, 0, "To fix the problem, do one of these:")
|
||||
GuiTextCentered(modGUI, 0, 0, "- Redownload a release of this mod from GitHub, don't download the sourcecode")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
problem = true
|
||||
end
|
||||
|
||||
if not problem then
|
||||
GuiTextCentered(modGUI, 0, 0, "No problems found.")
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
end
|
||||
|
||||
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, "Use ESC to pause, and close the game to stop the process.")
|
||||
GuiTextCentered(
|
||||
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,
|
||||
'If you want to start a new map, you have to delete all images from the "output" folder!'
|
||||
)
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
if GuiButton(modGUI, 0, 0, ">> Start capturing map around view <<", 1) then
|
||||
UiProgress = {}
|
||||
startCapturingSpiral()
|
||||
end
|
||||
if GuiButton(modGUI, 0, 0, ">> Start capturing full map <<", 1) then
|
||||
UiProgress = {}
|
||||
startCapturingHilbert()
|
||||
end
|
||||
GuiTextCentered(modGUI, 0, 0, " ")
|
||||
elseif not UiProgress.Done then
|
||||
-- Show progress
|
||||
local x, y = GameGetCameraPos()
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("Coordinates: %d, %d", x, y))
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("Waiting %d frames...", UiCaptureDelay))
|
||||
if UiProgress.Progress then
|
||||
GuiTextCentered(
|
||||
modGUI,
|
||||
0,
|
||||
0,
|
||||
progressBarString(
|
||||
UiProgress,
|
||||
{BarLength = 100, CharFull = "l", CharEmpty = ".", Format = "|%s| [%d / %d] [%1.2f%%]"}
|
||||
)
|
||||
)
|
||||
end
|
||||
if UiCaptureProblem then
|
||||
GuiTextCentered(modGUI, 0, 0, string.format("A problem occurred while capturing: %s", UiCaptureProblem))
|
||||
end
|
||||
else
|
||||
GuiTextCentered(modGUI, 0, 0, "Done!")
|
||||
end
|
||||
GuiLayoutEnd(modGUI)
|
||||
end
|
||||
end
|
||||
|
||||
async_loop(
|
||||
function()
|
||||
-- When capturing is active, DrawUI is called from a different coroutine
|
||||
-- This ensures that the text is drawn *after* a screenshot has been grabbed
|
||||
if not UiProgress or UiProgress.Done then DrawUI() end
|
||||
wait(0)
|
||||
end
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user