Skip to content

Commit 7fd334e

Browse files
Add Debug Settings Architecture (#718)
* Add Debug Settings Architecture Repost of this commit since it was reverted. The Debug Settings system provides runtime-configurable debug features through a UI overlay. Settings are persisted to config.debug and can be accessed anywhere via the DebugSettings singleton. Also provide a way to generate the debug menu and surface it from a debug button. To support this new button and future overlays, add a root element to the game so we can order overlays Updated Bool Selector to size correctly Updated Style Selector creation to make sure sizing and layout is right Reload main menu when you come back to it Make navigation stack a UIElement so it works with touch handling Fixes #697 Also restore the custom name after saving for debug username
1 parent 860f767 commit 7fd334e

36 files changed

Lines changed: 1102 additions & 187 deletions

client/src/BattleRoom.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ local BlackFadeTransition = require("client.src.scenes.Transitions.BlackFadeTran
1212
local Easings = require("client.src.Easings")
1313
local system = require("client.src.system")
1414
local GeneratorSource = require("common.engine.GeneratorSource")
15+
local DebugSettings = require("client.src.debug.DebugSettings")
1516

1617
-- A Battle Room is a session of matches, keeping track of the room number, player settings, wins / losses etc
1718
---@class BattleRoom : Signal
@@ -383,7 +384,7 @@ function BattleRoom:createScene(match)
383384
end
384385

385386
-- for touch android players load a different scene
386-
if (system.isMobileOS() or DEBUG_ENABLED) and self.gameScene.name ~= "PuzzleGame" and
387+
if (system.isMobileOS() or DebugSettings.simulateMobileOS()) and self.gameScene.name ~= "PuzzleGame" and
387388
--but only if they are the only local player cause for 2p vs local using portrait mode would be bad
388389
tableUtils.count(self.players, function(p) return p.isLocal and p.human end) == 1 then
389390
for _, player in ipairs(self.players) do

client/src/ChallengeModePlayerStack.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local class = require("common.lib.class")
22
local ClientStack = require("client.src.ClientStack")
33
local GraphicsUtil = require("client.src.graphics.graphics_util")
4+
local DebugSettings = require("client.src.debug.DebugSettings")
45

56
---@class ChallengeModePlayerStack : ClientStack
67
---@field engine SimulatedStack
@@ -198,7 +199,7 @@ function ChallengeModePlayerStack:drawMultibar()
198199
end
199200

200201
function ChallengeModePlayerStack:drawDebug()
201-
if config.debug_mode then
202+
if DebugSettings.showStackDebugInfo() then
202203
local drawX = self.frameOriginX + self:canvasWidth() / 2
203204
local drawY = 10
204205
local padding = 14

client/src/ClientMatch.lua

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ local Telegraph = require("client.src.graphics.Telegraph")
1616
local MatchParticipant = require("client.src.MatchParticipant")
1717
local ChallengeModePlayerStack = require("client.src.ChallengeModePlayerStack")
1818
local NetworkProtocol = require("common.network.NetworkProtocol")
19+
local DebugSettings = require("client.src.debug.DebugSettings")
1920
---@module "client.src.ChallengeModePlayerStack"
2021

2122
---@class ClientMatch
@@ -84,7 +85,7 @@ function ClientMatch.createFromGameMode(players, gameMode, panelSource, ranked,
8485
clientMatch.panelSource = panelSource
8586
clientMatch.supportsPause = #players == 1 and players[1].isLocal
8687

87-
clientMatch:setup()
88+
clientMatch:setupFromGameMode()
8889

8990
return clientMatch
9091
end
@@ -140,10 +141,12 @@ function ClientMatch.createFromReplay(replay, players)
140141
clientMatch.stacks[i] = clientStack
141142
end
142143

144+
clientMatch:sharedSetup()
145+
143146
return clientMatch
144147
end
145148

146-
function ClientMatch:setup()
149+
function ClientMatch:setupFromGameMode()
147150
self.engine = Match(self.panelSource, self.matchRules)
148151

149152
self.stacks = {}
@@ -189,9 +192,16 @@ function ClientMatch:setup()
189192
end
190193
end
191194

195+
self:sharedSetup()
196+
192197
self.replay = self.engine:createNewReplay()
193198
end
194199

200+
201+
function ClientMatch:sharedSetup()
202+
self.engine.debug.vsFramesBehind = DebugSettings.getVSFramesBehind()
203+
end
204+
195205
function ClientMatch:run()
196206
if self.isPaused or self.engine:hasEnded() then
197207
self:runGameOver()
@@ -559,7 +569,7 @@ end
559569

560570
function ClientMatch:drawCommunityMessage()
561571
-- Draw the community message
562-
if not config.debug_mode then
572+
if not DebugSettings.showStackDebugInfo() then
563573
GraphicsUtil.printf(join_community_msg or "", 0, 668, consts.CANVAS_WIDTH, "center")
564574
end
565575
end
@@ -598,7 +608,7 @@ function ClientMatch:render()
598608
end
599609
end
600610

601-
if config.debug_mode then
611+
if DebugSettings.showStackDebugInfo() then
602612
local padding = 14
603613
local drawX = 500
604614
local drawY = -4

client/src/Game.lua

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ local system = require("client.src.system")
3333
local ModController = require("client.src.mods.ModController")
3434

3535
local RichPresence = require("client.lib.rich_presence.RichPresence")
36+
local DebugSettings = require("client.src.debug.DebugSettings")
37+
local Button = require("client.src.ui.Button")
38+
local TextButton = require("client.src.ui.TextButton")
39+
local OverlayContainer = require("client.src.ui.OverlayContainer")
40+
local DebugMenu = require("client.src.debug.DebugMenu")
41+
local Label = require("client.src.ui.Label")
42+
local UIElement = require("client.src.ui.UIElement")
43+
local NavigationStack = require("client.src.NavigationStack")
3644

3745
-- Provides a scale that is on .5 boundary to make sure it renders well.
3846
-- Useful for creating new canvas with a solid DPI
@@ -106,12 +114,19 @@ local Game = class(
106114

107115
-- time in seconds, can be used by other elements to track the passing of time beyond dt
108116
self.timer = love.timer.getTime()
117+
118+
self.debugOverlay = nil
119+
self.debugButton = nil
120+
121+
-- Root UI element that contains all UI (scenes + overlays + debug)
122+
self.uiRoot = UIElement({x = 0, y = 0, width = consts.CANVAS_WIDTH, height = consts.CANVAS_HEIGHT})
109123
end
110124
)
111125

112126
Game.newCanvasSnappedScale = newCanvasSnappedScale
113127

114128
function Game:load()
129+
DebugSettings.init()
115130
PuzzleLibrary.cleanupDefaultPuzzles(consts.PUZZLES_SAVE_DIRECTORY)
116131

117132
-- move to constructor
@@ -131,8 +146,11 @@ function Game:load()
131146
self.input:importConfigurations(user_input_conf)
132147
end
133148

134-
self.navigationStack = require("client.src.NavigationStack")
149+
self.navigationStack = NavigationStack({})
135150
self.navigationStack:push(StartUp({setupRoutine = self.setupRoutine}))
151+
152+
-- Add navigation stack to root UI
153+
self.uiRoot:addChild(self.navigationStack)
136154
self.globalCanvas = love.graphics.newCanvas(consts.CANVAS_WIDTH, consts.CANVAS_HEIGHT, {dpiscale=GAME:newCanvasSnappedScale()})
137155
end
138156

@@ -253,6 +271,8 @@ function Game:setupRoutine()
253271

254272
self:initializeLocalPlayer()
255273
ModController:loadModFor(characters[GAME.localPlayer.settings.characterId], GAME.localPlayer, true)
274+
275+
self:initializeDebugOverlay()
256276
end
257277

258278
-- GAME.localPlayer is the standard player for battleRooms that don't get started from replays/spectate
@@ -366,9 +386,9 @@ function Game:update(dt)
366386

367387
handleShortcuts()
368388

369-
prof.push("navigationStack update")
370-
self.navigationStack:update(dt)
371-
prof.pop("navigationStack update")
389+
prof.push("uiRoot update")
390+
self.uiRoot:update(dt)
391+
prof.pop("uiRoot update")
372392

373393
if self.backgroundImage then
374394
self.backgroundImage:update(dt)
@@ -386,7 +406,7 @@ function Game:draw()
386406
love.graphics.clear()
387407

388408
-- With this, self.globalCanvas is clear and set as our active canvas everything is being drawn to
389-
self.navigationStack:draw()
409+
self.uiRoot:draw()
390410

391411
self:drawFPS()
392412
self:drawScaleInfo()
@@ -402,8 +422,7 @@ function Game:draw()
402422
end
403423

404424
function Game:drawFPS()
405-
-- Draw the FPS if enabled
406-
if self.config.show_fps then
425+
if self.config.show_fps or DebugSettings.forceFPS() then
407426
love.graphics.print("FPS: " .. love.timer.getFPS(), 1, 1)
408427
end
409428
end
@@ -666,4 +685,40 @@ function Game:setLanguage(lang_code)
666685
Localization:refresh_global_strings()
667686
end
668687

688+
function Game:initializeDebugOverlay()
689+
if not DEBUG_ENABLED then
690+
return
691+
end
692+
693+
self.debugButton = TextButton({
694+
x = consts.CANVAS_WIDTH - 50,
695+
y = consts.CANVAS_HEIGHT - 50,
696+
label = Label({
697+
text = "Debug",
698+
translate = false,
699+
hAlign = "center",
700+
vAlign = "center"
701+
}),
702+
width = 40,
703+
height = 40,
704+
onClick = function()
705+
if self.debugOverlay then
706+
if not self.debugOverlay:isActive() then
707+
self.debugOverlay:open()
708+
end
709+
end
710+
end
711+
})
712+
713+
local debugMenu = DebugMenu.makeDebugMenu({height = consts.CANVAS_HEIGHT - 40})
714+
self.debugOverlay = OverlayContainer({
715+
content = debugMenu
716+
})
717+
718+
-- Add debug UI to root
719+
self.uiRoot:addChild(self.debugButton)
720+
self.uiRoot:addChild(self.debugOverlay)
721+
end
722+
723+
669724
return Game

client/src/NavigationStack.lua

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
local DirectTransition = require("client.src.scenes.Transitions.DirectTransition")
22
local logger = require("common.lib.logger")
3-
4-
local NavigationStack = {
5-
scenes = {},
6-
transition = nil,
7-
callback = nil,
8-
}
3+
local UIElement = require("client.src.ui.UIElement")
4+
local class = require("common.lib.class")
5+
local consts = require("common.engine.consts")
6+
7+
---@class NavigationStack : UiElement
8+
---@field scenes Scene[]
9+
---@field transition table?
10+
---@field callback function?
11+
local NavigationStack = class(
12+
function(self)
13+
self.scenes = {}
14+
self.transition = nil
15+
self.callback = nil
16+
self.width = consts.CANVAS_WIDTH
17+
self.height = consts.CANVAS_HEIGHT
18+
end,
19+
UIElement
20+
)
921

1022
function NavigationStack:push(newScene, transition)
1123
local activeScene = self.scenes[#self.scenes]
@@ -142,7 +154,7 @@ function NavigationStack:getActiveScene()
142154
end
143155
end
144156

145-
function NavigationStack:update(dt)
157+
function NavigationStack:updateSelf(dt)
146158
if self.transition then
147159
self.transition:update(dt)
148160

@@ -163,7 +175,7 @@ function NavigationStack:update(dt)
163175
end
164176
end
165177

166-
function NavigationStack:draw()
178+
function NavigationStack:drawSelf()
167179
if self.transition then
168180
self.transition:draw()
169181
else
@@ -174,4 +186,12 @@ function NavigationStack:draw()
174186
end
175187
end
176188

189+
function NavigationStack:getTouchedElement(x, y)
190+
local activeScene = self:getActiveScene()
191+
if activeScene and activeScene.uiRoot then
192+
return activeScene.uiRoot:getTouchedElement(x, y)
193+
end
194+
return nil
195+
end
196+
177197
return NavigationStack

client/src/PlayerStack.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ local logger = require("common.lib.logger")
1515
require("client.src.analytics")
1616
local KeyDataEncoding = require("common.data.KeyDataEncoding")
1717
local MatchRules = require("common.data.MatchRules")
18+
local DebugSettings = require("client.src.debug.DebugSettings")
1819
---@module "common.data.LevelData"
1920

2021
local floor, min, max = math.floor, math.min, math.max
@@ -767,7 +768,7 @@ function PlayerStack:drawPopBurstParticle(atlas, quad, frameIndex, atlasDimensio
767768
end
768769

769770
function PlayerStack:drawDebug()
770-
if config.debug_mode then
771+
if DebugSettings.showStackDebugInfo() then
771772
local engine = self.engine
772773

773774
local x = self.origin_x + 480
@@ -863,7 +864,7 @@ function PlayerStack:drawDebug()
863864
end
864865

865866
function PlayerStack:drawDebugPanels(shakeOffset)
866-
if not config.debug_mode then
867+
if not DebugSettings.showStackDebugInfo() then
867868
return
868869
end
869870

@@ -952,7 +953,7 @@ function PlayerStack:drawRating()
952953
local rating
953954
if self.player.rating and tonumber(self.player.rating) then
954955
rating = self.player.rating
955-
elseif config.debug_mode then
956+
elseif DebugSettings.showStackDebugInfo() then
956957
rating = 1544 + self.player.playerNumber
957958
end
958959

client/src/Shortcuts.lua

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ local logger = require("common.lib.logger")
77
local function runSystemCommands()
88
-- toggle debug mode
99
if input.allKeys.isDown["d"] then
10-
config.debug_mode = not config.debug_mode
10+
if GAME.debugOverlay then
11+
if GAME.debugOverlay.active then
12+
GAME.debugOverlay:close()
13+
else
14+
GAME.debugOverlay:open()
15+
end
16+
end
1117
-- reload characters
1218
elseif input.allKeys.isDown["c"] then
1319
characters_reload_graphics()

0 commit comments

Comments
 (0)