Merge pull request #8483 from matija-hustic/selectall_fixed

Fixes regression with selection classes
This commit is contained in:
Pavel Penev
2015-06-25 16:51:13 +03:00
4 changed files with 76 additions and 57 deletions

View File

@@ -156,6 +156,7 @@
<Compile Include="Primitives\MergedStream.cs" /> <Compile Include="Primitives\MergedStream.cs" />
<Compile Include="Primitives\SpatiallyPartitioned.cs" /> <Compile Include="Primitives\SpatiallyPartitioned.cs" />
<Compile Include="Primitives\ConcurrentCache.cs" /> <Compile Include="Primitives\ConcurrentCache.cs" />
<Compile Include="SelectableExts.cs" />
<Compile Include="Selection.cs" /> <Compile Include="Selection.cs" />
<Compile Include="Server\Connection.cs" /> <Compile Include="Server\Connection.cs" />
<Compile Include="Server\Exts.cs" /> <Compile Include="Server\Exts.cs" />

View File

@@ -162,23 +162,4 @@ namespace OpenRA.Orders
} }
} }
} }
public static class SelectableExts
{
public static int SelectionPriority(this ActorInfo a)
{
var selectableInfo = a.Traits.GetOrDefault<SelectableInfo>();
return selectableInfo != null ? selectableInfo.Priority : int.MinValue;
}
public static Actor WithHighestSelectionPriority(this IEnumerable<Actor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
public static FrozenActor WithHighestSelectionPriority(this IEnumerable<FrozenActor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
}
} }

View File

@@ -0,0 +1,67 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Traits
{
public static class SelectableExts
{
public static int SelectionPriority(this ActorInfo a)
{
var selectableInfo = a.Traits.GetOrDefault<SelectableInfo>();
return selectableInfo != null ? selectableInfo.Priority : int.MinValue;
}
const int PriorityRange = 30;
public static int SelectionPriority(this Actor a)
{
var basePriority = a.Info.Traits.Get<SelectableInfo>().Priority;
var lp = a.World.LocalPlayer;
if (a.Owner == lp || lp == null)
return basePriority;
switch (lp.Stances[a.Owner])
{
case Stance.Ally: return basePriority - PriorityRange;
case Stance.Neutral: return basePriority - 2 * PriorityRange;
case Stance.Enemy: return basePriority - 3 * PriorityRange;
default:
throw new InvalidOperationException();
}
}
public static Actor WithHighestSelectionPriority(this IEnumerable<Actor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
public static FrozenActor WithHighestSelectionPriority(this IEnumerable<FrozenActor> actors)
{
return actors.MaxByOrDefault(a => a.Info.SelectionPriority());
}
static readonly Actor[] NoActors = { };
public static IEnumerable<Actor> SubsetWithHighestSelectionPriority(this IEnumerable<Actor> actors)
{
return actors.GroupBy(x => x.SelectionPriority())
.OrderByDescending(g => g.Key)
.Select(g => g.AsEnumerable())
.DefaultIfEmpty(NoActors)
.FirstOrDefault();
}
}
}

View File

@@ -8,7 +8,6 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
@@ -22,8 +21,6 @@ namespace OpenRA.Widgets
{ {
public class WorldInteractionControllerWidget : Widget public class WorldInteractionControllerWidget : Widget
{ {
static readonly Actor[] NoActors = { };
protected readonly World World; protected readonly World World;
readonly WorldRenderer worldRenderer; readonly WorldRenderer worldRenderer;
int2? dragStart, dragEnd; int2? dragStart, dragEnd;
@@ -238,7 +235,7 @@ namespace OpenRA.Widgets
else if (key == Game.Settings.Keys.SelectAllUnitsKey) else if (key == Game.Settings.Keys.SelectAllUnitsKey)
{ {
// Select actors on the screen which belong to the current player // Select actors on the screen which belong to the current player
var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, player); var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, player).SubsetWithHighestSelectionPriority();
World.Selection.Combine(World, ownUnitsOnScreen, false, false); World.Selection.Combine(World, ownUnitsOnScreen, false, false);
} }
else if (key == Game.Settings.Keys.SelectUnitsByTypeKey) else if (key == Game.Settings.Keys.SelectUnitsByTypeKey)
@@ -275,23 +272,24 @@ namespace OpenRA.Widgets
static IEnumerable<Actor> SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable<string> selectionClasses, Player player) static IEnumerable<Actor> SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable<string> selectionClasses, Player player)
{ {
return SelectActorsByPlayerByClass(world.ScreenMap.ActorsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight), selectionClasses, player); return SelectActorsByOwnerAndSelectionClass(world.ScreenMap.ActorsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight), player, selectionClasses);
} }
static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, Player player) static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, Player player)
{ {
return SelectActorsByPlayerByClass(world.ActorMap.ActorsInWorld(), selectionClasses, player); return SelectActorsByOwnerAndSelectionClass(world.ActorMap.ActorsInWorld(), player, selectionClasses);
} }
static IEnumerable<Actor> SelectActorsByPlayerByClass(IEnumerable<Actor> actors, IEnumerable<string> selectionClasses, Player player) static IEnumerable<Actor> SelectActorsByOwnerAndSelectionClass(IEnumerable<Actor> actors, Player owner, IEnumerable<string> selectionClasses)
{ {
return actors.Where(a => return actors.Where(a =>
{ {
if (a.Owner != player) if (a.Owner != owner)
return false; return false;
var s = a.TraitOrDefault<Selectable>(); var s = a.TraitOrDefault<Selectable>();
// sc == null means that units, that meet all other criteria, get selected // selectionClasses == null means that units, that meet all other criteria, get selected
return s != null && (selectionClasses == null || selectionClasses.Contains(s.Class)); return s != null && (selectionClasses == null || selectionClasses.Contains(s.Class));
}); });
} }
@@ -304,11 +302,7 @@ namespace OpenRA.Widgets
return world.ScreenMap.ActorsInBox(a, b) return world.ScreenMap.ActorsInBox(a, b)
.Where(x => x.HasTrait<Selectable>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x))) .Where(x => x.HasTrait<Selectable>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
.GroupBy(x => x.GetSelectionPriority()) .SubsetWithHighestSelectionPriority();
.OrderByDescending(g => g.Key)
.Select(g => g.AsEnumerable())
.DefaultIfEmpty(NoActors)
.FirstOrDefault();
} }
bool ToggleStatusBars() bool ToggleStatusBars()
@@ -324,28 +318,4 @@ namespace OpenRA.Widgets
return true; return true;
} }
} }
static class PriorityExts
{
const int PriorityRange = 30;
public static int GetSelectionPriority(this Actor a)
{
var basePriority = a.Info.Traits.Get<SelectableInfo>().Priority;
var lp = a.World.LocalPlayer;
if (a.Owner == lp || lp == null)
return basePriority;
switch (lp.Stances[a.Owner])
{
case Stance.Ally: return basePriority - PriorityRange;
case Stance.Neutral: return basePriority - 2 * PriorityRange;
case Stance.Enemy: return basePriority - 3 * PriorityRange;
default:
throw new InvalidOperationException();
}
}
}
} }