Change the way we filter out selected entities when we draw a selection box. Add a hotkey to allow selecting only idle units.

Patch by Rolf Sievers, fixes #2407.

This was SVN commit r16007.
This commit is contained in:
Itms
2014-11-24 16:46:05 +00:00
parent 882c1383e1
commit 347ffabaeb
3 changed files with 73 additions and 70 deletions
+1
View File
@@ -225,6 +225,7 @@ toggle = "Ctrl+F11" ; Enable/disable HTTP/GPU modes for new profiler
[hotkey.selection] [hotkey.selection]
add = Shift ; Add units to selection add = Shift ; Add units to selection
milonly = Alt ; Add only military units to selection milonly = Alt ; Add only military units to selection
idleonly = "I" ; Select only idle units
remove = Ctrl ; Remove units from selection remove = Ctrl ; Remove units from selection
cancel = Esc ; Un-select all units and cancel building placement cancel = Esc ; Un-select all units and cancel building placement
idleworker = Period ; Select next idle worker idleworker = Period ; Select next idle worker
+71 -70
View File
@@ -437,44 +437,76 @@ function tryPlaceWall(queued)
return true; return true;
} }
// Limits bandboxed selections to certain types of entities based on priority // Updates the bandbox object with new positions and visibility.
function getPreferredEntities(ents) // The coordinates [x0, y0, x1, y1] are returned for further use.
function updateBandbox(bandbox, ev, hidden)
{ {
var entStateList = []; var x0 = dragStart[0];
var preferredEnts = []; var y0 = dragStart[1];
var x1 = ev.x;
var y1 = ev.y;
// normalize the orientation of the rectangle
if (x0 > x1) { let t = x0; x0 = x1; x1 = t; }
if (y0 > y1) { let t = y0; y0 = y1; y1 = t; }
// Check if there are units in the selection and get a list of entity states bandbox.size = [x0, y0, x1, y1].join(" ");
for each (var ent in ents) bandbox.hidden = hidden;
{
var entState = GetEntityState(ent);
if (!entState)
continue;
if (hasClass(entState, "Unit"))
preferredEnts.push(ent);
entStateList.push(entState); return [x0, y0, x1, y1];
}
// If there are no units, check if there are defensive entities in the selection
if (!preferredEnts.length)
for (var i = 0; i < ents.length; i++)
if (hasClass(entStateList[i], "Defensive"))
preferredEnts.push(ents[i]);
return preferredEnts;
} }
// Removes any support units from the passed list of entities // Define some useful unit filters for getPreferredEntities
function getMilitaryEntities(ents) var unitFilters = {
{ "isUnit": function (entity) {
var militaryEnts = []; var entState = GetEntityState(entity);
for each (var ent in ents) if (!entState)
{ return false;
var entState = GetEntityState(ent); return hasClass(entState, "Unit");
if (!hasClass(entState, "Support")) },
militaryEnts.push(ent); "isDefensive": function (entity) {
var entState = GetEntityState(entity);
if (!entState)
return false;
return hasClass(entState, "Defensive");
},
"isNotSupport": function (entity) {
var entState = GetEntityState(entity);
if (!entState)
return false;
return hasClass(entState, "Unit") && !hasClass(entState, "Support");
},
"isIdle": function (entity) {
var entState = GetEntityState(entity);
if (!entState)
return false;
return hasClass(entState, "Unit") && entState.unitAI.isIdle;
},
"isAnything": function (entity) {
return true;
} }
return militaryEnts; };
// Choose, inside a list of entities, which ones will be selected.
// We may use several entity filters, until one returns at least one element.
function getPreferredEntities(ents)
{
// Default filters
var filters = [unitFilters.isUnit, unitFilters.isDefensive, unitFilters.isAnything];
// Handle hotkeys
if (Engine.HotkeyIsPressed("selection.milonly"))
filters = [unitFilters.isNotSupport];
if (Engine.HotkeyIsPressed("selection.idleonly"))
filters = [unitFilters.isIdle];
var preferredEnts = [];
for (var i = 0; i < filters.length; ++i)
{
preferredEnts = ents.filter(filters[i]);
if (preferredEnts.length > 0)
break;
}
return preferredEnts;
} }
function handleInputBeforeGui(ev, hoveredObject) function handleInputBeforeGui(ev, hoveredObject)
@@ -511,55 +543,25 @@ function handleInputBeforeGui(ev, hoveredObject)
switch (inputState) switch (inputState)
{ {
case INPUT_BANDBOXING: case INPUT_BANDBOXING:
var bandbox = Engine.GetGUIObjectByName("bandbox");
switch (ev.type) switch (ev.type)
{ {
case "mousemotion": case "mousemotion":
var x0 = dragStart[0]; var rect = updateBandbox(bandbox, ev, false);
var y0 = dragStart[1];
var x1 = ev.x;
var y1 = ev.y;
if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
var bandbox = Engine.GetGUIObjectByName("bandbox"); var ents = Engine.PickFriendlyEntitiesInRect(rect[0], rect[1], rect[2], rect[3], Engine.GetPlayerID());
bandbox.size = [x0, y0, x1, y1].join(" "); var preferredEntities = getPreferredEntities(ents);
bandbox.hidden = false; g_Selection.setHighlightList(preferredEntities);
// TODO: Should we handle "control all units" here as well?
var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID());
g_Selection.setHighlightList(ents);
return false; return false;
case "mousebuttonup": case "mousebuttonup":
if (ev.button == SDL_BUTTON_LEFT) if (ev.button == SDL_BUTTON_LEFT)
{ {
var x0 = dragStart[0]; var rect = updateBandbox(bandbox, ev, true);
var y0 = dragStart[1];
var x1 = ev.x;
var y1 = ev.y;
if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
var bandbox = Engine.GetGUIObjectByName("bandbox");
bandbox.hidden = true;
// Get list of entities limited to preferred entities // Get list of entities limited to preferred entities
// TODO: Should we handle "control all units" here as well? var ents = getPreferredEntities(Engine.PickFriendlyEntitiesInRect(rect[0], rect[1], rect[2], rect[3], Engine.GetPlayerID()));
var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID());
var preferredEntities = getPreferredEntities(ents)
if (preferredEntities.length)
{
ents = preferredEntities;
if (Engine.HotkeyIsPressed("selection.milonly"))
{
var militaryEntities = getMilitaryEntities(ents);
if (militaryEntities.length)
ents = militaryEntities;
}
}
// Remove the bandbox hover highlighting // Remove the bandbox hover highlighting
g_Selection.setHighlightList([]); g_Selection.setHighlightList([]);
@@ -585,7 +587,6 @@ function handleInputBeforeGui(ev, hoveredObject)
else if (ev.button == SDL_BUTTON_RIGHT) else if (ev.button == SDL_BUTTON_RIGHT)
{ {
// Cancel selection // Cancel selection
var bandbox = Engine.GetGUIObjectByName("bandbox");
bandbox.hidden = true; bandbox.hidden = true;
g_Selection.setHighlightList([]); g_Selection.setHighlightList([]);
@@ -333,6 +333,7 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
"canGuard": cmpUnitAI.CanGuard(), "canGuard": cmpUnitAI.CanGuard(),
"isGuarding": cmpUnitAI.IsGuardOf(), "isGuarding": cmpUnitAI.IsGuardOf(),
"possibleStances": cmpUnitAI.GetPossibleStances(), "possibleStances": cmpUnitAI.GetPossibleStances(),
"isIdle":cmpUnitAI.IsIdle(),
}; };
// Add some information needed for ungarrisoning // Add some information needed for ungarrisoning
if (cmpUnitAI.IsGarrisoned() && ret.player !== undefined) if (cmpUnitAI.IsGarrisoned() && ret.player !== undefined)