Redesigned the selection GUI

No more groups of any kind
Max selection size increased to 32

Single click - deselects all others
Single click with shift key - deselects all that are not the same type
(only for one rank)

This was SVN commit r7826.
This commit is contained in:
WhiteTreePaladin 2010-07-30 22:19:43 +00:00
parent d29dd45237
commit ba591b6d9f
7 changed files with 134 additions and 419 deletions

View File

@ -4,7 +4,7 @@ const SDL_BUTTON_RIGHT = 3;
const SDLK_RSHIFT = 303;
const SDLK_LSHIFT = 304;
const MAX_SELECTION_SIZE = 24;
const MAX_SELECTION_SIZE = 32;
// TODO: these constants should be defined somewhere else instead, in
// case any other code wants to use them too
@ -266,9 +266,6 @@ function handleInputBeforeGui(ev)
g_Selection.reset();
g_Selection.addList(ents);
// Create the selection groups
g_Selection.groups.createGroups(ents);
inputState = INPUT_NORMAL;
return true;
}
@ -616,3 +613,12 @@ function removeFromTrainingQueue(entity, id)
{
Engine.PostNetworkCommand({"type": "stop-train", "entity": entity, "id": id});
}
// Called by unit selection buttons
function changePrimarySelectionGroup(index)
{
if (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT])
g_Selection.makePrimarySelection(index, true);
else
g_Selection.makePrimarySelection(index, false);
}

View File

@ -1,11 +1,3 @@
// Group Selection by Rank
var g_GroupSelectionByRank = true; // referenced in EntityGroups.createGroups(ents) AND in setupUnitPanel(...)
function groupSelectionByRank(booleanValue)
{
g_GroupSelectionByRank = booleanValue;
g_Selection.groups.createGroups(g_Selection.toList());
}
function toggleDeveloperOverlay()
{
if (getGUIObjectByName("devCommands").hidden)

View File

@ -14,163 +14,6 @@ function _setMotionOverlay(ents, enabled)
Engine.GuiInterfaceCall("SetMotionDebugOverlay", { "entities":ents, "enabled":enabled });
}
//-------------------------------- -------------------------------- --------------------------------
// EntityGroups class for ordering / managing entities by their templates
//-------------------------------- -------------------------------- --------------------------------
function EntityGroups()
{
// private properties
this.primary = 0;
this.groups = []; // Includes only highest ranked versions of each type
}
EntityGroups.prototype.Group = function(templateName, typeCount, firstOfType)
{
this.templateName = templateName;
this.typeCount = typeCount;
this.firstOfType = firstOfType;
};
EntityGroups.prototype.reset = function()
{
this.primary = 0;
this.groups = [];
};
EntityGroups.prototype.getLength = function()
{
return this.groups.length;
};
EntityGroups.prototype.getPrimary = function()
{
return this.primary;
};
EntityGroups.prototype.setPrimary = function(index)
{
if (this.groups.length > index)
this.primary = index;
else
console.write("Warning: \"index\" is larger than g_Selection.toList().length: Cannot set Primary Selection.");
};
EntityGroups.prototype.getGroup = function(templateName)
{
// Get the group that corresponds to the template name
var group = this.groups[this.getGroupNumber(templateName)];
if (group)
return group;
// The templateName didn't match any in the groups...
// Check if it's the same unit, but a different rank and return that group
if (g_GroupSelectionByRank)
{
var thatGenericTemplateName = templateName.substring(0, templateName.length-2);
var templateNames = this.getTemplateNames();
for (var i = 0; i < templateNames.length; i++)
{
var thisGenericTemplateName = templateNames[i].substring(0, templateNames[i].length-2);
if (thisGenericTemplateName == thatGenericTemplateName)
return this.groups[i];
}
}
// There was no match...
//console.write("Warning: Could not find either \"" + templateName + "\" or the more generic: \"" + thatGenericTemplateName + "\"");
return undefined;
};
EntityGroups.prototype.addGroup = function(templateName, typeCount, firstOfType)
{
this.groups.push(new this.Group(templateName, typeCount, firstOfType));
};
EntityGroups.prototype.removeGroup = function(templateName)
{
var index = this.getGroupNumber(templateName);
this.groups.splice(index, 1);
};
EntityGroups.prototype.getGroupNumber = function(templateName)
{
for (var i = 0; i < this.groups.length; i++)
if (this.groups[i].templateName == templateName)
return i;
return -1;
};
EntityGroups.prototype.getTemplateNames = function()
{
var templateNames = [];
for (var i = 0; i < this.groups.length; i++)
templateNames.push(this.groups[i].templateName);
return templateNames;
};
// Checks if the new rank code is greater than the old rank code (private helper function for EntityGroups.createGroups)
EntityGroups.prototype.greaterThanPreviousRank = function(oldRank, newRank)
{
if (oldRank == newRank)
return false;
else if (oldRank == 'b' || newRank == 'e')
return true;
else
return false;
};
EntityGroups.prototype.createGroups = function(ents)
{
// Erase old groups first
this.reset();
// Make selection groups
for (var i = 0; i < ents.length; i++)
{
var templateName = Engine.GuiInterfaceCall("GetEntityState", ents[i]).template;
var group = this.getGroup(templateName);
// We already have one of these types
if (group)
{
// See if the new one has a higher rank
var isRankableUnit = ((templateName.charAt(templateName.length-2) == '_')? true : false);
if (g_GroupSelectionByRank && isRankableUnit)
{
var oldRank = group.templateName.charAt(group.templateName.length-1);
var newRank = templateName.charAt(templateName.length-1);
if (this.greaterThanPreviousRank(oldRank, newRank))
{
var oldTypeCount = group.typeCount;
this.removeGroup(group.templateName);
this.addGroup(templateName, oldTypeCount+1, i);
}
else
{
group.typeCount += 1;
}
}
else // It was not a rankable unit or its rank was not higher than the one we had
{
group.typeCount += 1;
}
}
else // Don't have any of this type, so add it in
{
this.addGroup(templateName, 1, i);
}
}
resetCycleIndex();
}
//-------------------------------- -------------------------------- --------------------------------
// EntitySelection class for managing the entity selection list and the primary selection
//-------------------------------- -------------------------------- --------------------------------
@ -178,7 +21,6 @@ function EntitySelection()
{
// Private properties:
//--------------------------------
this.primary = 0; // The active selection in the unit details panel
this.selected = {}; // { id:id, id:id, ... } for each selected entity ID 'id'
// { id:id, ... } for mouseover-highlighted entity IDs in these, the key is a string and the value is an int;
@ -189,38 +31,56 @@ function EntitySelection()
// Public properties:
//--------------------------------
this.groups = new EntityGroups(); // the selection entity groups must be reset whenever the selection changes
this.dirty = false; // set whenever the selection has changed
}
EntitySelection.prototype.getPrimaryTemplateName = function()
// Deselect everything but entities of the chosen type if the modifier is true
// otherwise deselect just the chosen entity
EntitySelection.prototype.makePrimarySelection = function(primaryIndex, modifierKey)
{
var entId = g_Selection.toList()[this.primary];
var entState = Engine.GuiInterfaceCall("GetEntityState", entId);
var ents = [];
var selection = this.toList();
if (entState)
return entState.template
return undefined;
};
EntitySelection.prototype.getPrimary = function()
if (modifierKey)
{
return this.primary;
};
var primaryEntState = Engine.GuiInterfaceCall("GetEntityState", selection[primaryIndex]);
if (!primaryEntState)
return;
EntitySelection.prototype.setPrimary = function(index)
for (var i = 0; i < selection.length; i++)
{
if (g_Selection.toList().length > index)
this.primary = index;
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[i]);
if (!entState)
return;
if (entState.template == primaryEntState.template)
ents.push(selection[i]);
}
}
else
console.write("Warning: \"index\" is larger than g_Selection.toList().length: Cannot set Primary Selection.");
};
EntitySelection.prototype.resetPrimary = function()
{
this.primary = 0; // the primary selection must be reset whenever the selection changes
};
ents.push(selection[primaryIndex]);
}
this.reset();
this.addList(ents);
}
// Get a list of the template names
EntitySelection.prototype.getTemplateNames = function()
{
var templateNames = [];
var ents = this.toList();
for each (var ent in ents)
{
var entState = Engine.GuiInterfaceCall("GetEntityState", ent);
if (entState)
templateNames.push(entState.template);
}
return templateNames;
}
// Update the selection to take care of changes (like units that have been killed)
EntitySelection.prototype.updateSelection = function()
@ -228,13 +88,13 @@ EntitySelection.prototype.updateSelection = function()
var numberRemoved = 0;
var i = 0;
for each (var unit in this.selected)
for each (var ent in this.selected)
{
var entState = Engine.GuiInterfaceCall("GetEntityState", unit);
var entState = Engine.GuiInterfaceCall("GetEntityState", ent);
if (!entState)
{
delete this.selected[unit];
delete this.selected[ent];
numberRemoved++;
}
@ -242,11 +102,7 @@ EntitySelection.prototype.updateSelection = function()
}
if (numberRemoved > 0)
{
this.dirty = true;
this.groups.createGroups(this.toList());
this.resetPrimary(); // TODO: should probably set this to a unit of the same type as the unit that was removed...
}
};
EntitySelection.prototype.toggle = function(ent)
@ -287,8 +143,6 @@ EntitySelection.prototype.reset = function()
_setHighlight(this.toList(), g_InactiveSelectionColour);
_setMotionOverlay(this.toList(), false);
this.selected = {};
this.resetPrimary();
this.groups.reset();
this.dirty = true;
};

View File

@ -1,96 +1,30 @@
const RESOURCE_ICON_CELL_IDS = {food : 0, wood : 1, stone : 2, metal : 3};
// Called by unit selection buttons
function changePrimarySelectionGroup(entType)
function layoutSelectionMultiple()
{
g_Selection.groups.setPrimary(g_Selection.groups.getGroupNumber(entType)); // set primary group
g_Selection.setPrimary(g_Selection.groups.getGroup(entType).firstOfType); // set primary selection
resetCycleIndex();
getGUIObjectByName("sdSpecific").hidden = true;
getGUIObjectByName("sdIcon").hidden = true;
getGUIObjectByName("sdStatsArea").hidden = true;
getGUIObjectByName("sdHealth").hidden = true;
getGUIObjectByName("sdStamina").hidden = true;
}
// Cycle through the units in the main icon
var cycleIndex = 0;
var displayedCycleIndex = 1;
function resetCycleIndex()
function layoutSelectionSingle(entState)
{
cycleIndex = 0;
displayedCycleIndex = 1;
}
getGUIObjectByName("sdSpecific").hidden = false;
getGUIObjectByName("sdIcon").hidden = false;
getGUIObjectByName("sdStatsArea").hidden = false;
function cycleThroughSelection()
if (entState.maxHitpoints != undefined)
getGUIObjectByName("sdHealth").hidden = false;
var player = Engine.GetPlayerID();
if (entState.player == player || g_DevSettings.controlAll)
{
var selection = g_Selection.toList();
if (selection.length > 1)
{
var primaryTemplateName = g_Selection.getPrimaryTemplateName();
var primaryIndex = g_Selection.getPrimary();
var startIndex = cycleIndex;
var endIndex = selection.length-1;
cycleIndex = ((cycleIndex < endIndex)? cycleIndex+1 : 0);
while (cycleIndex != startIndex)
{
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[cycleIndex]);
if (!entState)
return;
var equivalentTemplateNames;
if (g_GroupSelectionByRank)
equivalentTemplateNames = templatesEqualWithoutRank(primaryTemplateName, entState.template);
else
equivalentTemplateNames = (primaryTemplateName == entState.template);
if ((cycleIndex != primaryIndex) && equivalentTemplateNames)
{
var typeCount = g_Selection.groups.getGroup(entState.template).typeCount;
displayedCycleIndex = ((displayedCycleIndex < typeCount)? displayedCycleIndex+1 : 1);
g_Selection.setPrimary(cycleIndex);
break;
}
cycleIndex = ((cycleIndex < endIndex)? cycleIndex+1 : 0);
}
}
}
function reverseCycleThroughSelection()
{
var selection = g_Selection.toList();
if (selection.length > 1)
{
var primaryTemplateName = g_Selection.getPrimaryTemplateName();
var primaryIndex = g_Selection.getPrimary();
var startIndex = cycleIndex;
var endIndex = selection.length-1;
cycleIndex = ((cycleIndex > 0)? cycleIndex-1 : endIndex);
while (cycleIndex != startIndex)
{
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[cycleIndex]);
if (!entState)
return;
var equivalentTemplateNames;
if (g_GroupSelectionByRank)
equivalentTemplateNames = templatesEqualWithoutRank(primaryTemplateName, entState.template);
else
equivalentTemplateNames = (primaryTemplateName == entState.template);
if ((cycleIndex != primaryIndex) && equivalentTemplateNames)
{
var typeCount = g_Selection.groups.getGroup(entState.template).typeCount;
displayedCycleIndex = ((displayedCycleIndex > 1)? displayedCycleIndex-1 : typeCount);
g_Selection.setPrimary(cycleIndex);
break;
}
cycleIndex = ((cycleIndex > 0)? cycleIndex-1 : endIndex);
}
// if (entState.stamina != undefined)
getGUIObjectByName("sdStamina").hidden = false;
// else
// getGUIObjectByName("sdStamina").hidden = true;
}
}
@ -110,7 +44,7 @@ function displayGeneralInfo(playerState, entState, template)
rankText = (rankText? " (" + rankText + ")" : "");
// Specific Name
var name = template.name.specific + rankText; // (eliteStatus? "Elite " + template.name.specific : template.name.specific);
var name = template.name.specific + rankText;
getGUIObjectByName("sdSpecific").caption = name;
iconTooltip += "[font=\"serif-bold-16\"]" + name + "[/font]";
@ -126,20 +60,19 @@ function displayGeneralInfo(playerState, entState, template)
getGUIObjectByName("sdPlayer").textcolor = playerColor;
// Hitpoints
if (entState.hitpoints != undefined)
if (entState.maxHitpoints != undefined)
{
var healthSize = getGUIObjectByName("sdHealthBar").size;
var unitHealthBar = getGUIObjectByName("sdHealthBar");
var healthSize = unitHealthBar.size;
healthSize.rright = 100*Math.max(0, Math.min(1, entState.hitpoints / entState.maxHitpoints));
getGUIObjectByName("sdHealthBar").size = healthSize;
unitHealthBar.size = healthSize;
var tooltipHitPoints = "[font=\"serif-bold-13\"]Hitpoints [/font]" + entState.hitpoints + "/" + entState.maxHitpoints;
getGUIObjectByName("sdHealth").tooltip = tooltipHitPoints;
getGUIObjectByName("sdHealth").hidden = false;
iconTooltip += "\n" + tooltipHitPoints;
}
else
{
getGUIObjectByName("sdHealth").hidden = true;
getGUIObjectByName("sdHealth").tooltip = "";
}
@ -206,7 +139,7 @@ function updateSelectionDetails(simState)
/* If the unit has no data (e.g. it was killed), don't try displaying any
data for it. (TODO: it should probably be removed from the selection too;
also need to handle multi-unit selections) */
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[g_Selection.getPrimary()]);
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[0]);
if (!entState)
return;
@ -217,28 +150,9 @@ function updateSelectionDetails(simState)
// Choose the highest ranked version of the primary selection
// Different selection details are shown based on whether multiple units or a single unit is selected
if (selection.length > 1)
{
var typeCount = g_Selection.groups.getGroup(entState.template).typeCount;
getGUIObjectByName("sdSelectionCount").caption = ((typeCount > 1)? displayedCycleIndex + "/" + typeCount : "");
// Show cycle area if there is more than one unit of that type
if (typeCount > 1)
getGUIObjectByName("sdCycleArea").hidden = false;
layoutSelectionMultiple();
else
getGUIObjectByName("sdCycleArea").hidden = true;
// Hide stats area if there is more thanone group
if (g_Selection.groups.getLength() > 1)
getGUIObjectByName("sdStatsArea").hidden = true;
else
getGUIObjectByName("sdStatsArea").hidden = false;
}
else
{
getGUIObjectByName("sdSelectionCount").caption = "";
getGUIObjectByName("sdCycleArea").hidden = true;
getGUIObjectByName("sdStatsArea").hidden = false;
}
layoutSelectionSingle(entState);
var template = Engine.GuiInterfaceCall("GetTemplateData", entState.template);

View File

@ -139,7 +139,7 @@ function updateDebug(simState)
var selection = g_Selection.toList();
if (selection.length)
{
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[g_Selection.getPrimary()]);
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[0]);
if (entState)
{
var template = Engine.GuiInterfaceCall("GetTemplateData", entState.template);
@ -276,22 +276,3 @@ function getFormalCivName(civ)
return "Gaia";
}
}
/*
function getTemplateCategory(templateName)
{
var slashIndex = templateName.search("/");
if (slashIndex >= 0)
return templateName.substring(slashIndex+1, templateName.search("_"));
return "unknown category";
}
*/
function templatesEqualWithoutRank(templateName1, templateName2)
{
return ((templateName1.substring(0, templateName1.length-2) == templateName2.substring(0, templateName2.length-2))? true : false);
}

View File

@ -126,7 +126,7 @@
<object name="settingsTitleBar" style="wheatWindowTitleBar" type="text">Settings</object>
<object name="settingsOptions"
size="30 30 100%-30 175"
size="30 30 100%-30 150"
type="image"
style="goldPanel"
>
@ -156,11 +156,6 @@
<action on="Press">toggleDeveloperOverlay();</action>
</object>
<!-- Settings / Dev Overlay -->
<object size="0 110 100%-80 135" type="text" style="settingsText" ghost="true">Group Selections by Rank</object>
<object size="100%-56 115 100%-30 140" type="checkbox" style="wheatCrossBox" checked="true">
<action on="Press">groupSelectionByRank(this.checked);</action>
</object>
</object>
<object name="settingsOKButton"
@ -236,7 +231,7 @@
<object
name="mapAndResourcePanel"
style="sessionPanelStyle"
size="0 100%-154 272 100%"
size="0 100%-158 272 100%"
type="image"
z="30"
>
@ -296,19 +291,20 @@
<object name="selectionDetails"
type="image"
style="sessionPanelStyle"
size="277 100%-154 560 100%"
size="277 100%-158 583 100%"
hidden="true"
z="20"
>
<!-- Unit Selection Area -->
<object name="unitSelectionPanel"
size="92 30 274 56"
size="6 6 274 56"
>
<object size="0 0 100% 47">
<repeat count="24">
<repeat count="32">
<object name="unitSelectionButton[n]" hidden="true" style="iconButton" type="button" size="0 0 36 36">
<object name="unitSelectionIcon[n]" type="image" ghost="true" size="3 3 34 34"/>
<object name="unitSelectionCount[n]" ghost="true" style="groupIconsText" type="text"/>
<object size="0 100%-3 100% 100%" name="unitSelectionHealthBackground[n]" type="image" sprite="sdHealthBackground" ghost="true"/>
<object size="0 100%-3 100% 100%" name="unitSelectionHealthForeground[n]" type="image" sprite="sdHealthForeground" ghost="true"/>
</object>
</repeat>
</object>
@ -321,19 +317,6 @@
<object size="100%-24 -6 100%+6 24" name="sdRankIcon" type="image" cell_id="0" sprite="snIconSheetRank" ghost="true"/>
</object>
<!-- Cycle through units area -->
<object size= "6 120 86 136" name="sdCycleArea" type="image" sprite="menuBackground">
<object name="sdIconButtonReverse" style="wheatArrowDn" type="button" size="0 0 16 16">
<action on="Press">reverseCycleThroughSelection();</action>
</object>
<object name="sdSelectionCount" ghost="true" style="groupIconsCenteredText" type="text"/>
<object name="sdIconButtonForward" style="wheatArrowUp" type="button" size="100%-16 0 100% 16">
<action on="Press">cycleThroughSelection();</action>
</object>
</object>
<!-- Health bar -->
<object size="6 112 86 118" type="image" name="sdHealth" tooltip="Hitpoints" tooltip_style="snToolTip">
<object type="image" sprite="sdHealthBackground" ghost="true"/>
@ -346,11 +329,8 @@
<object type="image" sprite="sdStaminaForeground" ghost="true" name="sdStaminaBar"/>
</object>
<!-- Details text -->
<object size="6 0 100% 24" name="sdMainText" type="image">
<object size="-4 0 100% 26" name="sdSpecific" type="text" style="leftAlignedText" font="serif-bold-18" tooltip_style="snToolTip"/>
<object hidden="true" size="0 20 100% 40" name="sdGeneric" type="text" font="serif-14"/>
</object>
<!-- Specific Name -->
<object size="0 0 100% 26" name="sdSpecific" type="text" style="leftAlignedText" font="serif-bold-18" tooltip_style="snToolTip"/>
<!-- Stats -->
<object size="86 30 100% 100%" name="sdStatsArea" type="image">
@ -376,14 +356,6 @@
</object>
</object>
<!-- Commands
<object size="90 100%-30 100% 100%-10" type="image" name="sdCommands" tooltip="Commands" tooltip_style="snToolTip">
<object name="commandsDeleteButton" style="iconButton" type="button" size="100%-48 0 100%-24 24">
<object size="0 0 24 24" name="sdCommandsDelete" type="image" style="commandsIcon" cell_id="4"/>
<action on="Press">deleteUnit()</action>
</object>
</object>
-->
</object>
<!-- ================================ ================================ -->
@ -392,20 +364,20 @@
<object name="unitCommands"
type="image"
style="sessionPanelStyle"
size="565 100%-154 1024 100%"
size="588 100%-158 1024 100%"
hidden="true"
z="50"
>
<object name="unitConstructionPanel"
size="0 3 100% 100%"
size="0 6 100% 100%"
>
<object size="-2 -2 54 54" type="image" sprite="snIconSheetTab" tooltip_style="snToolTip"
cell_id="0" tooltip="Construction"/>
<object size="54 0 100% 50">
<repeat count="24">
<object name="unitConstructionButton[n]" hidden="true" style="iconButton" type="button" size="0 0 48 48">
<object name="unitConstructionIcon[n]" type="image" ghost="true" size="3 3 45 45"/>
<object name="unitConstructionButton[n]" hidden="true" style="iconButton" type="button" size="0 0 45 45">
<object name="unitConstructionIcon[n]" type="image" ghost="true" size="3 3 42 42"/>
</object>
</repeat>
</object>
@ -445,15 +417,15 @@
</object>
<object name="unitTrainingPanel"
size="0 3 100% 100%"
size="0 6 100% 100%"
>
<object size="-2 -2 54 54" type="image" sprite="snIconSheetTab" tooltip_style="snToolTip"
cell_id="2" tooltip="Training"/>
<object size="54 0 100% 50">
<repeat count="24">
<object name="unitTrainingButton[n]" hidden="true" style="iconButton" type="button" size="0 0 48 48">
<object name="unitTrainingIcon[n]" type="image" ghost="true" size="3 3 45 45"/>
<object name="unitTrainingButton[n]" hidden="true" style="iconButton" type="button" size="0 0 45 45">
<object name="unitTrainingIcon[n]" type="image" ghost="true" size="3 3 42 42"/>
</object>
</repeat>
</object>
@ -461,7 +433,7 @@
<object name="unitQueuePanel"
style="sessionPanelStyle"
size="0 -63 100% 100%-164"
size="0 -56 100% 100%-164"
type="image"
>
<object size="-2 -2 54 54" type="image" sprite="snIconSheetTab" tooltip_style="snToolTip"
@ -469,8 +441,8 @@
<object size="54 3 100% 100%">
<repeat count="24">
<object name="unitQueueButton[n]" hidden="true" style="iconButton" type="button" size="0 0 48 48">
<object name="unitQueueIcon[n]" ghost="true" type="image" size="3 3 45 45"/>
<object name="unitQueueButton[n]" hidden="true" style="iconButton" type="button" size="0 0 45 45">
<object name="unitQueueIcon[n]" ghost="true" type="image" size="3 3 42 42"/>
<object name="unitQueueCount[n]" ghost="true" style="iconButtonCount" type="text"/>
<object name="unitQueueProgress[n]" ghost="true" style="iconButtonProgress" type="text"/>
</object>

View File

@ -1,5 +1,6 @@
// The height of a Queue or Garrison panel
const UNIT_PANEL_HEIGHT = 63;
// Constants used by the Queue or Garrison panel
const UNIT_PANEL_BASE = -56; // The offset above the main panel (will often be negative)
const UNIT_PANEL_HEIGHT = 47; // The height needed for a row of buttons
// The number of currently visible buttons (used to optimise showing/hiding)
var g_unitPanelButtons = { "Construction": 0, "Training": 0, "Queue": 0, "Selection": 0 };
@ -32,13 +33,15 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
{
usedPanels[guiName] = 1;
var i = 0;
var selection = g_Selection.toList();
for each (var item in items)
{
if (i > 23) // End loop early if there are more than 24 buttons
// End loop early if there too many buttons
if ((guiName != "Selection") && (i > 23))
break;
else if (i > 31)
break;
else if (guiName == "Selection" && i > 14) // End loop early if more then 16 selection buttons
break
// Get templates
var entType;
@ -54,7 +57,7 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
// Name
var name;
if (guiName == "Selection")
name = template.name.specific || template.name.generic || "???";
name = "[font=\"serif-bold-16\"]" + (template.name.specific || template.name.generic || "???") + "[/font]";
else
name = getFullName(template);
@ -63,16 +66,23 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
if (guiName == "Selection")
{
var typeCount = g_Selection.groups.getGroup(item).typeCount;
var entState = Engine.GuiInterfaceCall("GetEntityState", selection[i]);
if (!entState)
return;
if (typeCount > 1)
// Rank Title
var rankText = getRankTitle(getRankCellId(entState.template));
rankText = (rankText? " [font=\"serif-bold-16\"](" + rankText + ")[/font]" : "" );
tooltip += rankText;
// Hitpoints
if (entState.maxHitpoints != undefined)
{
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = typeCount;
tooltip += " (" + typeCount + ")";
}
else
{
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = "";
var unitHealthBar = getGUIObjectByName("unitSelectionHealthForeground[" + i + "]");
var healthSize = unitHealthBar.size;
healthSize.rright = 100*Math.max(0, Math.min(1, entState.hitpoints / entState.maxHitpoints));
unitHealthBar.size = healthSize;
tooltip += " [font=\"serif-9\"](" + entState.hitpoints + "/" + entState.maxHitpoints + ")[/font]";
}
}
else if (guiName == "Queue")
@ -104,23 +114,15 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
}
}
// Ignore this button because it is already featured on the big primary icon
if (guiName == "Selection")
{
if (g_GroupSelectionByRank && templatesEqualWithoutRank(g_Selection.getPrimaryTemplateName(), item))
continue;
else if (g_Selection.getPrimaryTemplateName() == item)
continue;
}
// Button
var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]");
var icon = getGUIObjectByName("unit"+guiName+"Icon["+i+"]");
button.hidden = false;
button.tooltip = tooltip;
if (callback != null)
button.onpress = (function(e) { return function() { callback(e) } })(item); // (need nested functions to get the closure right)
// Button Function
var parameter = ((guiName == "Selection")? i : item);
button.onpress = (function(e) { return function() { callback(e) } })(parameter); // (need nested functions to get the closure right)
// Get icon sheet
icon.sprite = template.icon_sheet;
@ -135,7 +137,7 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
// Position the visible buttons (TODO: if there's lots, maybe they should be squeezed together to fit)
var numButtons = i;
var rowLength = ((guiName == "Selection")? 5 : 8);
var rowLength = 8;
var numRows = ceiling(numButtons / rowLength);
var buttonSideLength = getGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
var buttonSpacer = ((guiName == "Selection")? buttonSideLength+1 : buttonSideLength+2);
@ -145,7 +147,7 @@ function setupUnitPanel(guiName, usedPanels, playerState, unitEntState, items, c
{
var panel = getGUIObjectByName("unitQueuePanel");
var size = panel.size;
size.top = (-UNIT_PANEL_HEIGHT - ((numRows-1)*50));
size.top = (UNIT_PANEL_BASE - ((numRows-1)*UNIT_PANEL_HEIGHT));
panel.size = size;
}
@ -193,15 +195,9 @@ function updateUnitCommands(playerState, entState, commandsPanel, selection)
function (item) { removeFromTrainingQueue(entState.id, item.id); } );
if (selection.length > 1)
setupUnitPanel("Selection", usedPanels, playerState, entState, g_Selection.groups.getTemplateNames(),
setupUnitPanel("Selection", usedPanels, playerState, entState, g_Selection.getTemplateNames(),
function (entType) { changePrimarySelectionGroup(entType); } );
// Stamina
if (entState.stamina != undefined)
getGUIObjectByName("sdStamina").hidden = false;
else
getGUIObjectByName("sdStamina").hidden = true;
commandsPanel.hidden = false;
}
else