diff --git a/src/css/ingame_hud/debug_info.scss b/src/css/ingame_hud/debug_info.scss index de69a4f9..3a077d53 100644 --- a/src/css/ingame_hud/debug_info.scss +++ b/src/css/ingame_hud/debug_info.scss @@ -5,10 +5,12 @@ text-align: right; font-size: 15px; - display: flex; + display: grid; line-height: 15px; - flex-direction: column; color: #fff; + grid-gap: 2px; + text-shadow: 1px 1px 3px rgba(#000, 0.4); + font-weight: bold; &:not([data-mode="detailed"]) { .mousePosition, @@ -16,4 +18,17 @@ display: none; } } + + code { + background: #333; + min-width: 30px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 14px; + line-height: 15px; + padding: 1px; + font-family: "GameFont"; + border-radius: 3px; + } } diff --git a/src/js/changelog.js b/src/js/changelog.js index 98388839..3e3e1a7d 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -9,11 +9,12 @@ export const CHANGELOG = [ "Allow binding TAB (by swtw7466)", "Added keybinding to close menus (by isaisstillalive / Sandwichs-del)", "Fix rare crash regarding the buildings toolbar (by isaisstillalive)", - "Fixed some phrases (By EnderDoom77)", + "Fixed some phrases (by EnderDoom77)", "Zoom towards mouse cursor (by Dimava)", "Updated the soundtrack again, it is now 20 minutes in total!", "Updated and added new translations (Thanks to all contributors!)", "Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)", + "Show mouse and camera tile on debug overlay (F4) (by dengr)", "Fix tunnels entrances connecting to exits sometimes when they shouldn't", ], }, diff --git a/src/js/game/hud/parts/debug_info.js b/src/js/game/hud/parts/debug_info.js index bfa09b1e..cdd00540 100644 --- a/src/js/game/hud/parts/debug_info.js +++ b/src/js/game/hud/parts/debug_info.js @@ -3,84 +3,120 @@ import { makeDiv, round3Digits, round2Digits } from "../../../core/utils"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { KEYMAPPINGS } from "../../key_action_mapper"; import { Vector } from "../../../core/vector"; +import { TrackedState } from "../../../core/tracked_state"; /** @enum {string} */ -export const enumDebugOverlayMode = { disabled: "disabled", regular: "regular", detailed: "detailed" }; +const enumDebugOverlayMode = { disabled: "disabled", regular: "regular", detailed: "detailed" }; + +/** + * Specifies which mode follows after which mode + * @enum {enumDebugOverlayMode} + */ +const enumDebugOverlayModeNext = { + [enumDebugOverlayMode.disabled]: enumDebugOverlayMode.regular, + [enumDebugOverlayMode.regular]: enumDebugOverlayMode.detailed, + [enumDebugOverlayMode.detailed]: enumDebugOverlayMode.disabled, +}; + +const UPDATE_INTERVAL_SECONDS = 0.25; export class HUDDebugInfo extends BaseHUDPart { createElements(parent) { this.element = makeDiv(parent, "ingame_HUD_DebugInfo", []); - this.tickRateElement = makeDiv(this.element, null, ["tickRate"], "Ticks /s: 120"); - this.fpsElement = makeDiv(this.element, null, ["fps"], "FPS: 60"); - this.tickDurationElement = makeDiv(this.element, null, ["tickDuration"], "Tick dur: 0.5ms"); - this.mousePositionElement = makeDiv(this.element, null, ["mousePosition"], "Pos: 0 0"); - this.cameraPositionElement = makeDiv(this.element, null, ["cameraPosition"], "Center: 0 0"); + const tickRateElement = makeDiv(this.element, null, ["tickRate"]); + this.trackedTickRate = new TrackedState(str => (tickRateElement.innerText = str)); + + const tickDurationElement = makeDiv(this.element, null, ["tickDuration"]); + this.trackedTickDuration = new TrackedState(str => (tickDurationElement.innerText = str)); + + const fpsElement = makeDiv(this.element, null, ["fps"]); + this.trackedFPS = new TrackedState(str => (fpsElement.innerText = str)); + + const mousePositionElement = makeDiv(this.element, null, ["mousePosition"]); + this.trackedMousePosition = new TrackedState(str => (mousePositionElement.innerHTML = str)); + + const cameraPositionElement = makeDiv(this.element, null, ["cameraPosition"]); + this.trackedCameraPosition = new TrackedState(str => (cameraPositionElement.innerHTML = str)); + this.versionElement = makeDiv(this.element, null, ["version"], "version unknown"); } initialize() { this.lastTick = 0; - this.mode = enumDebugOverlayMode.disabled; + this.trackedMode = new TrackedState(this.onModeChanged, this); this.domAttach = new DynamicDomAttach(this.root, this.element); - this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleFPSInfo).add(() => this.toggle()); + this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleFPSInfo).add(() => this.cycleModes()); + + // Set initial mode + this.trackedMode.set(enumDebugOverlayMode.disabled); } - updateFullText() { - this.element.setAttribute("data-mode", this.mode); - - let version = `version ${G_BUILD_VERSION}`; - if (this.full) { - version += ` @ ${G_APP_ENVIRONMENT} @ ${G_BUILD_COMMIT_HASH}`; - } - - this.versionElement.innerText = version; + /** + * Called when the mode changed + * @param {enumDebugOverlayMode} mode + */ + onModeChanged(mode) { + this.element.setAttribute("data-mode", mode); + this.versionElement.innerText = `${G_BUILD_VERSION} @ ${G_APP_ENVIRONMENT} @ ${G_BUILD_COMMIT_HASH}`; } - updatePositions() { - let mousePos = this.root.app.mousePosition || new Vector(0, 0); - mousePos = this.root.camera.screenToWorld(mousePos).toTileSpace(); - const cameraPos = this.root.camera.center.toTileSpace(); - - this.mousePositionElement.innerText = `Pos: ${mousePos.x} ${mousePos.y}`; - this.cameraPositionElement.innerText = `Center: ${cameraPos.x} ${cameraPos.y}`; - } - - toggle() { - switch (this.mode) { - case enumDebugOverlayMode.detailed: - this.mode = enumDebugOverlayMode.disabled; - break; - case enumDebugOverlayMode.regular: - this.mode = enumDebugOverlayMode.detailed; - break; - default: - this.mode = enumDebugOverlayMode.regular; - break; - } - this.updateFullText(); - this.domAttach.update(this.mode !== enumDebugOverlayMode.disabled); - } - - update() { - const now = this.root.time.realtimeNow(); - if (!this.visible) return; - - if (now - this.lastTick > 0.25) { - this.lastTick = now; - this.tickRateElement.innerText = "Tickrate: " + this.root.dynamicTickrate.currentTickRate; - this.fpsElement.innerText = - "FPS: " + + /** + * Updates the labels + */ + updateLabels() { + this.trackedTickRate.set("Tickrate: " + this.root.dynamicTickrate.currentTickRate); + this.trackedFPS.set( + "FPS: " + Math.round(this.root.dynamicTickrate.averageFps) + " (" + round2Digits(1000 / this.root.dynamicTickrate.averageFps) + - " ms)"; - this.tickDurationElement.innerText = - "Tick Dur: " + round3Digits(this.root.dynamicTickrate.averageTickDuration) + "ms"; + " ms)" + ); + this.trackedTickDuration.set( + "Tick: " + round3Digits(this.root.dynamicTickrate.averageTickDuration) + "ms" + ); + } + + /** + * Updates the detailed information + */ + updateDetailedInformation() { + const mousePos = this.root.app.mousePosition || new Vector(0, 0); + const mouseTile = this.root.camera.screenToWorld(mousePos).toTileSpace(); + const cameraTile = this.root.camera.center.toTileSpace(); + + this.trackedMousePosition.set(`Pos: ${mouseTile.x} / ${mouseTile.y}`); + this.trackedCameraPosition.set(`Center: ${cameraTile.x} / ${cameraTile.y}`); + } + + /** + * Cycles through the different modes + */ + cycleModes() { + this.trackedMode.set(enumDebugOverlayModeNext[this.trackedMode.get()]); + } + + update() { + const visible = this.trackedMode.get() !== enumDebugOverlayMode.disabled; + this.domAttach.update(visible); + + if (!visible) { + return; } - this.updatePositions(); + // Periodically update the text + const now = this.root.time.realtimeNow(); + if (now - this.lastTick > UPDATE_INTERVAL_SECONDS) { + this.lastTick = now; + this.updateLabels(); + } + + // Also update detailed information if required + if (this.trackedMode.get() === enumDebugOverlayMode.detailed) { + this.updateDetailedInformation(); + } } }