diff --git a/changelog.txt b/changelog.txt index 19ee2b2..c9bb03f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ --------------------------------------------------------------------------------------------------- Version: 1.5.0 + Features: + - Add toggle/shortcut to take a screenshot (on paused active camera) + Changes: - Use 10 digits for screenshot numbers. - Use 'transition' when mentioning camera movement (instead of zoom) diff --git a/control.lua b/control.lua index 316694c..f0d224b 100644 --- a/control.lua +++ b/control.lua @@ -11,6 +11,7 @@ local function on_init() for index, player in pairs(game.players) do -- initialize player(s) when mod is loaded into existing game TLBE.Config.reload({ player_index = index }) + TLBE.GUI.initialize(player, global.playerSettings[index]) player.print({ "mod-loaded" }, { r = 1, g = 0.5, b = 0 }) player.print({ "mod-loaded2" }) @@ -29,11 +30,15 @@ local function on_init() end -- A player got created (or joined the game) +--- @param event EventData.on_player_created local function on_player_created(event) -- Initialize playerSettings TLBE.Config.reload(event) - game.players[event.player_index].print({ "mod-loaded2" }, { r = 1, g = 0.5, b = 0 }) + local player = game.players[event.player_index] + player.print({ "mod-loaded2" }, { r = 1, g = 0.5, b = 0 }) + + TLBE.GUI.initialize(player, global.playerSettings[event.player_index]) end local function on_tick() @@ -62,6 +67,7 @@ script.on_event(defines.events.on_rocket_launched, TLBE.Main.rocket_launched) script.on_event("tlbe-main-window-toggle", TLBE.GUI.toggleMainWindow) script.on_event("tlbe-pause-cameras", TLBE.GUI.togglePauseCameras) +script.on_event("tlbe-take-screenshot", TLBE.GUI.takeScreenshot) script.on_event(defines.events.on_lua_shortcut, TLBE.GUI.onShortcut) script.on_event(defines.events.on_tick, on_tick) diff --git a/graphics/take-screenshot.png b/graphics/take-screenshot.png new file mode 100644 index 0000000..c6a7e57 Binary files /dev/null and b/graphics/take-screenshot.png differ diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index ba3201a..88690ae 100644 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -66,6 +66,7 @@ tracker-wrong-surface=Tracker is disabled because tracker surface differs from c [controls] tlbe-main-window-toggle=Open/Close camera settings tlbe-pause-cameras=Pause/Unpause all TLBE cameras +tlbe-take-screenshot=Take a screenshot [mod-setting-name] tlbe-save-folder=Save location @@ -78,3 +79,4 @@ tlbe-sequential-names=Use sequential numbering per camera for the screenshot num [shortcut] tlbe=Time Lapse Base Edition tlbe-pause=Pause all TLBE cameras +tlbe-screenshot=Take a screenshot using the selected camera diff --git a/migrations/tlbe.1.4.5.lua b/migrations/tlbe.1.4.5.lua index 31f9a8d..3475b94 100644 --- a/migrations/tlbe.1.4.5.lua +++ b/migrations/tlbe.1.4.5.lua @@ -3,6 +3,7 @@ if global.playerSettings == nil then end local Camera = require("scripts.camera") +local GUI = require("scripts.gui") -- Convert to new Camera transitionData for player_index, player in pairs(game.players) do @@ -12,6 +13,16 @@ for player_index, player in pairs(game.players) do goto NextPlayer end + -- Just make sure it is here + if playerSettings.guiPersist == nil then + playerSettings.guiPersist = { + selectedCamera = 1, + selectedTracker = 1, + selectedCameraTracker = 1 + } + end + GUI.updateTakeScreenshotButton(player, playerSettings) + local warned = false for _, camera in pairs(playerSettings.cameras) do local activeTracker = camera.lastKnownActiveTracker diff --git a/prototypes/shortcuts.lua b/prototypes/shortcuts.lua index 6aeed30..676a19a 100644 --- a/prototypes/shortcuts.lua +++ b/prototypes/shortcuts.lua @@ -1,4 +1,3 @@ --- luacheck: globals data data:extend( { { @@ -13,6 +12,12 @@ data:extend( key_sequence = "CONTROL + SHIFT + P", consuming = "none" }, + { + type = "custom-input", + name = "tlbe-take-screenshot", + key_sequence = "CONTROL + SHIFT + S", + consuming = "none" + }, { type = "shortcut", name = "tlbe-shortcut", @@ -61,7 +66,7 @@ data:extend( localised_name = { "shortcut.tlbe-pause" }, associated_control_input = "tlbe-pause-cameras", icon = { - -- tlbe-logo + -- tlbe-pause-camera filename = "__TLBE__/graphics/pause-camera.png", priority = "extra-high-no-scale", width = 64, @@ -71,7 +76,7 @@ data:extend( flags = { "icon" } }, small_icon = { - -- tlbe-logo + -- tlbe-pause-camera filename = "__TLBE__/graphics/pause-camera.png", priority = "extra-high-no-scale", width = 64, @@ -81,7 +86,7 @@ data:extend( flags = { "icon" } }, disabled_small_icon = { - -- tlbe-logo-white + -- tlbe-pause-camera-white filename = "__TLBE__/graphics/pause-camera.png", priority = "extra-high-no-scale", width = 64, @@ -90,6 +95,45 @@ data:extend( scale = 1, flags = { "icon" } } + }, + { + type = "shortcut", + name = "tlbe-screenshot-shortcut", + toggleable = false, + order = "a[mod]-tlbe", + action = "lua", + localised_name = { "shortcut.tlbe-screenshot" }, + associated_control_input = "tlbe-take-screenshot", + icon = { + -- tlbe-take-screenshot + filename = "__TLBE__/graphics/take-screenshot.png", + priority = "extra-high-no-scale", + width = 64, + height = 64, + position = { 0, 0 }, + scale = 1, + flags = { "icon" } + }, + small_icon = { + -- tlbe-take-screenshot + filename = "__TLBE__/graphics/take-screenshot.png", + priority = "extra-high-no-scale", + width = 64, + height = 64, + position = { 0, 0 }, + scale = 1, + flags = { "icon" } + }, + disabled_small_icon = { + -- tlbe-take-screenshot-white + filename = "__TLBE__/graphics/take-screenshot.png", + priority = "extra-high-no-scale", + width = 64, + height = 50, + position = { 65, 0 }, + scale = 1, + flags = { "icon" } + } } } ) diff --git a/prototypes/sprites.lua b/prototypes/sprites.lua index 846b38e..bac7b24 100644 --- a/prototypes/sprites.lua +++ b/prototypes/sprites.lua @@ -1,4 +1,3 @@ --- luacheck: globals data data:extend( { { @@ -34,6 +33,17 @@ data:extend( scale = 0.5, flags = { "gui-icon" } }, + { + type = "sprite", + name = "tlbe-take-screenshot", + filename = "__TLBE__/graphics/take-screenshot.png", + priority = "extra-high-no-scale", + width = 64, + height = 64, + position = { 0, 0 }, + scale = 0.5, + flags = { "gui-icon" } + }, { type = "sprite", name = "play-white", diff --git a/scripts/config.lua b/scripts/config.lua index fcc5f28..f12dfca 100644 --- a/scripts/config.lua +++ b/scripts/config.lua @@ -10,6 +10,12 @@ local Tracker = require("scripts.tracker") --- @field saveFolder string --- @field sequentialNames boolean --- @field noticeMaxZoom boolean When true the warning about the max zoom is already raised +--- @field guiPersist persistedGUISettings + +--- @class persistedGUISettings +--- @field selectedCamera integer Selected camera +--- @field selectedTracker integer Selected tracker +--- @field selectedCameraTracker integer Selected tracker of the selected camera --- (re)loads the mod settings and initializes player settings if needed function Config.reload(event) @@ -49,7 +55,13 @@ function Config.newPlayerSettings(player) return { -- Setup a default camera and attach trackers to it cameras = { camera }, - trackers = trackers + trackers = trackers, + guiPersist = { + selectedCamera = 1, + selectedTracker = 1, + selectedCameraTracker = 1 + } + } end diff --git a/scripts/gui.lua b/scripts/gui.lua index c7e8372..875b9af 100644 --- a/scripts/gui.lua +++ b/scripts/gui.lua @@ -32,6 +32,13 @@ local function findActiveTracker(trackers, surfaceName) end end +-- Initialize the GUI for a new player +---@param player LuaPlayer +---@param playerSettings playerSettings +function GUI.initialize(player, playerSettings) + GUI.updateTakeScreenshotButton(player, playerSettings) +end + function GUI.tick() if game.tick % ticks_per_half_second ~= 0 then return @@ -101,9 +108,10 @@ function GUI.onClick(event) selectedCamera.enabled = not selectedCamera.enabled GUI.updateCameraActions(playerSettings.gui, playerSettings.guiPersist, playerSettings.cameras) + GUI.updateTakeScreenshotButton(player, playerSettings) elseif event.element.name == "tlbe_camera_add" then table.insert(playerSettings.cameras, Camera.newCamera(player, playerSettings.cameras)) - playerSettings.guiPersist.selectedCamera = #playerSettings.cameras + GUI.setSelectedCamera(player, playerSettings, #playerSettings.cameras) GUI.updateCameraList(playerSettings.gui, playerSettings.guiPersist, playerSettings.cameras) GUI.updateCameraActions(playerSettings.gui, playerSettings.guiPersist, playerSettings.cameras) @@ -125,7 +133,7 @@ function GUI.onClick(event) table.remove(playerSettings.cameras, playerSettings.guiPersist.selectedCamera) if playerSettings.guiPersist.selectedCamera > #playerSettings.cameras then - playerSettings.guiPersist.selectedCamera = #playerSettings.cameras + GUI.setSelectedCamera(player, playerSettings, #playerSettings.cameras) end GUI.updateCameraList(playerSettings.gui, playerSettings.guiPersist, playerSettings.cameras) @@ -390,11 +398,13 @@ function GUI.onClick(event) end end +--- @param event EventData.on_gui_selection_state_changed function GUI.onSelected(event) + local player = game.players[event.player_index] local playerSettings = global.playerSettings[event.player_index] if event.element.name == "tlbe-cameras-list" then - playerSettings.guiPersist.selectedCamera = event.element.selected_index + GUI.setSelectedCamera(player, playerSettings, event.element.selected_index) playerSettings.guiPersist.selectedCameraTracker = 1 GUI.updateCameraActions(playerSettings.gui, playerSettings.guiPersist, playerSettings.cameras) @@ -531,7 +541,7 @@ function GUI.onTextChanged(event) Camera.setFrameRate(playerSettings.cameras[playerSettings.guiPersist.selectedCamera], event.element.text) elseif event.element.name == "camera-speed-gain" then Camera.setSpeedGain(playerSettings.cameras[playerSettings.guiPersist.selectedCamera], event.element.text) - elseif event.element.name == "camera-transtion-period" then + elseif event.element.name == "camera-transition-period" then Camera.setTransitionPeriod(playerSettings.cameras[playerSettings.guiPersist.selectedCamera], event.element.text) elseif event.element.name == "tlbe-tracker-top" then local value = tonumber(event.element.text) @@ -591,16 +601,33 @@ function GUI.onStateChanged(event) end end +--- @param event EventData.on_lua_shortcut function GUI.onShortcut(event) if event.prototype_name == "tlbe-shortcut" then GUI.toggleMainWindow(event) elseif event.prototype_name == "tlbe-pause-shortcut" then GUI.togglePauseCameras(event) + elseif event.prototype_name == "tlbe-screenshot-shortcut" then + GUI.takeScreenshot(event) + end +end + +function GUI.takeScreenshot(event) + local player = game.players[event.player_index] + local active = player.is_shortcut_available("tlbe-screenshot-shortcut") + player.print("active " .. tostring(active)) + if active then + ---@type playerSettings + local playerSettings = global.playerSettings[event.player_index] + local camera = playerSettings.cameras[playerSettings.guiPersist.selectedCamera] + local _, activeTracker = Tracker.findActiveTracker(camera.trackers, camera.surfaceName) + + Main.takeScreenshot(player, playerSettings, camera, activeTracker) end end function GUI.onSurfacesUpdated() - -- Surface list got udpated so refresh GUI + -- Surface list got updated so refresh GUI for _, player in pairs(game.players) do local playerSettings = global.playerSettings[player.index] if playerSettings.gui ~= nil then @@ -685,14 +712,6 @@ function GUI.toggleMainWindow(event) -- Create frame without caption (we have our own title_bar) local mainWindow = player.gui.screen.add { type = "frame", name = "tlbe-main-window", direction = "vertical" } playerSettings.gui = {} - if playerSettings.guiPersist == nil then - playerSettings.guiPersist = { - -- initialize persisting gui configurations - selectedCamera = 1, - selectedCameraTracker = 1, - selectedTracker = 1 - } - end -- Add title bar local title_bar = mainWindow.add { type = "flow" } @@ -840,7 +859,7 @@ function GUI.createCameraSettings(parent, playerGUI, guiPersist, cameras, tracke } playerGUI.cameraInfo.add { type = "textfield", - name = "camera-transtion-period", + name = "camera-transition-period", tooltip = { "tooltip.camera-transitionperiod" }, style = "tlbe_config_half_width_textfield", numeric = true, @@ -1217,7 +1236,7 @@ function GUI.updateCameraConfig(cameraInfo, camera) cameraInfo["camera-name"].text = camera.name cameraInfo["camera-frame-rate"].text = string.format("%d", camera.frameRate or 25) cameraInfo["camera-speed-gain"].text = string.format("%d", camera.speedGain or 60) - cameraInfo["camera-transtion-period"].text = string.format("%2.2f", camera.transitionPeriod or 1.5) + cameraInfo["camera-transition-period"].text = string.format("%2.2f", camera.transitionPeriod or 1.5) cameraInfo["camera-entity-info"].state = camera.entityInfo cameraInfo["camera-always-day"].state = camera.alwaysDay resolutionFlow["camera-resolution-x"].text = string.format("%d", camera.width or 1920) @@ -1465,4 +1484,21 @@ function GUI.fancyListBoxSelectItem(fancyList, selectedIndex) end end +---@param player LuaPlayer +---@param playerSettings playerSettings +---@param index integer +function GUI.setSelectedCamera(player, playerSettings, index) + index = Utils.clamp(1, #playerSettings.cameras, index) + playerSettings.guiPersist.selectedCamera = index + + GUI.updateTakeScreenshotButton(player, playerSettings) +end + +---@param player LuaPlayer +---@param playerSettings playerSettings +function GUI.updateTakeScreenshotButton(player, playerSettings) + local available = playerSettings.cameras[playerSettings.guiPersist.selectedCamera].enabled == false + player.set_shortcut_available("tlbe-screenshot-shortcut", available) +end + return GUI diff --git a/scripts/main.lua b/scripts/main.lua index 87c7bc5..8c3a407 100644 --- a/scripts/main.lua +++ b/scripts/main.lua @@ -39,38 +39,7 @@ function Main.tick() Tracker.tick(activeTracker, player) - -- Move to tracker - Camera.followTracker(playerSettings, player, camera, activeTracker, false) - - local screenshotNumber - if playerSettings.sequentialNames then - screenshotNumber = camera.screenshotNumber - camera.screenshotNumber = camera.screenshotNumber + 1 - else - screenshotNumber = game.tick - end - - -- override the daytime if we are always day, otherwise leave it unaltered - local alwaysDay - if camera.alwaysDay then - -- take screenshot at full light - alwaysDay = 0 - else - alwaysDay = nil - end - - game.take_screenshot { - by_player = player, - surface = camera.surfaceName or game.surfaces[1], - position = camera.centerPos, - resolution = { camera.width, camera.height }, - zoom = camera.zoom, - path = string.format("%s/%s/%010d-%s.png", playerSettings.saveFolder, camera.saveFolder, screenshotNumber - , camera.saveName), - show_entity_info = camera.entityInfo, - allow_in_replay = true, - daytime = alwaysDay - } + Main.takeScreenshot(player, playerSettings, camera, activeTracker) ::nextCamera:: end @@ -163,6 +132,48 @@ function Main.rocket_launched(event) end end +-- Update camera position (if activeTracker is provided) and take a screenshot +---@param player LuaPlayer +---@param playerSettings playerSettings +---@param camera Camera.camera +---@param activeTracker Tracker.tracker|nil +function Main.takeScreenshot(player, playerSettings, camera, activeTracker) + if activeTracker ~= nil then + -- Move to tracker + Camera.followTracker(playerSettings, player, camera, activeTracker, false) + end + + local screenshotNumber + if playerSettings.sequentialNames then + screenshotNumber = camera.screenshotNumber + camera.screenshotNumber = camera.screenshotNumber + 1 + else + screenshotNumber = game.tick + end + + -- override the daytime if always day is selected, otherwise leave it unaltered + local alwaysDay + if camera.alwaysDay then + -- take screenshot at full light + alwaysDay = 0 + else + alwaysDay = nil + end + + game.take_screenshot { + by_player = player, + surface = camera.surfaceName or game.surfaces[1], + position = camera.centerPos, + resolution = { camera.width, camera.height }, + zoom = camera.zoom, + path = string.format("%s/%s/%010d-%s.png", playerSettings.saveFolder, camera.saveFolder, screenshotNumber + , camera.saveName), + show_entity_info = camera.entityInfo, + allow_in_replay = true, + daytime = alwaysDay + } +end + function Main.get_base_bbox() local entities = game.surfaces[1].find_entities_filtered { force = "player" }