Merge pull request #6040 from pchote/more-renderables

Convert RenderAfterWorld to use Renderables.
This commit is contained in:
Matthias Mailänder
2014-07-26 07:28:53 +02:00
31 changed files with 619 additions and 298 deletions

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -8,8 +8,10 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
@@ -61,16 +63,16 @@ namespace OpenRA.Mods.RA.Buildings
return self.Owner == self.World.RenderPlayer || (allyBuildRadius && self.Owner.IsAlliedWith(self.World.RenderPlayer));
}
// Range circle
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
// Visible to player and allies
if (!ValidRenderPlayer())
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
self.CenterPosition,
WRange.FromCells(Info.Range),
0,
Color.FromArgb(128, Ready() ? Color.White : Color.Red),
Color.FromArgb(96, Color.Black)
);

View File

@@ -0,0 +1,59 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 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.Drawing;
using OpenRA.Graphics;
namespace OpenRA.Mods.RA.Graphics
{
public struct RangeCircleRenderable : IRenderable
{
readonly WPos centerPosition;
readonly WRange radius;
readonly int zOffset;
readonly Color color;
readonly Color contrastColor;
public RangeCircleRenderable(WPos centerPosition, WRange radius, int zOffset, Color color, Color contrastColor)
{
this.centerPosition = centerPosition;
this.radius = radius;
this.zOffset = zOffset;
this.color = color;
this.contrastColor = contrastColor;
}
public WPos Pos { get { return centerPosition; } }
public float Scale { get { return 1f; } }
public PaletteReference Palette { get { return null; } }
public int ZOffset { get { return zOffset; } }
public bool IsDecoration { get { return true; } }
public IRenderable WithScale(float newScale) { return new RangeCircleRenderable(centerPosition, radius, zOffset, color, contrastColor); }
public IRenderable WithPalette(PaletteReference newPalette) { return new RangeCircleRenderable(centerPosition, radius, zOffset, color, contrastColor); }
public IRenderable WithZOffset(int newOffset) { return new RangeCircleRenderable(centerPosition, radius, newOffset, color, contrastColor); }
public IRenderable OffsetBy(WVec vec) { return new RangeCircleRenderable(centerPosition + vec, radius, zOffset, color, contrastColor); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
var wlr = Game.Renderer.WorldLineRenderer;
var oldWidth = wlr.LineWidth;
wlr.LineWidth = 3;
wr.DrawRangeCircle(centerPosition, radius, contrastColor);
wlr.LineWidth = 1;
wr.DrawRangeCircle(centerPosition, radius, color);
wlr.LineWidth = oldWidth;
}
public void RenderDebugGeometry(WorldRenderer wr) {}
}
}

View File

@@ -79,7 +79,7 @@ namespace OpenRA.Mods.RA
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi)
{

View File

@@ -114,15 +114,15 @@ namespace OpenRA.Mods.RA
yield return new CPos(i, j);
}
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.Owner != self.World.LocalPlayer || Minefield == null)
return;
yield break;
var pal = wr.Palette("terrain");
foreach (var c in Minefield)
new SpriteRenderable(tile, self.World.Map.CenterOfCell(c),
WVec.Zero, -511, pal, 1f, true).Render(wr);
yield return new SpriteRenderable(tile, self.World.Map.CenterOfCell(c),
WVec.Zero, -511, pal, 1f, true);
}
class MinefieldOrderGenerator : IOrderGenerator
@@ -170,10 +170,10 @@ namespace OpenRA.Mods.RA
CPos lastMousePos;
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
if (!minelayer.IsInWorld)
return;
yield break;
var movement = minelayer.Trait<IPositionable>();
var minefield = GetMinefieldCells(minefieldStart, lastMousePos,
@@ -183,8 +183,8 @@ namespace OpenRA.Mods.RA
foreach (var c in minefield)
{
var tile = movement.CanEnterCell(c) ? tileOk : tileBlocked;
new SpriteRenderable(tile, world.Map.CenterOfCell(c),
WVec.Zero, -511, pal, 1f, true).Render(wr);
yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c),
WVec.Zero, -511, pal, 1f, true);
}
}

View File

@@ -530,6 +530,7 @@
<Compile Include="Air\FlyAwayOnIdle.cs" />
<Compile Include="Buildings\ClonesProducedUnits.cs" />
<Compile Include="Cloneable.cs" />
<Compile Include="Graphics\RangeCircleRenderable.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA.Orders
public virtual void Tick(World world) { }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return !world.ShroudObscures(xy) ? "ability" : "generic-blocked"; }
}
}

View File

@@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA.Orders
public void Tick(World world) {}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
var topLeft = xy - FootprintUtils.AdjustForBuildingSize(BuildingInfo);
@@ -89,7 +89,8 @@ namespace OpenRA.Mods.RA.Orders
var actorInfo = rules.Actors[Building];
foreach (var dec in actorInfo.Traits.WithInterface<IPlaceBuildingDecoration>())
dec.Render(wr, world, actorInfo, world.Map.CenterOfCell(xy));
foreach (var r in dec.Render(wr, world, actorInfo, world.Map.CenterOfCell(xy)))
yield return r;
var cells = new Dictionary<CPos, bool>();
// Linebuild for walls.
@@ -119,7 +120,7 @@ namespace OpenRA.Mods.RA.Orders
var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, BuildingInfo) - WPos.Zero;
foreach (var r in preview)
r.OffsetBy(offset).Render(wr);
yield return r.OffsetBy(offset);
var res = world.WorldActor.Trait<ResourceLayer>();
var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft);
@@ -131,8 +132,8 @@ namespace OpenRA.Mods.RA.Orders
foreach (var c in cells)
{
var tile = c.Value ? buildOk : buildBlocked;
new SpriteRenderable(tile, world.Map.CenterOfCell(c.Key),
WVec.Zero, -511, pal, 1f, true).Render(wr);
yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c.Key),
WVec.Zero, -511, pal, 1f, true);
}
}

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Orders
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi)
{

View File

@@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Orders
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi)
{

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
@@ -172,17 +173,18 @@ namespace OpenRA.Mods.RA
yield break;
}
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
if (!self.IsInWorld || self.Owner != self.World.LocalPlayer)
return;
yield break;
if (!self.Trait<PortableChrono>().Info.HasDistanceLimit)
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
self.CenterPosition,
WRange.FromCells(self.Trait<PortableChrono>().Info.MaxDistance),
0,
Color.FromArgb(128, Color.LawnGreen),
Color.FromArgb(96, Color.Black)
);

View File

@@ -9,6 +9,7 @@
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Activities;
@@ -23,13 +24,14 @@ namespace OpenRA.Mods.RA.Render
public override object Create(ActorInitializer init) { return new RenderBuilding(init, this);}
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
{
if (!ai.Traits.Get<BuildingInfo>().RequiresBaseProvider)
return;
yield break;
foreach (var a in w.ActorsWithTrait<BaseProvider>())
a.Trait.RenderAfterWorld(wr);
foreach (var r in a.Trait.RenderAfterWorld(wr))
yield return r;
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -8,8 +8,10 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -25,16 +27,18 @@ namespace OpenRA.Mods.RA
public RenderDetectionCircle(Actor self) { this.self = self; }
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.Owner != self.World.LocalPlayer)
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
self.CenterPosition,
WRange.FromCells(self.Info.Traits.Get<DetectCloakedInfo>().Range),
0,
Color.FromArgb(128, Color.LimeGreen),
Color.FromArgb(96, Color.Black));
Color.FromArgb(96, Color.Black)
);
}
}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -8,8 +8,10 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
@@ -17,19 +19,36 @@ namespace OpenRA.Mods.RA
//todo: remove all the Render*Circle duplication
class RenderJammerCircleInfo : ITraitInfo, IPlaceBuildingDecoration
{
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
{
var jamsMissiles = ai.Traits.GetOrDefault<JamsMissilesInfo>();
if (jamsMissiles != null)
RenderJammerCircle.DrawRangeCircle(wr, centerPosition, jamsMissiles.Range, Color.Red);
{
yield return new RangeCircleRenderable(
centerPosition,
WRange.FromCells(jamsMissiles.Range),
0,
Color.FromArgb(128, Color.Red),
Color.FromArgb(96, Color.Black)
);
}
var jamsRadar = ai.Traits.GetOrDefault<JamsRadarInfo>();
if (jamsRadar != null)
RenderJammerCircle.DrawRangeCircle(wr, centerPosition, jamsRadar.Range, Color.Blue);
{
yield return new RangeCircleRenderable(
centerPosition,
WRange.FromCells(jamsRadar.Range),
0,
Color.FromArgb(128, Color.Blue),
Color.FromArgb(96, Color.Black)
);
}
foreach (var a in w.ActorsWithTrait<RenderJammerCircle>())
if (a.Actor.Owner == a.Actor.World.LocalPlayer)
a.Trait.RenderAfterWorld(wr);
foreach (var r in a.Trait.RenderAfterWorld(wr))
yield return r;
}
public object Create(ActorInitializer init) { return new RenderJammerCircle(init.self); }
@@ -41,28 +60,34 @@ namespace OpenRA.Mods.RA
public RenderJammerCircle(Actor self) { this.self = self; }
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.Owner != self.World.LocalPlayer)
return;
yield break;
var jamsMissiles = self.Info.Traits.GetOrDefault<JamsMissilesInfo>();
if (jamsMissiles != null)
DrawRangeCircle(wr, self.CenterPosition, jamsMissiles.Range, Color.Red);
{
yield return new RangeCircleRenderable(
self.CenterPosition,
WRange.FromCells(jamsMissiles.Range),
0,
Color.FromArgb(128, Color.Red),
Color.FromArgb(96, Color.Black)
);
}
var jamsRadar = self.Info.Traits.GetOrDefault<JamsRadarInfo>();
if (jamsRadar != null)
DrawRangeCircle(wr, self.CenterPosition, jamsRadar.Range, Color.Blue);
}
public static void DrawRangeCircle(WorldRenderer wr, WPos pos, int range, Color color)
{
wr.DrawRangeCircleWithContrast(
pos,
WRange.FromCells(range),
Color.FromArgb(128, color),
Color.FromArgb(96, Color.Black)
);
{
yield return new RangeCircleRenderable(
self.CenterPosition,
WRange.FromCells(jamsRadar.Range),
0,
Color.FromArgb(128, Color.Blue),
Color.FromArgb(96, Color.Black)
);
}
}
}
}

View File

@@ -8,16 +8,18 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public interface IPlaceBuildingDecoration
{
void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition);
IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition);
}
[Desc("Draw a circle indicating my weapon's range.")]
@@ -28,7 +30,7 @@ namespace OpenRA.Mods.RA
[Desc("Range to draw if no armaments are available")]
public readonly WRange FallbackRange = WRange.Zero;
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
{
var armaments = ai.Traits.WithInterface<ArmamentInfo>();
var range = FallbackRange;
@@ -37,11 +39,12 @@ namespace OpenRA.Mods.RA
range = armaments.Select(a => w.Map.Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max();
if (range == WRange.Zero)
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
centerPosition,
range,
0,
Color.FromArgb(128, Color.Yellow),
Color.FromArgb(96, Color.Black)
);
@@ -49,7 +52,8 @@ namespace OpenRA.Mods.RA
foreach (var a in w.ActorsWithTrait<RenderRangeCircle>())
if (a.Actor.Owner == a.Actor.World.LocalPlayer)
if (a.Actor.Info.Traits.Get<RenderRangeCircleInfo>().RangeCircleType == RangeCircleType)
a.Trait.RenderAfterWorld(wr);
foreach (var r in a.Trait.RenderAfterWorld(wr))
yield return r;
}
public object Create(ActorInitializer init) { return new RenderRangeCircle(init.self); }
@@ -66,14 +70,15 @@ namespace OpenRA.Mods.RA
attack = self.Trait<AttackBase>();
}
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.Owner != self.World.LocalPlayer)
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
self.CenterPosition,
attack.GetMaximumRange(),
0,
Color.FromArgb(128, Color.Yellow),
Color.FromArgb(96, Color.Black)
);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 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,
@@ -8,26 +8,30 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class RenderShroudCircleInfo : ITraitInfo, IPlaceBuildingDecoration
{
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
public IEnumerable<IRenderable> Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
{
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
centerPosition,
ai.Traits.Get<CreatesShroudInfo>().Range,
0,
Color.FromArgb(128, Color.Cyan),
Color.FromArgb(96, Color.Black)
);
foreach (var a in w.ActorsWithTrait<RenderShroudCircle>())
if (a.Actor.Owner == a.Actor.World.LocalPlayer)
a.Trait.RenderAfterWorld(wr);
foreach (var r in a.Trait.RenderAfterWorld(wr))
yield return r;
}
public object Create(ActorInitializer init) { return new RenderShroudCircle(init.self); }
@@ -39,14 +43,15 @@ namespace OpenRA.Mods.RA
public RenderShroudCircle(Actor self) { this.self = self; }
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.Owner != self.World.LocalPlayer)
return;
yield break;
wr.DrawRangeCircleWithContrast(
yield return new RangeCircleRenderable(
self.CenterPosition,
self.Info.Traits.Get<CreatesShroudInfo>().Range,
0,
Color.FromArgb(128, Color.Cyan),
Color.FromArgb(96, Color.Black)
);

View File

@@ -121,13 +121,14 @@ namespace OpenRA.Mods.RA
world.CancelInputMode();
}
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
var targetUnits = power.UnitsInRange(xy);
foreach (var unit in targetUnits)
if (manager.self.Owner.Shroud.IsTargetable(unit))
wr.DrawSelectionBox(unit, Color.Red);
yield return new SelectionBoxRenderable(unit, Color.Red);
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)
@@ -203,11 +204,11 @@ namespace OpenRA.Mods.RA
world.CancelInputMode();
}
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
foreach (var unit in power.UnitsInRange(sourceLocation))
if (manager.self.Owner.Shroud.IsTargetable(unit))
wr.DrawSelectionBox(unit, Color.Red);
yield return new SelectionBoxRenderable(unit, Color.Red);
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)

View File

@@ -98,11 +98,11 @@ namespace OpenRA.Mods.RA
world.CancelInputMode();
}
public void RenderAfterWorld(WorldRenderer wr, World world)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world)
{
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
foreach (var unit in power.UnitsInRange(xy))
wr.DrawSelectionBox(unit, Color.Red);
yield return new SelectionBoxRenderable(unit, Color.Red);
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world)

View File

@@ -258,7 +258,7 @@ namespace OpenRA.Mods.RA
}
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? cursor : "generic-blocked"; }
}
}