Index: ps/trunk/binaries/data/mods/public/gui/common/OverlayCounterManager.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/common/OverlayCounterManager.js (revision 24867) +++ ps/trunk/binaries/data/mods/public/gui/common/OverlayCounterManager.js (revision 24868) @@ -1,119 +1,128 @@ /** * Since every GUI page can display the FPS or realtime counter, * this manager is initialized for every GUI page. */ var g_OverlayCounterManager; class OverlayCounterManager { constructor(dataCounter) { this.dataCounter = dataCounter; this.counters = []; this.enabledCounters = []; this.lastTick = undefined; this.resizeHandlers = []; + this.lastHeight = undefined; this.initSize = this.dataCounter.size; for (let name of this.availableCounterNames()) { let counterType = OverlayCounterTypes.prototype[name]; if (counterType.IsAvailable && !counterType.IsAvailable()) continue; let counter = new counterType(this); this.counters.push(counter); counter.updateEnabled(); } this.dataCounter.onTick = this.onTick.bind(this); } /** * Mods may overwrite this to change the order of the counters shown. */ availableCounterNames() { return Object.keys(OverlayCounterTypes.prototype); } deleteCounter(counter) { let filter = count => count != counter; this.counters = this.counters.filter(filter); this.enabledCounters = this.enabledCounters.filter(filter); } /** * This function allows enabling and disabling of timers while preserving the counter order. */ setCounterEnabled(counter, enabled) { if (enabled) this.enabledCounters = this.counters.filter(count => this.enabledCounters.indexOf(count) != -1 || count == counter); else this.enabledCounters = this.enabledCounters.filter(count => count != counter); // Update instantly this.lastTick = undefined; this.onTick(); } /** * Handlers subscribed here will be informed when the dimension of the overlay changed. * This allows placing the buttons away from the counter. */ registerResizeHandler(handler) { this.resizeHandlers.push(handler); } onTick() { // Don't rebuild the caption every frame let now = Date.now(); if (now < this.lastTick + this.Delay) return; this.lastTick = now; let lineCount = 0; let txt = ""; for (let counter of this.enabledCounters) { let newTxt = counter.get(); if (!newTxt) continue; ++lineCount; txt += newTxt + "\n"; } + let height; if (lineCount) { this.dataCounter.caption = txt; // Just using the previous size for getting the size of the new text // could lead to unneeded linebreaks. // Therefore we set the overlay to the maximum size before reading the text size. this.dataCounter.size = this.initSize; let textSize = this.dataCounter.getTextSize(); let size = this.dataCounter.size; size.bottom = size.top + textSize.height; size.left = size.right - textSize.width; this.dataCounter.size = size; + height = textSize.height; } + else + height = 0; this.dataCounter.hidden = !lineCount; - for (let handler of this.resizeHandlers) - handler(textSize); + if (this.lastHeight != height) + { + this.lastHeight = height; + for (let handler of this.resizeHandlers) + handler(height); + } } } /** * To minimize the computation performed every frame, this duration * in milliseconds determines how often the caption is rebuilt. */ OverlayCounterManager.prototype.Delay = 250; Index: ps/trunk/binaries/data/mods/public/gui/session/ResearchProgress.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/ResearchProgress.js (revision 24867) +++ ps/trunk/binaries/data/mods/public/gui/session/ResearchProgress.js (revision 24868) @@ -1,108 +1,109 @@ /** * This class is responsible for displaying the currently researched technologies in an overlay. */ class ResearchProgress { constructor(playerViewControl, selection) { this.buttons = Engine.GetGUIObjectByName("researchStartedButtons").children; this.buttonHandlers = this.buttons.map((button, i) => new ResearchProgressButton(selection, i)); /** * Top coordinate of the research list. * Changes depending on the number of displayed counters. */ this.topOffset = 0; let updater = this.updateResearchProgress.bind(this); registerSimulationUpdateHandler(updater); playerViewControl.registerViewedPlayerChangeHandler(updater); + g_OverlayCounterManager.registerResizeHandler(this.setTopOffset.bind(this)); } setTopOffset(offset) { this.topOffset = offset; } updateResearchProgress() { let researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", g_ViewedPlayer); let i = 0; for (let techName in researchStarted) { if (i == this.buttons.length) break; this.buttonHandlers[i++].onResearchedProgress(this.topOffset, techName, researchStarted[techName]); } while (i < this.buttons.length) this.buttons[i++].hidden = true; } } /** * This is an individual button displaying a tech currently researched by the currently viewed player. */ class ResearchProgressButton { constructor(selection, i) { this.selection = selection; this.button = Engine.GetGUIObjectByName("researchStartedButton[" + i + "]"); this.sprite = Engine.GetGUIObjectByName("researchStartedIcon[" + i + "]"); this.progress = Engine.GetGUIObjectByName("researchStartedProgressSlider[" + i + "]"); this.timeRemaining = Engine.GetGUIObjectByName("researchStartedTimeRemaining[" + i + "]"); this.buttonHeight = this.button.size.bottom - this.button.size.top; this.buttonTop = this.Margin + (this.Margin + this.buttonHeight) * i; this.progressHeight = this.progress.size.bottom - this.progress.size.top; this.progressTop = this.progress.size.top; this.button.onPress = this.onPress.bind(this); } onResearchedProgress(offset, techName, researchStatus) { this.researcher = researchStatus.researcher; let template = GetTechnologyData(techName, g_Players[g_ViewedPlayer].civ); this.sprite.sprite = "stretched:" + this.PortraitDirectory + template.icon; let size = this.button.size; size.top = offset + this.buttonTop; size.bottom = size.top + this.buttonHeight; this.button.size = size; this.button.tooltip = getEntityNames(template); this.button.hidden = false; size = this.progress.size; size.top = this.progressTop + this.progressHeight * researchStatus.progress; this.progress.size = size; this.timeRemaining.caption = Engine.FormatMillisecondsIntoDateStringGMT( researchStatus.timeRemaining, translateWithContext("countdown format", this.CountdownFormat)); } onPress() { this.selection.selectAndMoveTo(this.researcher); } } /** * Distance between consecutive buttons. */ ResearchProgressButton.prototype.Margin = 4; /** * Directory containing all icons. */ ResearchProgressButton.prototype.PortraitDirectory = "session/portraits/"; /** * This format is used when displaying the remaining time of the currently viewed techs in research. */ ResearchProgressButton.prototype.CountdownFormat = markForTranslationWithContext("countdown format", "m:ss");