Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/gui/reference/structree/StructureBox.js
- This file was added.
/** | |||||
* This code wraps the gui representing buildable structures within the structree. | |||||
* | |||||
* An instance of this class is created for each child of the gui element named "structures". | |||||
*/ | |||||
class StructureBox extends EntityBox | |||||
{ | |||||
constructor(structIdx, Parser) | |||||
{ | |||||
super(structIdx, Parser); | |||||
this.gui = Engine.GetGUIObjectByName("structure[" + this.guiIdx + "]"); | |||||
this.productionIconRows = Engine.GetGUIObjectByName("structure[" + this.guiIdx + "]_rows"); | |||||
// Position production icons | |||||
for (let row of this.productionIconRows.children) | |||||
horizontallySpaceObjects(row.name, this.constructor.ProdIconSize().hMargin); | |||||
} | |||||
draw(templateName, civCode, runningWidths) | |||||
{ | |||||
super.draw(templateName, civCode); | |||||
this.phaseIdx = this.Parser.phaseList.indexOf(this.template.phase); | |||||
let rowCounts = Array(this.Parser.phaseList.length - this.phaseIdx).fill(0); | |||||
// (Want to draw Units before Techs) | |||||
for (let prodType of Object.keys(this.template.production).reverse()) | |||||
elexis: Separation of concerns - The task to draw a ProductionQueue item type 1 (unit) and a… | |||||
for (let prod of this.template.production[prodType]) | |||||
{ | |||||
let pIdx = 0; | |||||
switch (prodType) | |||||
{ | |||||
case "units": | |||||
prod = this.Parser.getEntity(prod, civCode); | |||||
pIdx = this.Parser.phaseList.indexOf(prod.phase); | |||||
break; | |||||
case "techs": | |||||
pIdx = this.Parser.phaseList.indexOf(this.Parser.getPhaseOfTechnology(prod, civCode)); | |||||
prod = clone(this.Parser.getTechnology(prod, civCode)); | |||||
for (let res in this.template.techCostMultiplier) | |||||
if (prod.cost[res]) | |||||
prod.cost[res] *= this.template.techCostMultiplier[res]; | |||||
break; | |||||
default: | |||||
continue; | |||||
} | |||||
let rowIdx = Math.max(0, pIdx - this.phaseIdx); | |||||
if (!this.drawProdIcon(rowIdx, rowCounts[rowIdx], prod, civCode)) | |||||
break; | |||||
++rowCounts[rowIdx]; | |||||
} | |||||
if (this.template.upgrades) | |||||
for (let upgrade of this.template.upgrades) | |||||
{ | |||||
let pIdx = this.Parser.phaseList.indexOf(upgrade.phase); | |||||
let rowIdx = Math.max(0, pIdx - this.phaseIdx); | |||||
if (!this.drawProdIcon(rowIdx, rowCounts[rowIdx], upgrade, civCode)) | |||||
break; | |||||
++rowCounts[rowIdx]; | |||||
} | |||||
if (this.template.wallset && this.drawProdIcon(0, rowCounts[0], this.template.wallset.tower, civCode)) | |||||
++rowCounts[0]; | |||||
// Position the production rows and centre the icons within them | |||||
let prodIconSize = this.constructor.ProdIconSize(); | |||||
let largestRowWidth = 0; | |||||
for (let rowIdx in rowCounts) | |||||
{ | |||||
hideRemaining(this.productionIconRows.children[rowIdx].name, rowCounts[rowIdx]); | |||||
let rowOffset = prodIconSize.rowHeight * (this.Parser.phaseList.length - this.phaseIdx - rowIdx); | |||||
let rowWidth = rowCounts[rowIdx] * prodIconSize.rowWidth + prodIconSize.hMargin; | |||||
largestRowWidth = Math.max(largestRowWidth, rowWidth); | |||||
let size = this.productionIconRows.children[rowIdx].size; | |||||
size.left = -rowWidth / 2; | |||||
size.top = -rowOffset; | |||||
this.productionIconRows.children[rowIdx].size = size; | |||||
} | |||||
// Hide remaining phase rows | |||||
hideRemaining(this.productionIconRows.name, rowCounts.length); | |||||
let boxWidth = Math.max(this.constructor.boxMinWidth, super.captionWidth(), largestRowWidth); | |||||
// Set position of the Structure Box | |||||
let size = this.gui.size; | |||||
size.left = this.constructor.boxMargin + runningWidths[this.phaseIdx]; | |||||
size.right = this.constructor.boxMargin + runningWidths[this.phaseIdx] + boxWidth; | |||||
size.top = this.constructor.boxMargin * 2 + StructreePage.getPositionOffset(this.phaseIdx, this.Parser); | |||||
size.bottom = StructreePage.getPositionOffset(this.phaseIdx + 1, this.Parser); | |||||
Not Done Inline Actions(StructreePage.getPositionOffset = this.getPositionOffset if its not static I think) elexis: (`StructreePage.getPositionOffset` = `this.getPositionOffset` if its not static I think) | |||||
this.gui.size = size; | |||||
// Update new right-side-edge dimension | |||||
runningWidths[this.phaseIdx] += boxWidth + this.constructor.boxMargin / 2; | |||||
} | |||||
/** | |||||
* Draws a single production icon (the small icons on the gray bars). | |||||
* | |||||
* This differs from the version used within the TrainerBox class by having a rowID argument. | |||||
* | |||||
* Returns True if successfully drawn, False if no space left to draw. | |||||
*/ | |||||
drawProdIcon(rowID, iconID, template, civCode) | |||||
{ | |||||
let prodEle = this.productionIconRows.children[rowID].children[iconID]; | |||||
if (prodEle === undefined) | |||||
{ | |||||
error("The structures of the currently displayed civ have more production " + | |||||
"icons than can be supported by the current GUI layout"); | |||||
return false; | |||||
} | |||||
this.constructor.drawProdIcon(prodEle, template, civCode); | |||||
return true; | |||||
} | |||||
} |
Wildfire Games · Phabricator
Separation of concerns - The task to draw a ProductionQueue item type 1 (unit) and a ProductionQueue type 2 (tech), the task to draw Upgrade components and the task to distribute boxes could be split into separate functions.
A disadvantage of having more functions is that it becomes less transparent which of these functions are called from other files ("public") and which ones are called only internally ("private").
An advantage of having more functions is that mods (for example nanis autociv mod) can hook into existing functions (replace them with functions that call the previous function and add some statements for example).
Another advantage of having more functions, especially in this case, is that it could ease introduction of new components.
If a simulation author adds a new Component and sees there are functions for SimulationComponent1 and SimulationComponent2, it will be inviting to add a function for SimulationComponent3.
Depending on how far one wants to open up that room, one could even split them into different subclasses somehow.
I dont mind how it's implemented, just mentioning this as an alternative with possible pros and cons.