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

@@ -0,0 +1,158 @@
#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;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
public struct SelectionBarsRenderable : IRenderable
{
readonly WPos pos;
readonly Actor actor;
public SelectionBarsRenderable(Actor actor)
: this(actor.CenterPosition, actor) { }
public SelectionBarsRenderable(WPos pos, Actor actor)
{
this.pos = pos;
this.actor = actor;
}
public WPos Pos { get { return pos; } }
public float Scale { get { return 1f; } }
public PaletteReference Palette { get { return null; } }
public int ZOffset { get { return 0; } }
public bool IsDecoration { get { return true; } }
public IRenderable WithScale(float newScale) { return this; }
public IRenderable WithPalette(PaletteReference newPalette) { return this; }
public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(WVec vec) { return new SelectionBarsRenderable(pos + vec, actor); }
public IRenderable AsDecoration() { return this; }
void DrawExtraBars(WorldRenderer wr, float2 xy, float2 Xy)
{
foreach (var extraBar in actor.TraitsImplementing<ISelectionBar>())
{
var value = extraBar.GetValue();
if (value != 0)
{
xy.Y += (int)(4 / wr.Viewport.Zoom);
Xy.Y += (int)(4 / wr.Viewport.Zoom);
DrawSelectionBar(wr, xy, Xy, extraBar.GetValue(), extraBar.GetColor());
}
}
}
void DrawSelectionBar(WorldRenderer wr, float2 xy, float2 Xy, float value, Color barColor)
{
var c = Color.FromArgb(128, 30, 30, 30);
var c2 = Color.FromArgb(128, 10, 10, 10);
var p = new float2(0, -4 / wr.Viewport.Zoom);
var q = new float2(0, -3 / wr.Viewport.Zoom);
var r = new float2(0, -2 / wr.Viewport.Zoom);
var barColor2 = Color.FromArgb(255, barColor.R / 2, barColor.G / 2, barColor.B / 2);
var z = float2.Lerp(xy, Xy, value);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(xy + p, Xy + p, c, c);
wlr.DrawLine(xy + q, Xy + q, c2, c2);
wlr.DrawLine(xy + r, Xy + r, c, c);
wlr.DrawLine(xy + p, z + p, barColor2, barColor2);
wlr.DrawLine(xy + q, z + q, barColor, barColor);
wlr.DrawLine(xy + r, z + r, barColor2, barColor2);
}
Color GetHealthColor(Health health)
{
if (Game.Settings.Game.TeamHealthColors)
{
var isAlly = actor.Owner.IsAlliedWith(actor.World.LocalPlayer)
|| (actor.IsDisguised() && actor.World.LocalPlayer.IsAlliedWith(actor.EffectiveOwner.Owner));
return isAlly ? Color.LimeGreen : actor.Owner.NonCombatant ? Color.Tan : Color.Red;
}
else
return health.DamageState == DamageState.Critical ? Color.Red :
health.DamageState == DamageState.Heavy ? Color.Yellow : Color.LimeGreen;
}
void DrawHealthBar(WorldRenderer wr, Health health, float2 xy, float2 Xy)
{
if (health == null || health.IsDead)
return;
var c = Color.FromArgb(128, 30, 30, 30);
var c2 = Color.FromArgb(128, 10, 10, 10);
var p = new float2(0, -4 / wr.Viewport.Zoom);
var q = new float2(0, -3 / wr.Viewport.Zoom);
var r = new float2(0, -2 / wr.Viewport.Zoom);
var healthColor = GetHealthColor(health);
var healthColor2 = Color.FromArgb(
255,
healthColor.R / 2,
healthColor.G / 2,
healthColor.B / 2);
var z = float2.Lerp(xy, Xy, (float)health.HP / health.MaxHP);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(xy + p, Xy + p, c, c);
wlr.DrawLine(xy + q, Xy + q, c2, c2);
wlr.DrawLine(xy + r, Xy + r, c, c);
wlr.DrawLine(xy + p, z + p, healthColor2, healthColor2);
wlr.DrawLine(xy + q, z + q, healthColor, healthColor);
wlr.DrawLine(xy + r, z + r, healthColor2, healthColor2);
if (health.DisplayHp != health.HP)
{
var deltaColor = Color.OrangeRed;
var deltaColor2 = Color.FromArgb(
255,
deltaColor.R / 2,
deltaColor.G / 2,
deltaColor.B / 2);
var zz = float2.Lerp(xy, Xy, (float)health.DisplayHp / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor, deltaColor);
wlr.DrawLine(z + r, zz + r, deltaColor2, deltaColor2);
}
}
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
if (!actor.IsInWorld || actor.IsDead())
return;
var health = actor.TraitOrDefault<Health>();
var screenPos = wr.ScreenPxPosition(pos);
var bounds = actor.Bounds.Value;
bounds.Offset(screenPos.X, screenPos.Y);
var xy = new float2(bounds.Left, bounds.Top);
var Xy = new float2(bounds.Right, bounds.Top);
DrawHealthBar(wr, health, xy, Xy);
DrawExtraBars(wr, xy, Xy);
}
public void RenderDebugGeometry(WorldRenderer wr) {}
}
}

View File

@@ -0,0 +1,73 @@
#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;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
public struct SelectionBoxRenderable : IRenderable
{
readonly WPos pos;
readonly float scale;
readonly Rectangle bounds;
readonly Color color;
public SelectionBoxRenderable(Actor actor, Color color)
: this(actor.CenterPosition, actor.Bounds.Value, 1f, color) { }
public SelectionBoxRenderable(WPos pos, Rectangle bounds, float scale, Color color)
{
this.pos = pos;
this.bounds = bounds;
this.scale = scale;
this.color = color;
}
public WPos Pos { get { return pos; } }
public float Scale { get { return scale; } }
public PaletteReference Palette { get { return null; } }
public int ZOffset { get { return 0; } }
public bool IsDecoration { get { return true; } }
public IRenderable WithScale(float newScale) { return new SelectionBoxRenderable(pos, bounds, newScale, color); }
public IRenderable WithPalette(PaletteReference newPalette) { return this; }
public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(WVec vec) { return new SelectionBoxRenderable(pos + vec, bounds, scale, color); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
var screenPos = wr.ScreenPxPosition(pos);
var tl = screenPos + scale * new float2(bounds.Left, bounds.Top);
var br = screenPos + scale * new float2(bounds.Right, bounds.Bottom);
var tr = new float2(br.X, tl.Y);
var bl = new float2(tl.X, br.Y);
var u = new float2(4f / wr.Viewport.Zoom, 0);
var v = new float2(0, 4f / wr.Viewport.Zoom);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(tl + u, tl, color, color);
wlr.DrawLine(tl, tl + v, color, color);
wlr.DrawLine(tr, tr - u, color, color);
wlr.DrawLine(tr, tr + v, color, color);
wlr.DrawLine(bl, bl + u, color, color);
wlr.DrawLine(bl, bl - v, color, color);
wlr.DrawLine(br, br - u, color, color);
wlr.DrawLine(br, br - v, color, color);
}
public void RenderDebugGeometry(WorldRenderer wr) {}
}
}

View File

@@ -0,0 +1,62 @@
#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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
public struct TargetLineRenderable : IRenderable
{
readonly IEnumerable<WPos> waypoints;
readonly Color color;
public TargetLineRenderable(IEnumerable<WPos> waypoints, Color color)
{
this.waypoints = waypoints;
this.color = color;
}
public WPos Pos { get { return waypoints.First(); } }
public float Scale { get { return 1f; } }
public PaletteReference Palette { get { return null; } }
public int ZOffset { get { return 0; } }
public bool IsDecoration { get { return true; } }
public IRenderable WithScale(float newScale) { return new TargetLineRenderable(waypoints, color); }
public IRenderable WithPalette(PaletteReference newPalette) { return new TargetLineRenderable(waypoints, color); }
public IRenderable WithZOffset(int newOffset) { return new TargetLineRenderable(waypoints, color); }
public IRenderable OffsetBy(WVec vec) { return new TargetLineRenderable(waypoints.Select(w => w + vec), color); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
if (!waypoints.Any())
return;
var first = wr.ScreenPxPosition(waypoints.First());
var a = first;
foreach (var b in waypoints.Skip(1).Select(pos => wr.ScreenPxPosition(pos)))
{
Game.Renderer.WorldLineRenderer.DrawLine(a, b, color, color);
wr.DrawTargetMarker(color, b);
a = b;
}
wr.DrawTargetMarker(color, first);
}
public void RenderDebugGeometry(WorldRenderer wr) {}
}
}

View File

@@ -0,0 +1,61 @@
#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.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace OpenRA.Graphics
{
public struct UISpriteRenderable : IRenderable
{
readonly Sprite sprite;
readonly int2 screenPos;
readonly int zOffset;
readonly PaletteReference palette;
readonly float scale;
public UISpriteRenderable(Sprite sprite, int2 screenPos, int zOffset, PaletteReference palette, float scale)
{
this.sprite = sprite;
this.screenPos = screenPos;
this.zOffset = zOffset;
this.palette = palette;
this.scale = scale;
}
// Does not exist in the world, so a world positions don't make sense
public WPos Pos { get { return WPos.Zero; } }
public WVec Offset { get { return WVec.Zero; } }
public bool IsDecoration { get { return true; } }
public float Scale { get { return scale; } }
public PaletteReference Palette { get { return palette; } }
public int ZOffset { get { return zOffset; } }
public IRenderable WithScale(float newScale) { return new UISpriteRenderable(sprite, screenPos, zOffset, palette, newScale); }
public IRenderable WithPalette(PaletteReference newPalette) { return new UISpriteRenderable(sprite, screenPos, zOffset, newPalette, scale); }
public IRenderable WithZOffset(int newOffset) { return this; }
public IRenderable OffsetBy(WVec vec) { return this; }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
Game.Renderer.SpriteRenderer.DrawSprite(sprite, screenPos, palette, sprite.size * scale);
}
public void RenderDebugGeometry(WorldRenderer wr)
{
var offset = screenPos + sprite.offset;
Game.Renderer.LineRenderer.DrawRect(offset, offset + sprite.size, Color.Red);
}
}
}

View File

@@ -87,10 +87,13 @@ namespace OpenRA.Graphics
worldRenderables = worldRenderables.OrderBy(r => r, comparer);
// Effects are drawn on top of all actors
// TODO: Allow effects to be interleaved with actors
// HACK: Effects aren't interleaved with actors.
var effectRenderables = world.Effects
.SelectMany(e => e.Render(this));
if (world.OrderGenerator != null)
effectRenderables = effectRenderables.Concat(world.OrderGenerator.RenderAfterWorld(this, world));
// Iterating via foreach() copies the structs, so enumerate by index
var renderables = worldRenderables.Concat(effectRenderables).ToList();
@@ -124,9 +127,6 @@ namespace OpenRA.Graphics
if (a.Actor.IsInWorld && !a.Actor.Destroyed)
a.Trait.RenderAfterWorld(this, a.Actor);
if (world.OrderGenerator != null)
world.OrderGenerator.RenderAfterWorld(this, world);
var renderShroud = world.RenderPlayer != null ? world.RenderPlayer.Shroud : null;
foreach (var a in world.ActorsWithTrait<IRenderShroud>())
@@ -138,11 +138,25 @@ namespace OpenRA.Graphics
Game.Renderer.DisableScissor();
foreach (var g in world.Selection.Actors.Where(a => !a.Destroyed)
var overlayRenderables = world.Selection.Actors.Where(a => !a.Destroyed)
.SelectMany(a => a.TraitsImplementing<IPostRenderSelection>())
.GroupBy(prs => prs.GetType()))
foreach (var t in g)
t.RenderAfterWorld(this);
.SelectMany(t => t.RenderAfterWorld(this))
.ToList();
Game.Renderer.WorldVoxelRenderer.BeginFrame();
for (var i = 0; i < overlayRenderables.Count; i++)
overlayRenderables[i].BeforeRender(this);
Game.Renderer.WorldVoxelRenderer.EndFrame();
// HACK: Keep old grouping behaviour
foreach (var g in overlayRenderables.GroupBy(prs => prs.GetType()))
foreach (var r in g)
r.Render(this);
if (devTrait.Value != null && devTrait.Value.ShowDebugGeometry)
foreach (var g in overlayRenderables.GroupBy(prs => prs.GetType()))
foreach (var r in g)
r.RenderDebugGeometry(this);
if (!world.IsShellmap && Game.Settings.Game.AlwaysShowStatusBars)
{
@@ -157,35 +171,14 @@ namespace OpenRA.Graphics
Game.Renderer.Flush();
}
public void DrawSelectionBox(Actor a, Color c)
{
var pos = ScreenPxPosition(a.CenterPosition);
var bounds = a.Bounds.Value;
var tl = pos + new float2(bounds.Left, bounds.Top);
var br = pos + new float2(bounds.Right, bounds.Bottom);
var tr = new float2(br.X, tl.Y);
var bl = new float2(tl.X, br.Y);
var u = new float2(4f / Viewport.Zoom, 0);
var v = new float2(0, 4f / Viewport.Zoom);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(tl + u, tl, c, c);
wlr.DrawLine(tl, tl + v, c, c);
wlr.DrawLine(tr, tr - u, c, c);
wlr.DrawLine(tr, tr + v, c, c);
wlr.DrawLine(bl, bl + u, c, c);
wlr.DrawLine(bl, bl - v, c, c);
wlr.DrawLine(br, br - u, c, c);
wlr.DrawLine(br, br - v, c, c);
}
public void DrawRollover(Actor unit)
{
var selectable = unit.TraitOrDefault<Selectable>();
if (selectable != null)
selectable.DrawRollover(this);
{
if (selectable.Info.Selectable)
new SelectionBarsRenderable(unit).Render(this);
}
}
public void DrawRangeCircle(WPos pos, WRange range, Color c)
@@ -199,17 +192,6 @@ namespace OpenRA.Graphics
}
}
public void DrawRangeCircleWithContrast(WPos pos, WRange range, Color fg, Color bg)
{
var wlr = Game.Renderer.WorldLineRenderer;
var oldWidth = wlr.LineWidth;
wlr.LineWidth = 3;
DrawRangeCircle(pos, range, bg);
wlr.LineWidth = 1;
DrawRangeCircle(pos, range, fg);
wlr.LineWidth = oldWidth;
}
public void DrawTargetMarker(Color c, float2 location)
{
var tl = new float2(-1 / Viewport.Zoom, -1 / Viewport.Zoom);

View File

@@ -237,6 +237,10 @@
<Compile Include="Sound\OpenAlSound.cs" />
<Compile Include="Sound\NullSound.cs" />
<Compile Include="Effects\SpriteEffect.cs" />
<Compile Include="Graphics\SelectionBoxRenderable.cs" />
<Compile Include="Graphics\SelectionBarsRenderable.cs" />
<Compile Include="Graphics\TargetLineRenderable.cs" />
<Compile Include="Graphics\UISpriteRenderable.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileSystem\D2kSoundResources.cs" />

View File

@@ -65,7 +65,7 @@ namespace OpenRA.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.Map.Contains(xy) ? cursor : "generic-blocked"; }
}
}

View File

@@ -18,7 +18,7 @@ namespace OpenRA
IEnumerable<Order> Order(World world, CPos xy, MouseInput mi);
void Tick(World world);
IEnumerable<IRenderable> Render(WorldRenderer wr, World world);
void RenderAfterWorld(WorldRenderer wr, World world);
IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world);
string GetCursor(World world, CPos xy, MouseInput mi);
}
}

View File

@@ -52,7 +52,7 @@ namespace OpenRA.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) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi)
{

View File

@@ -58,25 +58,21 @@ namespace OpenRA.Traits
lifetime = Info.Ticks;
}
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
var force = Game.GetModifierKeys().HasModifier(Modifiers.Alt);
if ((lifetime <= 0 || --lifetime <= 0) && !force)
return;
yield break;
if (targets == null || targets.Count == 0)
return;
yield break;
var from = wr.ScreenPxPosition(self.CenterPosition);
foreach (var target in targets)
{
if (target.Type == TargetType.Invalid)
continue;
var to = wr.ScreenPxPosition(target.CenterPosition);
Game.Renderer.WorldLineRenderer.DrawLine(from, to, c, c);
wr.DrawTargetMarker(c, from);
wr.DrawTargetMarker(c, to);
yield return new TargetLineRenderable(new [] { self.CenterPosition, target.CenterPosition }, c);
}
}

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,6 +8,7 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
@@ -35,160 +36,32 @@ namespace OpenRA.Traits
Info = info;
}
public void RenderAfterWorld(WorldRenderer wr)
IEnumerable<WPos> ActivityTargetPath()
{
if (!Info.Selectable)
return;
var pos = wr.ScreenPxPosition(self.CenterPosition);
var bounds = self.Bounds.Value;
bounds.Offset(pos.X, pos.Y);
var xy = new float2(bounds.Left, bounds.Top);
var Xy = new float2(bounds.Right, bounds.Top);
wr.DrawSelectionBox(self, Color.White);
DrawHealthBar(wr, xy, Xy);
DrawExtraBars(wr, xy, Xy);
DrawUnitPath(wr);
}
public void DrawRollover(WorldRenderer wr)
{
if (!Info.Selectable)
return;
var pos = wr.ScreenPxPosition(self.CenterPosition);
var bounds = self.Bounds.Value;
bounds.Offset(pos.X, pos.Y);
var xy = new float2(bounds.Left, bounds.Top);
var Xy = new float2(bounds.Right, bounds.Top);
DrawHealthBar(wr, xy, Xy);
DrawExtraBars(wr, xy, Xy);
}
void DrawExtraBars(WorldRenderer wr, float2 xy, float2 Xy)
{
foreach (var extraBar in self.TraitsImplementing<ISelectionBar>())
{
var value = extraBar.GetValue();
if (value != 0)
{
xy.Y += (int)(4 / wr.Viewport.Zoom);
Xy.Y += (int)(4 / wr.Viewport.Zoom);
DrawSelectionBar(wr, xy, Xy, extraBar.GetValue(), extraBar.GetColor());
}
}
}
void DrawSelectionBar(WorldRenderer wr, float2 xy, float2 Xy, float value, Color barColor)
{
if (!self.IsInWorld)
return;
var health = self.TraitOrDefault<Health>();
if (health == null || health.IsDead) return;
var c = Color.FromArgb(128, 30, 30, 30);
var c2 = Color.FromArgb(128, 10, 10, 10);
var p = new float2(0, -4 / wr.Viewport.Zoom);
var q = new float2(0, -3 / wr.Viewport.Zoom);
var r = new float2(0, -2 / wr.Viewport.Zoom);
var barColor2 = Color.FromArgb(255, barColor.R / 2, barColor.G / 2, barColor.B / 2);
var z = float2.Lerp(xy, Xy, value);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(xy + p, Xy + p, c, c);
wlr.DrawLine(xy + q, Xy + q, c2, c2);
wlr.DrawLine(xy + r, Xy + r, c, c);
wlr.DrawLine(xy + p, z + p, barColor2, barColor2);
wlr.DrawLine(xy + q, z + q, barColor, barColor);
wlr.DrawLine(xy + r, z + r, barColor2, barColor2);
}
void DrawHealthBar(WorldRenderer wr, float2 xy, float2 Xy)
{
if (!self.IsInWorld) return;
var health = self.TraitOrDefault<Health>();
if (health == null || health.IsDead) return;
var c = Color.FromArgb(128, 30, 30, 30);
var c2 = Color.FromArgb(128, 10, 10, 10);
var p = new float2(0, -4 / wr.Viewport.Zoom);
var q = new float2(0, -3 / wr.Viewport.Zoom);
var r = new float2(0, -2 / wr.Viewport.Zoom);
var healthColor = GetHealthColor(health);
var healthColor2 = Color.FromArgb(
255,
healthColor.R / 2,
healthColor.G / 2,
healthColor.B / 2);
var z = float2.Lerp(xy, Xy, (float)health.HP / health.MaxHP);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(xy + p, Xy + p, c, c);
wlr.DrawLine(xy + q, Xy + q, c2, c2);
wlr.DrawLine(xy + r, Xy + r, c, c);
wlr.DrawLine(xy + p, z + p, healthColor2, healthColor2);
wlr.DrawLine(xy + q, z + q, healthColor, healthColor);
wlr.DrawLine(xy + r, z + r, healthColor2, healthColor2);
if (health.DisplayHp != health.HP)
{
var deltaColor = Color.OrangeRed;
var deltaColor2 = Color.FromArgb(
255,
deltaColor.R / 2,
deltaColor.G / 2,
deltaColor.B / 2);
var zz = float2.Lerp(xy, Xy, (float)health.DisplayHp / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor, deltaColor);
wlr.DrawLine(z + r, zz + r, deltaColor2, deltaColor2);
}
}
void DrawUnitPath(WorldRenderer wr)
{
if (self.World.LocalPlayer == null || !self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug)
return;
if (!self.IsInWorld || self.IsDead())
yield break;
var activity = self.GetCurrentActivity();
if (activity != null)
{
var targets = activity.GetTargets(self);
var start = wr.ScreenPxPosition(self.CenterPosition);
yield return self.CenterPosition;
var c = Color.Green;
foreach (var stp in targets.Where(t => t.Type != TargetType.Invalid).Select(pos => wr.ScreenPxPosition(pos.CenterPosition)))
{
Game.Renderer.WorldLineRenderer.DrawLine(start, stp, c, c);
wr.DrawTargetMarker(c, stp);
start = stp;
}
foreach (var t in targets.Where(t => t.Type != TargetType.Invalid))
yield return t.CenterPosition;
}
}
Color GetHealthColor(Health health)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (Game.Settings.Game.TeamHealthColors)
{
var isAlly = self.Owner.IsAlliedWith(self.World.LocalPlayer)
|| (self.IsDisguised() && self.World.LocalPlayer.IsAlliedWith(self.EffectiveOwner.Owner));
return isAlly ? Color.LimeGreen : self.Owner.NonCombatant ? Color.Tan : Color.Red;
}
else
return health.DamageState == DamageState.Critical ? Color.Red :
health.DamageState == DamageState.Heavy ? Color.Yellow : Color.LimeGreen;
if (!Info.Selectable)
yield break;
yield return new SelectionBoxRenderable(self, Color.White);
yield return new SelectionBarsRenderable(self);
if (self.World.LocalPlayer != null && self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug)
yield return new TargetLineRenderable(ActivityTargetPath(), Color.Green);
}
}
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
@@ -35,51 +36,56 @@ namespace OpenRA.Traits
Info = info;
}
public void RenderAfterWorld(WorldRenderer wr)
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr)
{
if (self.World.FogObscures(self))
return;
yield break;
var b = self.Bounds.Value;
var pos = wr.ScreenPxPosition(self.CenterPosition);
var bounds = self.Bounds.Value;
bounds.Offset(pos.X, pos.Y);
var tl = wr.Viewport.WorldToViewPx(pos + new int2(b.Left, b.Top));
var bl = wr.Viewport.WorldToViewPx(pos + new int2(b.Left, b.Bottom));
var tm = wr.Viewport.WorldToViewPx(pos + new int2((b.Left + b.Right) / 2, b.Top));
var xy = new int2(bounds.Left, bounds.Top);
var xY = new int2(bounds.Left, bounds.Bottom);
foreach (var r in DrawControlGroup(wr, self, tl))
yield return r;
DrawControlGroup(wr, self, xy);
DrawPips(wr, self, xY);
DrawTags(wr, self, new int2((bounds.Left + bounds.Right) / 2, bounds.Top));
foreach (var r in DrawPips(wr, self, bl))
yield return r;
foreach (var r in DrawTags(wr, self, tm))
yield return r;
}
void DrawControlGroup(WorldRenderer wr, Actor self, int2 basePosition)
IEnumerable<IRenderable> DrawControlGroup(WorldRenderer wr, Actor self, int2 basePosition)
{
var group = self.World.Selection.GetControlGroupForActor(self);
if (group == null) return;
if (group == null)
yield break;
var pipImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette);
pipImages.PlayFetchIndex("groups", () => (int)group);
pipImages.Tick();
var pos = wr.Viewport.WorldToViewPx(basePosition) - (0.5f * pipImages.Image.size).ToInt2() + new int2(9, 5);
Game.Renderer.SpriteRenderer.DrawSprite(pipImages.Image, pos, pal);
var pos = basePosition - (0.5f * pipImages.Image.size).ToInt2() + new int2(9, 5);
yield return new UISpriteRenderable(pipImages.Image, pos, 0, pal, 1f);
}
void DrawPips(WorldRenderer wr, Actor self, int2 basePosition)
IEnumerable<IRenderable> DrawPips(WorldRenderer wr, Actor self, int2 basePosition)
{
if (!self.Owner.IsAlliedWith(self.World.RenderPlayer))
return;
yield break;
var pipSources = self.TraitsImplementing<IPips>();
if (!pipSources.Any())
return;
yield break;
var pipImages = new Animation(self.World, "pips");
pipImages.PlayRepeating(pipStrings[0]);
var pipSize = pipImages.Image.size.ToInt2();
var pipxyBase = wr.Viewport.WorldToViewPx(basePosition) + new int2(1 - pipSize.X / 2, - (3 + pipSize.Y / 2));
var pipxyBase = basePosition + new int2(1 - pipSize.X / 2, - (3 + pipSize.Y / 2));
var pipxyOffset = new int2(0, 0);
var pal = wr.Palette(Info.Palette);
var width = self.Bounds.Value.Width;
@@ -101,7 +107,7 @@ namespace OpenRA.Traits
pipImages.PlayRepeating(pipStrings[(int)pip]);
pipxyOffset += new int2(pipSize.X, 0);
Game.Renderer.SpriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, pal);
yield return new UISpriteRenderable(pipImages.Image, pipxyBase + pipxyOffset, 0, pal, 1f);
}
// Increment row
@@ -110,15 +116,14 @@ namespace OpenRA.Traits
}
}
void DrawTags(WorldRenderer wr, Actor self, int2 basePosition)
IEnumerable<IRenderable> DrawTags(WorldRenderer wr, Actor self, int2 basePosition)
{
if (!self.Owner.IsAlliedWith(self.World.RenderPlayer))
return;
yield break;
var tagImages = new Animation(self.World, "pips");
var pal = wr.Palette(Info.Palette);
var tagxyOffset = new int2(0, 6);
var tagBase = wr.Viewport.WorldToViewPx(basePosition);
foreach (var tags in self.TraitsImplementing<ITags>())
{
@@ -128,8 +133,8 @@ namespace OpenRA.Traits
continue;
tagImages.PlayRepeating(tagStrings[(int)tag]);
var pos = tagBase + tagxyOffset - (0.5f * tagImages.Image.size).ToInt2();
Game.Renderer.SpriteRenderer.DrawSprite(tagImages.Image, pos, pal);
var pos = basePosition + tagxyOffset - (0.5f * tagImages.Image.size).ToInt2();
yield return new UISpriteRenderable(tagImages.Image, pos, 0, pal, 1f);
// Increment row
tagxyOffset.Y += 8;

View File

@@ -226,7 +226,7 @@ namespace OpenRA.Traits
public interface IPostRender { void RenderAfterWorld(WorldRenderer wr, Actor self); }
public interface IRenderShroud { void RenderShroud(WorldRenderer wr, Shroud shroud); }
public interface IPostRenderSelection { void RenderAfterWorld(WorldRenderer wr); }
public interface IPostRenderSelection { IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr); }
public interface IBodyOrientation
{
WAngle CameraPitch { get; }

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"; }
}
}