Introduce IMouseBounds and split/rework mouse rectangles.
The render bounds for an actor now include the area covered by bibs, shadows, and any other widgets. In many cases this area is much larger than we really want to consider for tooltips and mouse selection. An optional Margin is added to Selectable to support cases like infantry, where we want the mouse area of the actor to be larger than the drawn selection box.
This commit is contained in:
@@ -77,6 +77,7 @@ namespace OpenRA
|
|||||||
readonly IHealth health;
|
readonly IHealth health;
|
||||||
readonly IRenderModifier[] renderModifiers;
|
readonly IRenderModifier[] renderModifiers;
|
||||||
readonly IRender[] renders;
|
readonly IRender[] renders;
|
||||||
|
readonly IMouseBounds[] mouseBounds;
|
||||||
readonly IDisable[] disables;
|
readonly IDisable[] disables;
|
||||||
readonly IVisibilityModifier[] visibilityModifiers;
|
readonly IVisibilityModifier[] visibilityModifiers;
|
||||||
readonly IDefaultVisibility defaultVisibility;
|
readonly IDefaultVisibility defaultVisibility;
|
||||||
@@ -125,6 +126,7 @@ namespace OpenRA
|
|||||||
health = TraitOrDefault<IHealth>();
|
health = TraitOrDefault<IHealth>();
|
||||||
renderModifiers = TraitsImplementing<IRenderModifier>().ToArray();
|
renderModifiers = TraitsImplementing<IRenderModifier>().ToArray();
|
||||||
renders = TraitsImplementing<IRender>().ToArray();
|
renders = TraitsImplementing<IRender>().ToArray();
|
||||||
|
mouseBounds = TraitsImplementing<IMouseBounds>().ToArray();
|
||||||
disables = TraitsImplementing<IDisable>().ToArray();
|
disables = TraitsImplementing<IDisable>().ToArray();
|
||||||
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
|
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
|
||||||
defaultVisibility = Trait<IDefaultVisibility>();
|
defaultVisibility = Trait<IDefaultVisibility>();
|
||||||
@@ -221,6 +223,18 @@ namespace OpenRA
|
|||||||
yield return r;
|
yield return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rectangle MouseBounds(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
foreach (var mb in mouseBounds)
|
||||||
|
{
|
||||||
|
var bounds = mb.MouseoverBounds(this, wr);
|
||||||
|
if (!bounds.IsEmpty)
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Rectangle.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
public void QueueActivity(bool queued, Activity nextActivity)
|
public void QueueActivity(bool queued, Activity nextActivity)
|
||||||
{
|
{
|
||||||
if (!queued)
|
if (!queued)
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
List<IFinalizedRenderable> GenerateRenderables()
|
List<IFinalizedRenderable> GenerateRenderables()
|
||||||
{
|
{
|
||||||
var actors = World.ScreenMap.ActorsInBox(Viewport.TopLeft, Viewport.BottomRight).Append(World.WorldActor);
|
var actors = World.ScreenMap.RenderableActorsInBox(Viewport.TopLeft, Viewport.BottomRight).Append(World.WorldActor);
|
||||||
if (World.RenderPlayer != null)
|
if (World.RenderPlayer != null)
|
||||||
actors = actors.Append(World.RenderPlayer.PlayerActor);
|
actors = actors.Append(World.RenderPlayer.PlayerActor);
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ namespace OpenRA.Graphics
|
|||||||
worldRenderables = worldRenderables.Concat(World.UnpartitionedEffects.SelectMany(e => e.Render(this)));
|
worldRenderables = worldRenderables.Concat(World.UnpartitionedEffects.SelectMany(e => e.Render(this)));
|
||||||
|
|
||||||
// Partitioned, currently on-screen effects
|
// Partitioned, currently on-screen effects
|
||||||
var effectRenderables = World.ScreenMap.EffectsInBox(Viewport.TopLeft, Viewport.BottomRight);
|
var effectRenderables = World.ScreenMap.RenderableEffectsInBox(Viewport.TopLeft, Viewport.BottomRight);
|
||||||
worldRenderables = worldRenderables.Concat(effectRenderables.SelectMany(e => e.Render(this)));
|
worldRenderables = worldRenderables.Concat(effectRenderables.SelectMany(e => e.Render(this)));
|
||||||
|
|
||||||
worldRenderables = worldRenderables.OrderBy(RenderableScreenZPositionComparisonKey);
|
worldRenderables = worldRenderables.OrderBy(RenderableScreenZPositionComparisonKey);
|
||||||
@@ -213,12 +213,20 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debugVis.Value != null && debugVis.Value.ScreenMap)
|
if (debugVis.Value != null && debugVis.Value.ScreenMap)
|
||||||
foreach (var r in World.ScreenMap.ItemBounds(World.RenderPlayer))
|
{
|
||||||
|
foreach (var r in World.ScreenMap.RenderBounds(World.RenderPlayer))
|
||||||
Game.Renderer.WorldRgbaColorRenderer.DrawRect(
|
Game.Renderer.WorldRgbaColorRenderer.DrawRect(
|
||||||
new float3(r.Left, r.Top, r.Bottom),
|
new float3(r.Left, r.Top, r.Bottom),
|
||||||
new float3(r.Right, r.Bottom, r.Bottom),
|
new float3(r.Right, r.Bottom, r.Bottom),
|
||||||
1 / Viewport.Zoom, Color.MediumSpringGreen);
|
1 / Viewport.Zoom, Color.MediumSpringGreen);
|
||||||
|
|
||||||
|
foreach (var r in World.ScreenMap.MouseBounds(World.RenderPlayer))
|
||||||
|
Game.Renderer.WorldRgbaColorRenderer.DrawRect(
|
||||||
|
new float3(r.Left, r.Top, r.Bottom),
|
||||||
|
new float3(r.Right, r.Bottom, r.Bottom),
|
||||||
|
1 / Viewport.Zoom, Color.OrangeRed);
|
||||||
|
}
|
||||||
|
|
||||||
Game.Renderer.Flush();
|
Game.Renderer.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Orders
|
namespace OpenRA.Orders
|
||||||
@@ -62,7 +63,7 @@ namespace OpenRA.Orders
|
|||||||
return world.Map.Contains(cell) ? Cursor : "generic-blocked";
|
return world.Map.Contains(cell) ? Cursor : "generic-blocked";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
|
public override bool InputOverridesSelection(WorldRenderer wr, World world, int2 xy, MouseInput mi)
|
||||||
{
|
{
|
||||||
// Custom order generators always override selection
|
// Custom order generators always override selection
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Orders
|
namespace OpenRA.Orders
|
||||||
@@ -20,14 +21,14 @@ namespace OpenRA.Orders
|
|||||||
{
|
{
|
||||||
static Target TargetForInput(World world, CPos cell, int2 worldPixel, MouseInput mi)
|
static Target TargetForInput(World world, CPos cell, int2 worldPixel, MouseInput mi)
|
||||||
{
|
{
|
||||||
var actor = world.ScreenMap.ActorsAt(mi)
|
var actor = world.ScreenMap.ActorsAtMouse(mi)
|
||||||
.Where(a => a.Info.HasTraitInfo<ITargetableInfo>() && !world.FogObscures(a))
|
.Where(a => a.Actor.Info.HasTraitInfo<ITargetableInfo>() && !world.FogObscures(a.Actor))
|
||||||
.WithHighestSelectionPriority(worldPixel);
|
.WithHighestSelectionPriority(worldPixel);
|
||||||
|
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
return Target.FromActor(actor);
|
return Target.FromActor(actor);
|
||||||
|
|
||||||
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi)
|
var frozen = world.ScreenMap.FrozenActorsAtMouse(world.RenderPlayer, mi)
|
||||||
.Where(a => a.Info.HasTraitInfo<ITargetableInfo>() && a.Visible && a.HasRenderables)
|
.Where(a => a.Info.HasTraitInfo<ITargetableInfo>() && a.Visible && a.HasRenderables)
|
||||||
.WithHighestSelectionPriority(worldPixel);
|
.WithHighestSelectionPriority(worldPixel);
|
||||||
|
|
||||||
@@ -78,16 +79,18 @@ namespace OpenRA.Orders
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Used for classic mouse orders, determines whether or not action at xy is move or select
|
// Used for classic mouse orders, determines whether or not action at xy is move or select
|
||||||
public virtual bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
|
public virtual bool InputOverridesSelection(WorldRenderer wr, World world, int2 xy, MouseInput mi)
|
||||||
{
|
{
|
||||||
var actor = world.ScreenMap.ActorsAt(xy).WithHighestSelectionPriority(xy);
|
var actor = world.ScreenMap.ActorsAtMouse(xy).WithHighestSelectionPriority(xy);
|
||||||
if (actor == null)
|
if (actor == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var target = Target.FromActor(actor);
|
var target = Target.FromActor(actor);
|
||||||
var cell = world.Map.CellContaining(target.CenterPosition);
|
var cell = world.Map.CellContaining(target.CenterPosition);
|
||||||
var actorsAt = world.ActorMap.GetActorsAt(cell).ToList();
|
var actorsAt = world.ActorMap.GetActorsAt(cell).ToList();
|
||||||
var underCursor = world.Selection.Actors.WithHighestSelectionPriority(xy);
|
var underCursor = world.Selection.Actors
|
||||||
|
.Select(a => new ActorBoundsPair(a, a.MouseBounds(wr)))
|
||||||
|
.WithHighestSelectionPriority(xy);
|
||||||
|
|
||||||
var o = OrderForUnit(underCursor, target, actorsAt, cell, mi);
|
var o = OrderForUnit(underCursor, target, actorsAt, cell, mi);
|
||||||
if (o != null)
|
if (o != null)
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
@@ -45,21 +47,29 @@ namespace OpenRA.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Actor WithHighestSelectionPriority(this IEnumerable<Actor> actors, int2 selectionPixel)
|
public static Actor WithHighestSelectionPriority(this IEnumerable<ActorBoundsPair> actors, int2 selectionPixel)
|
||||||
{
|
{
|
||||||
return actors.MaxByOrDefault(a => CalculateActorSelectionPriority(a.Info, a.SelectableBounds, selectionPixel));
|
if (!actors.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return actors.MaxBy(a => CalculateActorSelectionPriority(a.Actor.Info, a.Bounds, selectionPixel)).Actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FrozenActor WithHighestSelectionPriority(this IEnumerable<FrozenActor> actors, int2 selectionPixel)
|
public static FrozenActor WithHighestSelectionPriority(this IEnumerable<FrozenActor> actors, int2 selectionPixel)
|
||||||
{
|
{
|
||||||
return actors.MaxByOrDefault(a => CalculateActorSelectionPriority(a.Info, a.SelectableBounds, selectionPixel));
|
return actors.MaxByOrDefault(a => CalculateActorSelectionPriority(a.Info, a.MouseBounds, selectionPixel));
|
||||||
}
|
}
|
||||||
|
|
||||||
static long CalculateActorSelectionPriority(ActorInfo info, Rectangle bounds, int2 selectionPixel)
|
static long CalculateActorSelectionPriority(ActorInfo info, Rectangle bounds, int2 selectionPixel)
|
||||||
{
|
{
|
||||||
var centerPixel = new int2(bounds.X, bounds.Y);
|
if (bounds.IsEmpty)
|
||||||
var pixelDistance = (centerPixel - selectionPixel).Length;
|
return info.SelectionPriority();
|
||||||
|
|
||||||
|
var centerPixel = new int2(
|
||||||
|
bounds.Left + bounds.Size.Width / 2,
|
||||||
|
bounds.Top + bounds.Size.Height / 2);
|
||||||
|
|
||||||
|
var pixelDistance = (centerPixel - selectionPixel).Length;
|
||||||
return ((long)-pixelDistance << 32) + info.SelectionPriority();
|
return ((long)-pixelDistance << 32) + info.SelectionPriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ namespace OpenRA.Traits
|
|||||||
public IRenderable[] Renderables = NoRenderables;
|
public IRenderable[] Renderables = NoRenderables;
|
||||||
public Rectangle[] ScreenBounds = NoBounds;
|
public Rectangle[] ScreenBounds = NoBounds;
|
||||||
|
|
||||||
|
// TODO: Replace this with an int2[] polygon
|
||||||
|
public Rectangle MouseBounds = Rectangle.Empty;
|
||||||
|
|
||||||
static readonly IRenderable[] NoRenderables = new IRenderable[0];
|
static readonly IRenderable[] NoRenderables = new IRenderable[0];
|
||||||
static readonly Rectangle[] NoBounds = new Rectangle[0];
|
static readonly Rectangle[] NoBounds = new Rectangle[0];
|
||||||
|
|
||||||
@@ -298,7 +301,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
return world.ScreenMap.FrozenActorsInBox(owner, wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
return world.ScreenMap.RenderableFrozenActorsInBox(owner, wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
||||||
.Where(f => f.Visible)
|
.Where(f => f.Visible)
|
||||||
.SelectMany(ff => ff.Render(wr));
|
.SelectMany(ff => ff.Render(wr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
[Desc("This actor is selectable. Defines bounds of selectable area, selection class and selection priority.")]
|
[Desc("This actor is selectable. Defines bounds of selectable area, selection class and selection priority.")]
|
||||||
@@ -19,6 +23,9 @@ namespace OpenRA.Traits
|
|||||||
[Desc("Bounds for the selectable area.")]
|
[Desc("Bounds for the selectable area.")]
|
||||||
public readonly int[] Bounds = null;
|
public readonly int[] Bounds = null;
|
||||||
|
|
||||||
|
[Desc("Area outside the visible selection box that is enabled for selection")]
|
||||||
|
public readonly int Margin = 0;
|
||||||
|
|
||||||
[Desc("All units having the same selection class specified will be selected with select-by-type commands (e.g. double-click). "
|
[Desc("All units having the same selection class specified will be selected with select-by-type commands (e.g. double-click). "
|
||||||
+ "Defaults to the actor name when not defined or inherited.")]
|
+ "Defaults to the actor name when not defined or inherited.")]
|
||||||
public readonly string Class = null;
|
public readonly string Class = null;
|
||||||
@@ -28,7 +35,7 @@ namespace OpenRA.Traits
|
|||||||
public object Create(ActorInitializer init) { return new Selectable(init.Self, this); }
|
public object Create(ActorInitializer init) { return new Selectable(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Selectable
|
public class Selectable : IMouseBounds
|
||||||
{
|
{
|
||||||
public readonly string Class = null;
|
public readonly string Class = null;
|
||||||
|
|
||||||
@@ -39,5 +46,20 @@ namespace OpenRA.Traits
|
|||||||
Class = string.IsNullOrEmpty(info.Class) ? self.Info.Name : info.Class;
|
Class = string.IsNullOrEmpty(info.Class) ? self.Info.Name : info.Class;
|
||||||
Info = info;
|
Info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle IMouseBounds.MouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (Info.Bounds == null)
|
||||||
|
return Rectangle.Empty;
|
||||||
|
|
||||||
|
var size = new int2(Info.Bounds[0], Info.Bounds[1]);
|
||||||
|
|
||||||
|
var offset = -size / 2 - new int2(Info.Margin, Info.Margin);
|
||||||
|
if (Info.Bounds.Length > 2)
|
||||||
|
offset += new int2(Info.Bounds[2], Info.Bounds[3]);
|
||||||
|
|
||||||
|
var xy = wr.ScreenPxPosition(self.CenterPosition) + offset;
|
||||||
|
return new Rectangle(xy.X, xy.Y, size.X + 2 * Info.Margin, size.Y + 2 * Info.Margin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ namespace OpenRA.Traits
|
|||||||
public interface IAutoSelectionSizeInfo : ITraitInfoInterface { }
|
public interface IAutoSelectionSizeInfo : ITraitInfoInterface { }
|
||||||
public interface IAutoSelectionSize { int2 SelectionSize(Actor self); }
|
public interface IAutoSelectionSize { int2 SelectionSize(Actor self); }
|
||||||
|
|
||||||
|
// TODO: Replace Rectangle with an int2[] polygon
|
||||||
|
public interface IMouseBounds { Rectangle MouseoverBounds(Actor self, WorldRenderer wr); }
|
||||||
|
public interface IAutoMouseBounds { Rectangle AutoMouseoverBounds(Actor self, WorldRenderer wr); }
|
||||||
|
|
||||||
public interface IAutoRenderSizeInfo : ITraitInfoInterface { }
|
public interface IAutoRenderSizeInfo : ITraitInfoInterface { }
|
||||||
public interface IAutoRenderSize { int2 RenderSize(Actor self); }
|
public interface IAutoRenderSize { int2 RenderSize(Actor self); }
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,26 @@ using OpenRA.Primitives;
|
|||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
|
public struct ActorBoundsPair : IEquatable<ActorBoundsPair>
|
||||||
|
{
|
||||||
|
public readonly Actor Actor;
|
||||||
|
|
||||||
|
// TODO: Replace this with an int2[] polygon
|
||||||
|
public readonly Rectangle Bounds;
|
||||||
|
|
||||||
|
public ActorBoundsPair(Actor actor, Rectangle bounds) { Actor = actor; Bounds = bounds; }
|
||||||
|
|
||||||
|
public static bool operator ==(ActorBoundsPair me, ActorBoundsPair other) { return me.Actor == other.Actor && Equals(me.Bounds, other.Bounds); }
|
||||||
|
public static bool operator !=(ActorBoundsPair me, ActorBoundsPair other) { return !(me == other); }
|
||||||
|
|
||||||
|
public override int GetHashCode() { return Actor.GetHashCode() ^ Bounds.GetHashCode(); }
|
||||||
|
|
||||||
|
public bool Equals(ActorBoundsPair other) { return this == other; }
|
||||||
|
public override bool Equals(object obj) { return obj is ActorBoundsPair && Equals((ActorBoundsPair)obj); }
|
||||||
|
|
||||||
|
public override string ToString() { return "{0}->{1}".F(Actor.Info.Name, Bounds.GetType().Name); }
|
||||||
|
}
|
||||||
|
|
||||||
public class ScreenMapInfo : ITraitInfo
|
public class ScreenMapInfo : ITraitInfo
|
||||||
{
|
{
|
||||||
[Desc("Size of partition bins (world pixels)")]
|
[Desc("Size of partition bins (world pixels)")]
|
||||||
@@ -32,9 +52,14 @@ namespace OpenRA.Traits
|
|||||||
static readonly IEnumerable<FrozenActor> NoFrozenActors = new FrozenActor[0];
|
static readonly IEnumerable<FrozenActor> NoFrozenActors = new FrozenActor[0];
|
||||||
readonly Func<FrozenActor, bool> frozenActorIsValid = fa => fa.IsValid;
|
readonly Func<FrozenActor, bool> frozenActorIsValid = fa => fa.IsValid;
|
||||||
readonly Func<Actor, bool> actorIsInWorld = a => a.IsInWorld;
|
readonly Func<Actor, bool> actorIsInWorld = a => a.IsInWorld;
|
||||||
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedFrozenActors;
|
readonly Func<Actor, ActorBoundsPair> selectActorAndBounds;
|
||||||
readonly SpatiallyPartitioned<Actor> partitionedActors;
|
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedMouseFrozenActors;
|
||||||
readonly SpatiallyPartitioned<IEffect> partitionedEffects;
|
readonly SpatiallyPartitioned<Actor> partitionedMouseActors;
|
||||||
|
readonly Dictionary<Actor, ActorBoundsPair> partitionedMouseActorBounds = new Dictionary<Actor, ActorBoundsPair>();
|
||||||
|
|
||||||
|
readonly Cache<Player, SpatiallyPartitioned<FrozenActor>> partitionedRenderableFrozenActors;
|
||||||
|
readonly SpatiallyPartitioned<Actor> partitionedRenderableActors;
|
||||||
|
readonly SpatiallyPartitioned<IEffect> partitionedRenderableEffects;
|
||||||
|
|
||||||
// Updates are done in one pass to ensure all bound changes have been applied
|
// Updates are done in one pass to ensure all bound changes have been applied
|
||||||
readonly HashSet<Actor> addOrUpdateActors = new HashSet<Actor>();
|
readonly HashSet<Actor> addOrUpdateActors = new HashSet<Actor>();
|
||||||
@@ -49,14 +74,19 @@ namespace OpenRA.Traits
|
|||||||
var size = world.Map.Grid.TileSize;
|
var size = world.Map.Grid.TileSize;
|
||||||
var width = world.Map.MapSize.X * size.Width;
|
var width = world.Map.MapSize.X * size.Width;
|
||||||
var height = world.Map.MapSize.Y * size.Height;
|
var height = world.Map.MapSize.Y * size.Height;
|
||||||
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
|
||||||
|
partitionedMouseFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
||||||
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
|
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
|
||||||
|
partitionedMouseActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
|
||||||
|
selectActorAndBounds = a => partitionedMouseActorBounds[a];
|
||||||
|
|
||||||
|
partitionedRenderableFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
|
||||||
|
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
|
||||||
|
partitionedRenderableActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
|
||||||
|
partitionedRenderableEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
|
||||||
|
|
||||||
addOrUpdateFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
|
addOrUpdateFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
|
||||||
removeFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
|
removeFrozenActors = new Cache<Player, HashSet<FrozenActor>>(_ => new HashSet<FrozenActor>());
|
||||||
|
|
||||||
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);
|
|
||||||
partitionedEffects = new SpatiallyPartitioned<IEffect>(width, height, info.BinSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w, WorldRenderer wr) { worldRenderer = wr; }
|
public void WorldLoaded(World w, WorldRenderer wr) { worldRenderer = wr; }
|
||||||
@@ -94,7 +124,7 @@ namespace OpenRA.Traits
|
|||||||
var screenHeight = Math.Abs(size.Height);
|
var screenHeight = Math.Abs(size.Height);
|
||||||
var screenBounds = new Rectangle(screenPos.X - screenWidth / 2, screenPos.Y - screenHeight / 2, screenWidth, screenHeight);
|
var screenBounds = new Rectangle(screenPos.X - screenWidth / 2, screenPos.Y - screenHeight / 2, screenWidth, screenHeight);
|
||||||
if (ValidBounds(screenBounds))
|
if (ValidBounds(screenBounds))
|
||||||
partitionedEffects.Add(effect, screenBounds);
|
partitionedRenderableEffects.Add(effect, screenBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(IEffect effect, WPos position, Sprite sprite)
|
public void Add(IEffect effect, WPos position, Sprite sprite)
|
||||||
@@ -117,34 +147,41 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public void Remove(IEffect effect)
|
public void Remove(IEffect effect)
|
||||||
{
|
{
|
||||||
partitionedEffects.Remove(effect);
|
partitionedRenderableEffects.Remove(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidBounds(Rectangle bounds)
|
static bool ValidBounds(Rectangle bounds)
|
||||||
{
|
{
|
||||||
return bounds.Width > 0 && bounds.Height > 0;
|
return bounds.Width > 0 && bounds.Height > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FrozenActor> FrozenActorsAt(Player viewer, int2 worldPx)
|
public IEnumerable<FrozenActor> FrozenActorsAtMouse(Player viewer, int2 worldPx)
|
||||||
{
|
{
|
||||||
if (viewer == null)
|
if (viewer == null)
|
||||||
return NoFrozenActors;
|
return NoFrozenActors;
|
||||||
return partitionedFrozenActors[viewer].At(worldPx).Where(frozenActorIsValid);
|
|
||||||
|
return partitionedMouseFrozenActors[viewer]
|
||||||
|
.At(worldPx)
|
||||||
|
.Where(frozenActorIsValid)
|
||||||
|
.Where(x => x.MouseBounds.Contains(worldPx));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FrozenActor> FrozenActorsAt(Player viewer, MouseInput mi)
|
public IEnumerable<FrozenActor> FrozenActorsAtMouse(Player viewer, MouseInput mi)
|
||||||
{
|
{
|
||||||
return FrozenActorsAt(viewer, worldRenderer.Viewport.ViewToWorldPx(mi.Location));
|
return FrozenActorsAtMouse(viewer, worldRenderer.Viewport.ViewToWorldPx(mi.Location));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Actor> ActorsAt(int2 worldPx)
|
public IEnumerable<ActorBoundsPair> ActorsAtMouse(int2 worldPx)
|
||||||
{
|
{
|
||||||
return partitionedActors.At(worldPx).Where(actorIsInWorld);
|
return partitionedMouseActors.At(worldPx)
|
||||||
|
.Where(actorIsInWorld)
|
||||||
|
.Select(selectActorAndBounds)
|
||||||
|
.Where(x => x.Bounds.Contains(worldPx));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Actor> ActorsAt(MouseInput mi)
|
public IEnumerable<ActorBoundsPair> ActorsAtMouse(MouseInput mi)
|
||||||
{
|
{
|
||||||
return ActorsAt(worldRenderer.Viewport.ViewToWorldPx(mi.Location));
|
return ActorsAtMouse(worldRenderer.Viewport.ViewToWorldPx(mi.Location));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rectangle RectWithCorners(int2 a, int2 b)
|
static Rectangle RectWithCorners(int2 a, int2 b)
|
||||||
@@ -152,36 +189,35 @@ namespace OpenRA.Traits
|
|||||||
return Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y));
|
return Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Actor> ActorsInBox(int2 a, int2 b)
|
public IEnumerable<ActorBoundsPair> ActorsInMouseBox(int2 a, int2 b)
|
||||||
{
|
{
|
||||||
return ActorsInBox(RectWithCorners(a, b));
|
return ActorsInMouseBox(RectWithCorners(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IEffect> EffectsInBox(int2 a, int2 b)
|
public IEnumerable<ActorBoundsPair> ActorsInMouseBox(Rectangle r)
|
||||||
{
|
{
|
||||||
return partitionedEffects.InBox(RectWithCorners(a, b));
|
return partitionedMouseActors.InBox(r)
|
||||||
|
.Where(actorIsInWorld)
|
||||||
|
.Select(selectActorAndBounds)
|
||||||
|
.Where(x => r.IntersectsWith(x.Bounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Actor> ActorsInBox(Rectangle r)
|
public IEnumerable<Actor> RenderableActorsInBox(int2 a, int2 b)
|
||||||
{
|
{
|
||||||
return partitionedActors.InBox(r).Where(actorIsInWorld);
|
return partitionedRenderableActors.InBox(RectWithCorners(a, b)).Where(actorIsInWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FrozenActor> FrozenActorsInBox(Player p, int2 a, int2 b)
|
public IEnumerable<IEffect> RenderableEffectsInBox(int2 a, int2 b)
|
||||||
{
|
{
|
||||||
return FrozenActorsInBox(p, RectWithCorners(a, b));
|
return partitionedRenderableEffects.InBox(RectWithCorners(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IEffect> EffectsInBox(Rectangle r)
|
public IEnumerable<FrozenActor> RenderableFrozenActorsInBox(Player p, int2 a, int2 b)
|
||||||
{
|
|
||||||
return partitionedEffects.InBox(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<FrozenActor> FrozenActorsInBox(Player p, Rectangle r)
|
|
||||||
{
|
{
|
||||||
if (p == null)
|
if (p == null)
|
||||||
return NoFrozenActors;
|
return NoFrozenActors;
|
||||||
return partitionedFrozenActors[p].InBox(r).Where(frozenActorIsValid);
|
|
||||||
|
return partitionedRenderableFrozenActors[p].InBox(RectWithCorners(a, b)).Where(frozenActorIsValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle AggregateBounds(IEnumerable<Rectangle> screenBounds)
|
Rectangle AggregateBounds(IEnumerable<Rectangle> screenBounds)
|
||||||
@@ -196,24 +232,54 @@ namespace OpenRA.Traits
|
|||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle AggregateBounds(IEnumerable<int2> vertices)
|
||||||
|
{
|
||||||
|
if (!vertices.Any())
|
||||||
|
return Rectangle.Empty;
|
||||||
|
|
||||||
|
var first = vertices.First();
|
||||||
|
var rect = new Rectangle(first.X, first.Y, 0, 0);
|
||||||
|
foreach (var v in vertices.Skip(1))
|
||||||
|
rect = Rectangle.Union(rect, new Rectangle(v.X, v.Y, 0, 0));
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
foreach (var a in addOrUpdateActors)
|
foreach (var a in addOrUpdateActors)
|
||||||
{
|
{
|
||||||
var bounds = AggregateBounds(a.ScreenBounds(worldRenderer));
|
var mouseBounds = a.MouseBounds(worldRenderer);
|
||||||
if (!bounds.Size.IsEmpty)
|
if (!mouseBounds.Size.IsEmpty)
|
||||||
{
|
{
|
||||||
if (partitionedActors.Contains(a))
|
if (partitionedMouseActors.Contains(a))
|
||||||
partitionedActors.Update(a, bounds);
|
partitionedMouseActors.Update(a, mouseBounds);
|
||||||
else
|
else
|
||||||
partitionedActors.Add(a, bounds);
|
partitionedMouseActors.Add(a, mouseBounds);
|
||||||
|
|
||||||
|
partitionedMouseActorBounds[a] = new ActorBoundsPair(a, mouseBounds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
partitionedActors.Remove(a);
|
partitionedMouseActors.Remove(a);
|
||||||
|
|
||||||
|
var screenBounds = AggregateBounds(a.ScreenBounds(worldRenderer));
|
||||||
|
if (!screenBounds.Size.IsEmpty)
|
||||||
|
{
|
||||||
|
if (partitionedRenderableActors.Contains(a))
|
||||||
|
partitionedRenderableActors.Update(a, screenBounds);
|
||||||
|
else
|
||||||
|
partitionedRenderableActors.Add(a, screenBounds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
partitionedRenderableActors.Remove(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var a in removeActors)
|
foreach (var a in removeActors)
|
||||||
partitionedActors.Remove(a);
|
{
|
||||||
|
partitionedMouseActors.Remove(a);
|
||||||
|
partitionedMouseActorBounds.Remove(a);
|
||||||
|
partitionedRenderableActors.Remove(a);
|
||||||
|
}
|
||||||
|
|
||||||
addOrUpdateActors.Clear();
|
addOrUpdateActors.Clear();
|
||||||
removeActors.Clear();
|
removeActors.Clear();
|
||||||
@@ -222,16 +288,27 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
foreach (var fa in kv.Value)
|
foreach (var fa in kv.Value)
|
||||||
{
|
{
|
||||||
var bounds = AggregateBounds(fa.ScreenBounds);
|
var mouseBounds = fa.MouseBounds;
|
||||||
if (!bounds.Size.IsEmpty)
|
if (!mouseBounds.Size.IsEmpty)
|
||||||
{
|
{
|
||||||
if (partitionedFrozenActors[kv.Key].Contains(fa))
|
if (partitionedMouseFrozenActors[kv.Key].Contains(fa))
|
||||||
partitionedFrozenActors[kv.Key].Update(fa, bounds);
|
partitionedMouseFrozenActors[kv.Key].Update(fa, mouseBounds);
|
||||||
else
|
else
|
||||||
partitionedFrozenActors[kv.Key].Add(fa, bounds);
|
partitionedMouseFrozenActors[kv.Key].Add(fa, mouseBounds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
partitionedFrozenActors[kv.Key].Remove(fa);
|
partitionedMouseFrozenActors[kv.Key].Remove(fa);
|
||||||
|
|
||||||
|
var screenBounds = AggregateBounds(fa.ScreenBounds);
|
||||||
|
if (!screenBounds.Size.IsEmpty)
|
||||||
|
{
|
||||||
|
if (partitionedRenderableFrozenActors[kv.Key].Contains(fa))
|
||||||
|
partitionedRenderableFrozenActors[kv.Key].Update(fa, screenBounds);
|
||||||
|
else
|
||||||
|
partitionedRenderableFrozenActors[kv.Key].Add(fa, screenBounds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
partitionedRenderableFrozenActors[kv.Key].Remove(fa);
|
||||||
}
|
}
|
||||||
|
|
||||||
kv.Value.Clear();
|
kv.Value.Clear();
|
||||||
@@ -240,18 +317,28 @@ namespace OpenRA.Traits
|
|||||||
foreach (var kv in removeFrozenActors)
|
foreach (var kv in removeFrozenActors)
|
||||||
{
|
{
|
||||||
foreach (var fa in kv.Value)
|
foreach (var fa in kv.Value)
|
||||||
partitionedFrozenActors[kv.Key].Remove(fa);
|
{
|
||||||
|
partitionedMouseFrozenActors[kv.Key].Remove(fa);
|
||||||
|
partitionedRenderableFrozenActors[kv.Key].Remove(fa);
|
||||||
|
}
|
||||||
|
|
||||||
kv.Value.Clear();
|
kv.Value.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Rectangle> ItemBounds(Player viewer)
|
public IEnumerable<Rectangle> RenderBounds(Player viewer)
|
||||||
{
|
{
|
||||||
var bounds = partitionedActors.ItemBounds
|
var bounds = partitionedRenderableActors.ItemBounds
|
||||||
.Concat(partitionedEffects.ItemBounds);
|
.Concat(partitionedRenderableEffects.ItemBounds);
|
||||||
|
|
||||||
return viewer != null ? bounds.Concat(partitionedFrozenActors[viewer].ItemBounds) : bounds;
|
return viewer != null ? bounds.Concat(partitionedRenderableFrozenActors[viewer].ItemBounds) : bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Rectangle> MouseBounds(Player viewer)
|
||||||
|
{
|
||||||
|
var bounds = partitionedMouseActors.ItemBounds;
|
||||||
|
|
||||||
|
return viewer != null ? bounds.Concat(partitionedMouseFrozenActors[viewer].ItemBounds) : bounds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var underCursor = world.ScreenMap.ActorsAt(mi)
|
var underCursor = world.ScreenMap.ActorsAtMouse(mi)
|
||||||
|
.Select(a => a.Actor)
|
||||||
.Where(a => !world.FogObscures(a))
|
.Where(a => !world.FogObscures(a))
|
||||||
.MaxByOrDefault(a => a.Info.HasTraitInfo<SelectableInfo>()
|
.MaxByOrDefault(a => a.Info.HasTraitInfo<SelectableInfo>()
|
||||||
? a.Info.TraitInfo<SelectableInfo>().Priority : int.MinValue);
|
? a.Info.TraitInfo<SelectableInfo>().Priority : int.MinValue);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Graphics;
|
using OpenRA.Mods.Common.Graphics;
|
||||||
@@ -45,22 +46,26 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WithVoxelUnloadBody : IAutoSelectionSize, IAutoRenderSize
|
public class WithVoxelUnloadBody : IAutoSelectionSize, IAutoRenderSize, IAutoMouseBounds
|
||||||
{
|
{
|
||||||
public bool Docked;
|
public bool Docked;
|
||||||
|
|
||||||
readonly int2 size;
|
readonly int2 size;
|
||||||
|
readonly ModelAnimation modelAnimation;
|
||||||
|
readonly RenderVoxels rv;
|
||||||
|
|
||||||
public WithVoxelUnloadBody(Actor self, WithVoxelUnloadBodyInfo info)
|
public WithVoxelUnloadBody(Actor self, WithVoxelUnloadBodyInfo info)
|
||||||
{
|
{
|
||||||
var body = self.Trait<BodyOrientation>();
|
var body = self.Trait<BodyOrientation>();
|
||||||
var rv = self.Trait<RenderVoxels>();
|
rv = self.Trait<RenderVoxels>();
|
||||||
|
|
||||||
var idleModel = self.World.ModelCache.GetModelSequence(rv.Image, info.IdleSequence);
|
var idleModel = self.World.ModelCache.GetModelSequence(rv.Image, info.IdleSequence);
|
||||||
rv.Add(new ModelAnimation(idleModel, () => WVec.Zero,
|
modelAnimation = new ModelAnimation(idleModel, () => WVec.Zero,
|
||||||
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
||||||
() => Docked,
|
() => Docked,
|
||||||
() => 0, info.ShowShadow));
|
() => 0, info.ShowShadow);
|
||||||
|
|
||||||
|
rv.Add(modelAnimation);
|
||||||
|
|
||||||
// Selection size
|
// Selection size
|
||||||
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
||||||
@@ -76,5 +81,10 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
|||||||
|
|
||||||
int2 IAutoSelectionSize.SelectionSize(Actor self) { return size; }
|
int2 IAutoSelectionSize.SelectionSize(Actor self) { return size; }
|
||||||
int2 IAutoRenderSize.RenderSize(Actor self) { return size; }
|
int2 IAutoRenderSize.RenderSize(Actor self) { return size; }
|
||||||
|
|
||||||
|
Rectangle IAutoMouseBounds.AutoMouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return modelAnimation.ScreenBounds(self.CenterPosition, wr, rv.Info.Scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common;
|
using OpenRA.Mods.Common;
|
||||||
@@ -47,12 +48,15 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WithVoxelWalkerBody : IAutoSelectionSize, ITick, IActorPreviewInitModifier, IAutoRenderSize
|
public class WithVoxelWalkerBody : IAutoSelectionSize, ITick, IActorPreviewInitModifier, IAutoRenderSize, IAutoMouseBounds
|
||||||
{
|
{
|
||||||
readonly WithVoxelWalkerBodyInfo info;
|
readonly WithVoxelWalkerBodyInfo info;
|
||||||
readonly IMove movement;
|
readonly IMove movement;
|
||||||
readonly IFacing facing;
|
readonly IFacing facing;
|
||||||
readonly int2 size;
|
readonly int2 size;
|
||||||
|
readonly ModelAnimation modelAnimation;
|
||||||
|
readonly RenderVoxels rv;
|
||||||
|
|
||||||
int oldFacing;
|
int oldFacing;
|
||||||
uint tick, frame, frames;
|
uint tick, frame, frames;
|
||||||
|
|
||||||
@@ -63,13 +67,15 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
|||||||
facing = self.Trait<IFacing>();
|
facing = self.Trait<IFacing>();
|
||||||
|
|
||||||
var body = self.Trait<BodyOrientation>();
|
var body = self.Trait<BodyOrientation>();
|
||||||
var rv = self.Trait<RenderVoxels>();
|
rv = self.Trait<RenderVoxels>();
|
||||||
|
|
||||||
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||||
frames = model.Frames;
|
frames = model.Frames;
|
||||||
rv.Add(new ModelAnimation(model, () => WVec.Zero,
|
modelAnimation = new ModelAnimation(model, () => WVec.Zero,
|
||||||
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
||||||
() => false, () => frame, info.ShowShadow));
|
() => false, () => frame, info.ShowShadow);
|
||||||
|
|
||||||
|
rv.Add(modelAnimation);
|
||||||
|
|
||||||
// Selection size
|
// Selection size
|
||||||
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
||||||
@@ -98,6 +104,11 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
|||||||
{
|
{
|
||||||
inits.Add(new BodyAnimationFrameInit(frame));
|
inits.Add(new BodyAnimationFrameInit(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle IAutoMouseBounds.AutoMouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return modelAnimation.ScreenBounds(self.CenterPosition, wr, rv.Info.Scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BodyAnimationFrameInit : IActorInit<uint>
|
public class BodyAnimationFrameInit : IActorInit<uint>
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ namespace OpenRA.Mods.Common.Orders
|
|||||||
{
|
{
|
||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var underCursor = world.ScreenMap.ActorsAt(mi)
|
var underCursor = world.ScreenMap.ActorsAtMouse(mi)
|
||||||
|
.Select(a => a.Actor)
|
||||||
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.TraitsImplementing<T>()
|
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.TraitsImplementing<T>()
|
||||||
.Any(Exts.IsTraitEnabled));
|
.Any(Exts.IsTraitEnabled));
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ namespace OpenRA.Mods.Common.Orders
|
|||||||
|
|
||||||
static IEnumerable<Actor> FriendlyGuardableUnits(World world, MouseInput mi)
|
static IEnumerable<Actor> FriendlyGuardableUnits(World world, MouseInput mi)
|
||||||
{
|
{
|
||||||
return world.ScreenMap.ActorsAt(mi)
|
return world.ScreenMap.ActorsAtMouse(mi)
|
||||||
|
.Select(a => a.Actor)
|
||||||
.Where(a => !a.IsDead &&
|
.Where(a => !a.IsDead &&
|
||||||
a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) &&
|
a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) &&
|
||||||
a.Info.HasTraitInfo<GuardableInfo>() &&
|
a.Info.HasTraitInfo<GuardableInfo>() &&
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ namespace OpenRA.Mods.Common.Orders
|
|||||||
if (mi.Button != MouseButton.Left)
|
if (mi.Button != MouseButton.Left)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
var underCursor = world.ScreenMap.ActorsAt(mi)
|
var underCursor = world.ScreenMap.ActorsAtMouse(mi)
|
||||||
|
.Select(a => a.Actor)
|
||||||
.FirstOrDefault(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && !world.FogObscures(a));
|
.FirstOrDefault(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && !world.FogObscures(a));
|
||||||
|
|
||||||
if (underCursor == null)
|
if (underCursor == null)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Activities;
|
using OpenRA.Mods.Common.Activities;
|
||||||
using OpenRA.Orders;
|
using OpenRA.Orders;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -178,7 +179,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return prefix + "-blocked";
|
return prefix + "-blocked";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool InputOverridesSelection(World world, int2 xy, MouseInput mi)
|
public override bool InputOverridesSelection(WorldRenderer wr, World world, int2 xy, MouseInput mi)
|
||||||
{
|
{
|
||||||
// Custom order generators always override selection
|
// Custom order generators always override selection
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
IRenderable[] renderables = null;
|
IRenderable[] renderables = null;
|
||||||
Rectangle[] bounds = null;
|
Rectangle[] bounds = null;
|
||||||
|
Rectangle mouseBounds = Rectangle.Empty;
|
||||||
for (var playerIndex = 0; playerIndex < frozenStates.Count; playerIndex++)
|
for (var playerIndex = 0; playerIndex < frozenStates.Count; playerIndex++)
|
||||||
{
|
{
|
||||||
var frozen = frozenStates[playerIndex].FrozenActor;
|
var frozen = frozenStates[playerIndex].FrozenActor;
|
||||||
@@ -139,6 +140,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
isRendering = true;
|
isRendering = true;
|
||||||
renderables = self.Render(wr).ToArray();
|
renderables = self.Render(wr).ToArray();
|
||||||
bounds = self.ScreenBounds(wr).ToArray();
|
bounds = self.ScreenBounds(wr).ToArray();
|
||||||
|
mouseBounds = self.MouseBounds(wr);
|
||||||
|
|
||||||
isRendering = false;
|
isRendering = false;
|
||||||
}
|
}
|
||||||
@@ -146,6 +148,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
frozen.NeedRenderables = false;
|
frozen.NeedRenderables = false;
|
||||||
frozen.Renderables = renderables;
|
frozen.Renderables = renderables;
|
||||||
frozen.ScreenBounds = bounds;
|
frozen.ScreenBounds = bounds;
|
||||||
|
frozen.MouseBounds = mouseBounds;
|
||||||
self.World.ScreenMap.AddOrUpdate(self.World.Players[playerIndex], frozen);
|
self.World.ScreenMap.AddOrUpdate(self.World.Players[playerIndex], frozen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits.Render
|
namespace OpenRA.Mods.Common.Traits.Render
|
||||||
@@ -16,17 +20,28 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
[Desc("Automatically calculates the screen map boundaries from the sprite size.")]
|
[Desc("Automatically calculates the screen map boundaries from the sprite size.")]
|
||||||
public class AutoRenderSizeInfo : ITraitInfo, Requires<RenderSpritesInfo>, IAutoRenderSizeInfo
|
public class AutoRenderSizeInfo : ITraitInfo, Requires<RenderSpritesInfo>, IAutoRenderSizeInfo
|
||||||
{
|
{
|
||||||
public object Create(ActorInitializer init) { return new AutoRenderSize(this); }
|
public object Create(ActorInitializer init) { return new AutoRenderSize(init.Self); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AutoRenderSize : IAutoRenderSize
|
public class AutoRenderSize : IAutoRenderSize, IMouseBounds
|
||||||
{
|
{
|
||||||
public AutoRenderSize(AutoRenderSizeInfo info) { }
|
readonly RenderSprites rs;
|
||||||
|
|
||||||
|
public AutoRenderSize(Actor self)
|
||||||
|
{
|
||||||
|
rs = self.Trait<RenderSprites>();
|
||||||
|
}
|
||||||
|
|
||||||
public int2 RenderSize(Actor self)
|
public int2 RenderSize(Actor self)
|
||||||
{
|
{
|
||||||
var rs = self.Trait<RenderSprites>();
|
|
||||||
return rs.AutoRenderSize(self);
|
return rs.AutoRenderSize(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle IMouseBounds.MouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return self.TraitsImplementing<IAutoMouseBounds>()
|
||||||
|
.Select(s => s.AutoMouseoverBounds(self, wr))
|
||||||
|
.FirstOrDefault(r => !r.IsEmpty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
@@ -22,7 +24,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public object Create(ActorInitializer init) { return new CustomRenderSize(this); }
|
public object Create(ActorInitializer init) { return new CustomRenderSize(this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CustomRenderSize : IAutoRenderSize
|
public class CustomRenderSize : IAutoRenderSize, IMouseBounds
|
||||||
{
|
{
|
||||||
readonly CustomRenderSizeInfo info;
|
readonly CustomRenderSizeInfo info;
|
||||||
public CustomRenderSize(CustomRenderSizeInfo info) { this.info = info; }
|
public CustomRenderSize(CustomRenderSizeInfo info) { this.info = info; }
|
||||||
@@ -31,5 +33,20 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
return new int2(info.CustomBounds[0], info.CustomBounds[1]);
|
return new int2(info.CustomBounds[0], info.CustomBounds[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle IMouseBounds.MouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
if (info.CustomBounds == null)
|
||||||
|
return Rectangle.Empty;
|
||||||
|
|
||||||
|
var size = new int2(info.CustomBounds[0], info.CustomBounds[1]);
|
||||||
|
|
||||||
|
var offset = -size / 2;
|
||||||
|
if (info.CustomBounds.Length > 2)
|
||||||
|
offset += new int2(info.CustomBounds[2], info.CustomBounds[3]);
|
||||||
|
|
||||||
|
var xy = wr.ScreenPxPosition(self.CenterPosition);
|
||||||
|
return new Rectangle(xy.X, xy.Y, size.X, size.Y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly RenderSpritesInfo Info;
|
||||||
readonly string faction;
|
readonly string faction;
|
||||||
readonly RenderSpritesInfo info;
|
|
||||||
readonly List<AnimationWrapper> anims = new List<AnimationWrapper>();
|
readonly List<AnimationWrapper> anims = new List<AnimationWrapper>();
|
||||||
string cachedImage;
|
string cachedImage;
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public RenderSprites(ActorInitializer init, RenderSpritesInfo info)
|
public RenderSprites(ActorInitializer init, RenderSpritesInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
Info = info;
|
||||||
faction = init.Contains<FactionInit>() ? init.Get<FactionInit, string>() : init.Self.Owner.Faction.InternalName;
|
faction = init.Contains<FactionInit>() ? init.Get<FactionInit, string>() : init.Self.Owner.Faction.InternalName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
if (cachedImage != null)
|
if (cachedImage != null)
|
||||||
return cachedImage;
|
return cachedImage;
|
||||||
|
|
||||||
return cachedImage = info.GetImage(self.Info, self.World.Map.Rules.Sequences, faction);
|
return cachedImage = Info.GetImage(self.Info, self.World.Map.Rules.Sequences, faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePalette()
|
public void UpdatePalette()
|
||||||
@@ -199,7 +199,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
a.CachePalette(wr, owner);
|
a.CachePalette(wr, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var r in a.Animation.Render(self, wr, a.PaletteReference, info.Scale))
|
foreach (var r in a.Animation.Render(self, wr, a.PaletteReference, Info.Scale))
|
||||||
yield return r;
|
yield return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
{
|
{
|
||||||
foreach (var a in anims)
|
foreach (var a in anims)
|
||||||
if (a.IsVisible)
|
if (a.IsVisible)
|
||||||
yield return a.Animation.ScreenBounds(self, wr, info.Scale);
|
yield return a.Animation.ScreenBounds(self, wr, Info.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ITick.Tick(Actor self)
|
void ITick.Tick(Actor self)
|
||||||
@@ -231,8 +231,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
// Use defaults
|
// Use defaults
|
||||||
if (palette == null)
|
if (palette == null)
|
||||||
{
|
{
|
||||||
palette = info.Palette ?? info.PlayerPalette;
|
palette = Info.Palette ?? Info.PlayerPalette;
|
||||||
isPlayerPalette = info.Palette == null;
|
isPlayerPalette = Info.Palette == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
anims.Add(new AnimationWrapper(anim, palette, isPlayerPalette));
|
anims.Add(new AnimationWrapper(anim, palette, isPlayerPalette));
|
||||||
@@ -281,7 +281,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
{
|
{
|
||||||
return anims.Where(b => b.IsVisible
|
return anims.Where(b => b.IsVisible
|
||||||
&& b.Animation.Animation.CurrentSequence != null)
|
&& b.Animation.Animation.CurrentSequence != null)
|
||||||
.Select(a => (a.Animation.Animation.Image.Size.XY * info.Scale).ToInt2())
|
.Select(a => (a.Animation.Animation.Image.Size.XY * Info.Scale).ToInt2())
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,11 +97,12 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly RenderVoxelsInfo Info;
|
||||||
|
|
||||||
readonly List<ModelAnimation> components = new List<ModelAnimation>();
|
readonly List<ModelAnimation> components = new List<ModelAnimation>();
|
||||||
readonly Dictionary<ModelAnimation, AnimationWrapper> wrappers = new Dictionary<ModelAnimation, AnimationWrapper>();
|
readonly Dictionary<ModelAnimation, AnimationWrapper> wrappers = new Dictionary<ModelAnimation, AnimationWrapper>();
|
||||||
|
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
readonly RenderVoxelsInfo info;
|
|
||||||
readonly BodyOrientation body;
|
readonly BodyOrientation body;
|
||||||
readonly WRot camera;
|
readonly WRot camera;
|
||||||
readonly WRot lightSource;
|
readonly WRot lightSource;
|
||||||
@@ -109,7 +110,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
public RenderVoxels(Actor self, RenderVoxelsInfo info)
|
public RenderVoxels(Actor self, RenderVoxelsInfo info)
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.info = info;
|
Info = info;
|
||||||
body = self.Trait<BodyOrientation>();
|
body = self.Trait<BodyOrientation>();
|
||||||
camera = new WRot(WAngle.Zero, body.CameraPitch - new WAngle(256), new WAngle(256));
|
camera = new WRot(WAngle.Zero, body.CameraPitch - new WAngle(256), new WAngle(256));
|
||||||
lightSource = new WRot(WAngle.Zero, new WAngle(256) - info.LightPitch, info.LightYaw);
|
lightSource = new WRot(WAngle.Zero, new WAngle(256) - info.LightPitch, info.LightYaw);
|
||||||
@@ -133,16 +134,16 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
{
|
{
|
||||||
if (initializePalettes)
|
if (initializePalettes)
|
||||||
{
|
{
|
||||||
var paletteName = info.Palette ?? info.PlayerPalette + self.Owner.InternalName;
|
var paletteName = Info.Palette ?? Info.PlayerPalette + self.Owner.InternalName;
|
||||||
colorPalette = wr.Palette(paletteName);
|
colorPalette = wr.Palette(paletteName);
|
||||||
normalsPalette = wr.Palette(info.NormalsPalette);
|
normalsPalette = wr.Palette(Info.NormalsPalette);
|
||||||
shadowPalette = wr.Palette(info.ShadowPalette);
|
shadowPalette = wr.Palette(Info.ShadowPalette);
|
||||||
initializePalettes = false;
|
initializePalettes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IRenderable[] { new ModelRenderable(
|
return new IRenderable[] { new ModelRenderable(
|
||||||
components, self.CenterPosition, 0, camera, info.Scale,
|
components, self.CenterPosition, 0, camera, Info.Scale,
|
||||||
lightSource, info.LightAmbientColor, info.LightDiffuseColor,
|
lightSource, Info.LightAmbientColor, Info.LightDiffuseColor,
|
||||||
colorPalette, normalsPalette, shadowPalette) };
|
colorPalette, normalsPalette, shadowPalette) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,10 +152,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
var pos = self.CenterPosition;
|
var pos = self.CenterPosition;
|
||||||
foreach (var c in components)
|
foreach (var c in components)
|
||||||
if (c.IsVisible)
|
if (c.IsVisible)
|
||||||
yield return c.ScreenBounds(pos, wr, info.Scale);
|
yield return c.ScreenBounds(pos, wr, Info.Scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Image { get { return info.Image ?? self.Info.Name; } }
|
public string Image { get { return Info.Image ?? self.Info.Name; } }
|
||||||
public void Add(ModelAnimation m)
|
public void Add(ModelAnimation m)
|
||||||
{
|
{
|
||||||
components.Add(m);
|
components.Add(m);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Graphics;
|
using OpenRA.Mods.Common.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -43,9 +44,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WithSpriteBody : PausableConditionalTrait<WithSpriteBodyInfo>, INotifyDamageStateChanged, INotifyBuildComplete
|
public class WithSpriteBody : PausableConditionalTrait<WithSpriteBodyInfo>, INotifyDamageStateChanged, INotifyBuildComplete, IAutoMouseBounds
|
||||||
{
|
{
|
||||||
public readonly Animation DefaultAnimation;
|
public readonly Animation DefaultAnimation;
|
||||||
|
readonly RenderSprites rs;
|
||||||
|
|
||||||
public WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info)
|
public WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info)
|
||||||
: this(init, info, () => 0) { }
|
: this(init, info, () => 0) { }
|
||||||
@@ -53,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
protected WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info, Func<int> baseFacing)
|
protected WithSpriteBody(ActorInitializer init, WithSpriteBodyInfo info, Func<int> baseFacing)
|
||||||
: base(info)
|
: base(info)
|
||||||
{
|
{
|
||||||
var rs = init.Self.Trait<RenderSprites>();
|
rs = init.Self.Trait<RenderSprites>();
|
||||||
|
|
||||||
Func<bool> paused = () => IsTraitPaused &&
|
Func<bool> paused = () => IsTraitPaused &&
|
||||||
DefaultAnimation.CurrentSequence.Name == NormalizeSequence(init.Self, Info.Sequence);
|
DefaultAnimation.CurrentSequence.Name == NormalizeSequence(init.Self, Info.Sequence);
|
||||||
@@ -125,5 +127,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
{
|
{
|
||||||
DamageStateChanged(self);
|
DamageStateChanged(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle IAutoMouseBounds.AutoMouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return DefaultAnimation != null ? DefaultAnimation.ScreenBounds(wr, self.CenterPosition, WVec.Zero, rs.Info.Scale) : Rectangle.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Graphics;
|
using OpenRA.Mods.Common.Graphics;
|
||||||
@@ -39,21 +40,24 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WithVoxelBody : ConditionalTrait<WithVoxelBodyInfo>, IAutoSelectionSize, IAutoRenderSize
|
public class WithVoxelBody : ConditionalTrait<WithVoxelBodyInfo>, IAutoSelectionSize, IAutoRenderSize, IAutoMouseBounds
|
||||||
{
|
{
|
||||||
readonly int2 size;
|
readonly int2 size;
|
||||||
|
readonly ModelAnimation modelAnimation;
|
||||||
|
readonly RenderVoxels rv;
|
||||||
|
|
||||||
public WithVoxelBody(Actor self, WithVoxelBodyInfo info)
|
public WithVoxelBody(Actor self, WithVoxelBodyInfo info)
|
||||||
: base(info)
|
: base(info)
|
||||||
{
|
{
|
||||||
var body = self.Trait<BodyOrientation>();
|
var body = self.Trait<BodyOrientation>();
|
||||||
var rv = self.Trait<RenderVoxels>();
|
rv = self.Trait<RenderVoxels>();
|
||||||
|
|
||||||
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||||
rv.Add(new ModelAnimation(model, () => WVec.Zero,
|
modelAnimation = new ModelAnimation(model, () => WVec.Zero,
|
||||||
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
() => new[] { body.QuantizeOrientation(self, self.Orientation) },
|
||||||
() => IsTraitDisabled, () => 0, info.ShowShadow));
|
() => IsTraitDisabled, () => 0, info.ShowShadow);
|
||||||
|
|
||||||
|
rv.Add(modelAnimation);
|
||||||
// Selection size
|
// Selection size
|
||||||
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
var rvi = self.Info.TraitInfo<RenderVoxelsInfo>();
|
||||||
var s = (int)(rvi.Scale * model.Size.Aggregate(Math.Max));
|
var s = (int)(rvi.Scale * model.Size.Aggregate(Math.Max));
|
||||||
@@ -62,5 +66,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
|
|
||||||
public int2 SelectionSize(Actor self) { return size; }
|
public int2 SelectionSize(Actor self) { return size; }
|
||||||
public int2 RenderSize(Actor self) { return size; }
|
public int2 RenderSize(Actor self) { return size; }
|
||||||
|
|
||||||
|
Rectangle IAutoMouseBounds.AutoMouseoverBounds(Actor self, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return modelAnimation.ScreenBounds(self.CenterPosition, wr, rv.Info.Scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,8 +229,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
var worldPixel = worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos);
|
var worldPixel = worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos);
|
||||||
var underCursor = world.ScreenMap.ActorsAt(worldPixel)
|
var underCursor = world.ScreenMap.ActorsAtMouse(worldPixel)
|
||||||
.Where(a => a.Info.HasTraitInfo<ITooltipInfo>() && !world.FogObscures(a))
|
.Where(a => a.Actor.Info.HasTraitInfo<ITooltipInfo>() && !world.FogObscures(a.Actor))
|
||||||
.WithHighestSelectionPriority(worldPixel);
|
.WithHighestSelectionPriority(worldPixel);
|
||||||
|
|
||||||
if (underCursor != null)
|
if (underCursor != null)
|
||||||
@@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, worldPixel)
|
var frozen = world.ScreenMap.FrozenActorsAtMouse(world.RenderPlayer, worldPixel)
|
||||||
.Where(a => a.TooltipInfo != null && a.IsValid)
|
.Where(a => a.TooltipInfo != null && a.IsValid)
|
||||||
.WithHighestSelectionPriority(worldPixel);
|
.WithHighestSelectionPriority(worldPixel);
|
||||||
|
|
||||||
|
|||||||
@@ -107,11 +107,11 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
if (!IsValidDragbox && World.Selection.Actors.Any() && !multiClick)
|
if (!IsValidDragbox && World.Selection.Actors.Any() && !multiClick)
|
||||||
{
|
{
|
||||||
var selectableActor = World.ScreenMap.ActorsAt(mousePos).Any(x =>
|
var selectableActor = World.ScreenMap.ActorsAtMouse(mousePos).Select(a => a.Actor).Any(x =>
|
||||||
x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x)));
|
x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x)));
|
||||||
|
|
||||||
var uog = (UnitOrderGenerator)World.OrderGenerator;
|
var uog = (UnitOrderGenerator)World.OrderGenerator;
|
||||||
if (!selectableActor || uog.InputOverridesSelection(World, mousePos, mi))
|
if (!selectableActor || uog.InputOverridesSelection(worldRenderer, World, mousePos, mi))
|
||||||
{
|
{
|
||||||
// Order units instead of selecting
|
// Order units instead of selecting
|
||||||
ApplyOrders(World, mi);
|
ApplyOrders(World, mi);
|
||||||
@@ -124,7 +124,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
if (multiClick)
|
if (multiClick)
|
||||||
{
|
{
|
||||||
var unit = World.ScreenMap.ActorsAt(mousePos)
|
var unit = World.ScreenMap.ActorsAtMouse(mousePos)
|
||||||
.WithHighestSelectionPriority(mousePos);
|
.WithHighestSelectionPriority(mousePos);
|
||||||
|
|
||||||
if (unit != null && unit.Owner == (World.RenderPlayer ?? World.LocalPlayer))
|
if (unit != null && unit.Owner == (World.RenderPlayer ?? World.LocalPlayer))
|
||||||
@@ -294,7 +294,8 @@ namespace OpenRA.Mods.Common.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 SelectActorsByOwnerAndSelectionClass(world.ScreenMap.ActorsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight), player, selectionClasses);
|
var actors = world.ScreenMap.ActorsInMouseBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight).Select(a => a.Actor);
|
||||||
|
return SelectActorsByOwnerAndSelectionClass(actors, player, selectionClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, Player player)
|
static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, Player player)
|
||||||
@@ -322,7 +323,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if ((a - b).Length <= Game.Settings.Game.SelectionDeadzone)
|
if ((a - b).Length <= Game.Settings.Game.SelectionDeadzone)
|
||||||
a = b;
|
a = b;
|
||||||
|
|
||||||
return world.ScreenMap.ActorsInBox(a, b)
|
return world.ScreenMap.ActorsInMouseBox(a, b)
|
||||||
|
.Select(x => x.Actor)
|
||||||
.Where(x => x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
|
.Where(x => x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
|
||||||
.SubsetWithHighestSelectionPriority();
|
.SubsetWithHighestSelectionPriority();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user