2010-03-11 21:01:16 +01:00
|
|
|
var g_ActiveSelectionColour = { r:1, g:1, b:1, a:1 };
|
|
|
|
var g_HighlightSelectionColour = { r:1, g:1, b:1, a:0.5 };
|
|
|
|
var g_InactiveSelectionColour = { r:1, g:1, b:1, a:0 };
|
2010-01-09 20:20:14 +01:00
|
|
|
|
2010-03-11 21:01:16 +01:00
|
|
|
function _setHighlight(ents, colour)
|
|
|
|
{
|
2010-05-01 18:20:58 +02:00
|
|
|
if (ents.length)
|
|
|
|
Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "colour":colour });
|
2010-03-11 21:01:16 +01:00
|
|
|
}
|
2010-01-09 20:20:14 +01:00
|
|
|
|
2010-04-30 01:36:05 +02:00
|
|
|
function _setMotionOverlay(ents, enabled)
|
|
|
|
{
|
2010-05-01 18:20:58 +02:00
|
|
|
if (ents.length)
|
|
|
|
Engine.GuiInterfaceCall("SetMotionDebugOverlay", { "entities":ents, "enabled":enabled });
|
2010-04-30 01:36:05 +02:00
|
|
|
}
|
|
|
|
|
2010-06-26 20:10:03 +02:00
|
|
|
//-------------------------------- -------------------------------- --------------------------------
|
|
|
|
// EntityGroups class for ordering / managing entities by their templates
|
|
|
|
//-------------------------------- -------------------------------- --------------------------------
|
|
|
|
function EntityGroups()
|
|
|
|
{
|
2010-07-19 23:23:12 +02:00
|
|
|
// private properties
|
2010-06-26 20:10:03 +02:00
|
|
|
this.primary = 0;
|
2010-07-19 23:23:12 +02:00
|
|
|
this.groups = []; // Includes only highest ranked versions of each type
|
2010-06-26 20:10:03 +02:00
|
|
|
}
|
|
|
|
|
2010-07-19 23:23:12 +02:00
|
|
|
EntityGroups.prototype.Group = function(templateName, typeCount, firstOfType)
|
|
|
|
{
|
|
|
|
this.templateName = templateName;
|
|
|
|
this.typeCount = typeCount;
|
|
|
|
this.firstOfType = firstOfType;
|
|
|
|
};
|
|
|
|
|
2010-06-26 20:10:03 +02:00
|
|
|
EntityGroups.prototype.reset = function()
|
|
|
|
{
|
|
|
|
this.primary = 0;
|
2010-07-19 23:23:12 +02:00
|
|
|
this.groups = [];
|
|
|
|
};
|
|
|
|
|
|
|
|
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 + "\"");
|
2010-07-21 20:51:27 +02:00
|
|
|
return undefined;
|
2010-07-19 23:23:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
2010-06-26 20:10:03 +02:00
|
|
|
};
|
|
|
|
|
2010-07-19 23:23:12 +02:00
|
|
|
EntityGroups.prototype.getGroupNumber = function(templateName)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.groups.length; i++)
|
|
|
|
if (this.groups[i].templateName == templateName)
|
|
|
|
return i;
|
2010-07-21 20:51:27 +02:00
|
|
|
|
|
|
|
return -1;
|
2010-07-19 23:23:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2010-06-26 20:10:03 +02:00
|
|
|
//-------------------------------- -------------------------------- --------------------------------
|
|
|
|
// EntitySelection class for managing the entity selection list and the primary selection
|
|
|
|
//-------------------------------- -------------------------------- --------------------------------
|
2010-03-11 21:01:16 +01:00
|
|
|
function EntitySelection()
|
2010-01-25 23:31:43 +01:00
|
|
|
{
|
2010-05-01 18:20:58 +02:00
|
|
|
// Private properties:
|
2010-06-26 20:10:03 +02:00
|
|
|
//--------------------------------
|
|
|
|
this.primary = 0; // The active selection in the unit details panel
|
2010-05-09 15:56:06 +02:00
|
|
|
this.selected = {}; // { id:id, id:id, ... } for each selected entity ID 'id'
|
2010-06-26 20:10:03 +02:00
|
|
|
|
|
|
|
// { id:id, ... } for mouseover-highlighted entity IDs in these, the key is a string and the value is an int;
|
|
|
|
// we want to use the int form wherever possible since it's more efficient to send to the simulation code)
|
|
|
|
this.highlighted = {};
|
|
|
|
|
2010-04-30 01:36:05 +02:00
|
|
|
this.motionDebugOverlay = false;
|
2010-05-01 18:20:58 +02:00
|
|
|
|
|
|
|
// Public properties:
|
2010-06-26 20:10:03 +02:00
|
|
|
//--------------------------------
|
|
|
|
this.groups = new EntityGroups(); // the selection entity groups must be reset whenever the selection changes
|
2010-05-01 18:20:58 +02:00
|
|
|
this.dirty = false; // set whenever the selection has changed
|
2010-01-25 23:31:43 +01:00
|
|
|
}
|
|
|
|
|
2010-07-19 23:23:12 +02:00
|
|
|
EntitySelection.prototype.getPrimaryTemplateName = function()
|
|
|
|
{
|
|
|
|
var entId = g_Selection.toList()[this.primary];
|
|
|
|
var entState = Engine.GuiInterfaceCall("GetEntityState", entId);
|
|
|
|
|
|
|
|
if (entState)
|
|
|
|
return entState.template
|
2010-07-21 20:51:27 +02:00
|
|
|
|
|
|
|
return undefined;
|
2010-07-19 23:23:12 +02:00
|
|
|
};
|
|
|
|
|
2010-06-26 20:10:03 +02:00
|
|
|
EntitySelection.prototype.getPrimary = function()
|
|
|
|
{
|
|
|
|
return this.primary;
|
|
|
|
};
|
|
|
|
|
|
|
|
EntitySelection.prototype.setPrimary = function(index)
|
|
|
|
{
|
|
|
|
if (g_Selection.toList().length > index)
|
|
|
|
this.primary = index;
|
|
|
|
else
|
2010-07-19 23:23:12 +02:00
|
|
|
console.write("Warning: \"index\" is larger than g_Selection.toList().length: Cannot set Primary Selection.");
|
2010-06-26 20:10:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
EntitySelection.prototype.resetPrimary = function()
|
|
|
|
{
|
|
|
|
this.primary = 0; // the primary selection must be reset whenever the selection changes
|
|
|
|
};
|
|
|
|
|
2010-07-04 03:03:14 +02:00
|
|
|
// Update the selection to take care of changes (like units that have been killed)
|
|
|
|
EntitySelection.prototype.updateSelection = function()
|
|
|
|
{
|
|
|
|
var numberRemoved = 0;
|
|
|
|
var i = 0;
|
|
|
|
|
|
|
|
for each (var unit in this.selected)
|
|
|
|
{
|
|
|
|
var entState = Engine.GuiInterfaceCall("GetEntityState", unit);
|
|
|
|
|
|
|
|
if (!entState)
|
|
|
|
{
|
|
|
|
delete this.selected[unit];
|
|
|
|
numberRemoved++;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numberRemoved > 0)
|
|
|
|
{
|
|
|
|
this.dirty = true;
|
2010-07-19 23:23:12 +02:00
|
|
|
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...
|
2010-07-04 03:03:14 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-11 21:01:16 +01:00
|
|
|
EntitySelection.prototype.toggle = function(ent)
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
if (this.selected[ent])
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
_setHighlight([ent], g_InactiveSelectionColour);
|
2010-04-30 01:36:05 +02:00
|
|
|
_setMotionOverlay([ent], false);
|
2010-03-11 21:01:16 +01:00
|
|
|
delete this.selected[ent];
|
2010-01-09 20:20:14 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
_setHighlight([ent], g_ActiveSelectionColour);
|
2010-04-30 01:36:05 +02:00
|
|
|
_setMotionOverlay([ent], this.motionDebugOverlay);
|
2010-05-09 15:56:06 +02:00
|
|
|
this.selected[ent] = ent;
|
2010-01-09 20:20:14 +01:00
|
|
|
}
|
2010-05-01 18:20:58 +02:00
|
|
|
this.dirty = true;
|
2010-03-11 21:01:16 +01:00
|
|
|
};
|
2010-01-09 20:20:14 +01:00
|
|
|
|
2010-03-11 21:01:16 +01:00
|
|
|
EntitySelection.prototype.addList = function(ents)
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
var added = [];
|
2010-01-09 20:20:14 +01:00
|
|
|
for each (var ent in ents)
|
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
if (!this.selected[ent])
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
added.push(ent);
|
2010-05-09 15:56:06 +02:00
|
|
|
this.selected[ent] = ent;
|
2010-01-09 20:20:14 +01:00
|
|
|
}
|
|
|
|
}
|
2010-03-11 21:01:16 +01:00
|
|
|
_setHighlight(added, g_ActiveSelectionColour);
|
2010-04-30 01:36:05 +02:00
|
|
|
_setMotionOverlay(added, this.motionDebugOverlay);
|
2010-05-01 18:20:58 +02:00
|
|
|
this.dirty = true;
|
2010-03-11 21:01:16 +01:00
|
|
|
};
|
2010-01-09 20:20:14 +01:00
|
|
|
|
2010-03-11 21:01:16 +01:00
|
|
|
EntitySelection.prototype.reset = function()
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
2010-03-11 21:01:16 +01:00
|
|
|
_setHighlight(this.toList(), g_InactiveSelectionColour);
|
2010-04-30 01:36:05 +02:00
|
|
|
_setMotionOverlay(this.toList(), false);
|
2010-03-11 21:01:16 +01:00
|
|
|
this.selected = {};
|
2010-06-26 20:10:03 +02:00
|
|
|
this.resetPrimary();
|
|
|
|
this.groups.reset();
|
2010-05-01 18:20:58 +02:00
|
|
|
this.dirty = true;
|
2010-03-11 21:01:16 +01:00
|
|
|
};
|
2010-01-09 20:20:14 +01:00
|
|
|
|
2010-03-11 21:01:16 +01:00
|
|
|
EntitySelection.prototype.toList = function()
|
2010-01-09 20:20:14 +01:00
|
|
|
{
|
|
|
|
var ents = [];
|
2010-05-09 15:56:06 +02:00
|
|
|
for each (var ent in this.selected)
|
|
|
|
ents.push(ent);
|
2010-01-09 20:20:14 +01:00
|
|
|
return ents;
|
2010-03-11 21:01:16 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
EntitySelection.prototype.setHighlightList = function(ents)
|
|
|
|
{
|
|
|
|
var removed = [];
|
|
|
|
var added = [];
|
|
|
|
|
|
|
|
// Remove highlighting for the old units (excluding ones that are actively selected too)
|
2010-05-09 15:56:06 +02:00
|
|
|
for each (var ent in this.highlighted)
|
2010-03-11 21:01:16 +01:00
|
|
|
if (!this.selected[ent])
|
|
|
|
removed.push(ent);
|
|
|
|
|
|
|
|
// Add new highlighting
|
|
|
|
for each (var ent in ents)
|
|
|
|
if (!this.selected[ent])
|
|
|
|
added.push(ent);
|
|
|
|
|
|
|
|
_setHighlight(removed, g_InactiveSelectionColour);
|
|
|
|
_setHighlight(added, g_HighlightSelectionColour);
|
|
|
|
|
|
|
|
// TODO: this could be a bit more efficient by only changing the ones that
|
|
|
|
// have entered/left the highlight list
|
|
|
|
|
|
|
|
// Store the new list
|
|
|
|
this.highlighted = {};
|
|
|
|
for each (var ent in ents)
|
2010-05-09 15:56:06 +02:00
|
|
|
this.highlighted[ent] = ent;
|
2010-03-11 21:01:16 +01:00
|
|
|
};
|
|
|
|
|
2010-04-30 01:36:05 +02:00
|
|
|
EntitySelection.prototype.SetMotionDebugOverlay = function(enabled)
|
|
|
|
{
|
|
|
|
this.motionDebugOverlay = enabled;
|
|
|
|
_setMotionOverlay(this.toList(), enabled);
|
|
|
|
};
|
2010-03-11 21:01:16 +01:00
|
|
|
|
|
|
|
var g_Selection = new EntitySelection();
|