Merge pull request #6029 from pchote/gametomods

Move *Renderables and Render* out of Game.
This commit is contained in:
Matthias Mailänder
2014-07-23 06:54:42 +02:00
34 changed files with 56 additions and 21 deletions

View File

@@ -9,6 +9,7 @@
#endregion
using OpenRA.Graphics;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings

View File

@@ -10,6 +10,7 @@
using OpenRA.Effects;
using OpenRA.Traits;
using OpenRA.Mods.RA.Render;
namespace OpenRA.Mods.Cnc
{

View File

@@ -13,7 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
{
public class LaysTerrainInfo : ITraitInfo, Requires<BuildingInfo>, Requires<RenderSpritesInfo>
public class LaysTerrainInfo : ITraitInfo, Requires<BuildingInfo>
{
[Desc("The terrain template to place. If the template is PickAny, then" +
"the actor footprint will be filled with this tile.")]

View File

@@ -9,6 +9,7 @@
#endregion
using OpenRA.Graphics;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
namespace OpenRA.Mods.RA

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Render;
using OpenRA.Primitives;
using OpenRA.Traits;

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Mods.RA.Orders;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
namespace OpenRA.Mods.RA

View File

@@ -15,6 +15,7 @@ using System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Effects

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
namespace OpenRA.Mods.RA.Effects
{

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using OpenRA.Effects;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
namespace OpenRA.Mods.RA.Effects
{

View File

@@ -13,6 +13,7 @@ using System.Drawing;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
namespace OpenRA.Mods.RA.Effects
{

View File

@@ -14,6 +14,7 @@ using System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Effects

View File

@@ -0,0 +1,60 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 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 BeamRenderable : IRenderable
{
readonly WPos pos;
readonly int zOffset;
readonly WVec length;
readonly Color color;
readonly float width;
public BeamRenderable(WPos pos, int zOffset, WVec length, float width, Color color)
{
this.pos = pos;
this.zOffset = zOffset;
this.length = length;
this.color = color;
this.width = width;
}
public WPos Pos { get { return pos; } }
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 BeamRenderable(pos, zOffset, length, width, color); }
public IRenderable WithPalette(PaletteReference newPalette) { return new BeamRenderable(pos, zOffset, length, width, color); }
public IRenderable WithZOffset(int newOffset) { return new BeamRenderable(pos, zOffset, length, width, color); }
public IRenderable OffsetBy(WVec vec) { return new BeamRenderable(pos + vec, zOffset, length, width, color); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
var wlr = Game.Renderer.WorldLineRenderer;
var src = wr.ScreenPosition(pos);
var dest = wr.ScreenPosition(pos + length);
var oldWidth = wlr.LineWidth;
wlr.LineWidth = wr.Viewport.Zoom * width;
wlr.DrawLine(src, dest, color, color);
wlr.LineWidth = oldWidth;
}
public void RenderDebugGeometry(WorldRenderer wr) {}
}
}

View File

@@ -0,0 +1,120 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 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 System.Linq;
using OpenRA.Graphics;
namespace OpenRA.Mods.RA.Graphics
{
public struct ContrailRenderable : IRenderable
{
public int Length { get { return trail.Length; } }
readonly World world;
// Store trail positions in a circular buffer
readonly WPos[] trail;
int next;
int length;
int skip;
readonly Color color;
readonly int zOffset;
public ContrailRenderable(World world, Color color, int length, int skip, int zOffset)
: this(world, new WPos[length], 0, 0, skip, color, zOffset) {}
ContrailRenderable(World world, WPos[] trail, int next, int length, int skip, Color color, int zOffset)
{
this.world = world;
this.trail = trail;
this.next = next;
this.length = length;
this.skip = skip;
this.color = color;
this.zOffset = zOffset;
}
public WPos Pos { get { return trail[idx(next-1)]; } }
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 ContrailRenderable(world, (WPos[])trail.Clone(), next, length, skip, color, zOffset); }
public IRenderable WithPalette(PaletteReference newPalette) { return new ContrailRenderable(world, (WPos[])trail.Clone(), next, length, skip, color, zOffset); }
public IRenderable WithZOffset(int newOffset) { return new ContrailRenderable(world, (WPos[])trail.Clone(), next, length, skip, color, newOffset); }
public IRenderable OffsetBy(WVec vec) { return new ContrailRenderable(world, trail.Select(pos => pos + vec).ToArray(), next, length, skip, color, zOffset); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
// Need at least 4 points to smooth the contrail over
if (length - skip < 4)
return;
var wlr = Game.Renderer.WorldLineRenderer;
var oldWidth = wlr.LineWidth;
wlr.LineWidth = wr.Viewport.Zoom;
// Start of the first line segment is the tail of the list - don't smooth it.
var curPos = trail[idx(next - skip - 1)];
var curCell = wr.world.Map.CellContaining(curPos);
var curColor = color;
for (var i = 0; i < length - skip - 4; i++)
{
var j = next - skip - i - 2;
var nextPos = Average(trail[idx(j)], trail[idx(j-1)], trail[idx(j-2)], trail[idx(j-3)]);
var nextCell = wr.world.Map.CellContaining(nextPos);
var nextColor = Exts.ColorLerp(i * 1f / (length - 4), color, Color.Transparent);
if (!world.FogObscures(curCell) && !world.FogObscures(nextCell))
wlr.DrawLine(wr.ScreenPosition(curPos), wr.ScreenPosition(nextPos), curColor, nextColor);
curPos = nextPos;
curCell = nextCell;
curColor = nextColor;
}
wlr.LineWidth = oldWidth;
}
public void RenderDebugGeometry(WorldRenderer wr) {}
// Array index modulo length
int idx(int i)
{
var j = i % trail.Length;
return j < 0 ? j + trail.Length : j;
}
static WPos Average(params WPos[] list)
{
return list.Average();
}
public void Update(WPos pos)
{
trail[next] = pos;
next = idx(next+1);
if (length < trail.Length)
length++;
}
public static Color ChooseColor(Actor self)
{
var ownerColor = Color.FromArgb(255, self.Owner.Color.RGB);
return Exts.ColorLerp(0.5f, ownerColor, Color.White);
}
}
}

View File

@@ -0,0 +1,61 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using OpenRA.Graphics;
namespace OpenRA.Mods.RA.Graphics
{
public struct TextRenderable : IRenderable
{
readonly SpriteFont font;
readonly WPos pos;
readonly int zOffset;
readonly Color color;
readonly string text;
public TextRenderable(SpriteFont font, WPos pos, int zOffset, Color color, string text)
{
this.font = font;
this.pos = pos;
this.zOffset = zOffset;
this.color = color;
this.text = text;
}
public WPos Pos { get { return pos; } }
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 TextRenderable(font, pos, zOffset, color, text); }
public IRenderable WithPalette(PaletteReference newPalette) { return new TextRenderable(font, pos, zOffset, color, text); }
public IRenderable WithZOffset(int newOffset) { return new TextRenderable(font, pos, zOffset, color, text); }
public IRenderable OffsetBy(WVec vec) { return new TextRenderable(font, pos + vec, zOffset, color, text); }
public IRenderable AsDecoration() { return this; }
public void BeforeRender(WorldRenderer wr) {}
public void Render(WorldRenderer wr)
{
var screenPos = wr.Viewport.Zoom*(wr.ScreenPosition(pos) - wr.Viewport.TopLeft.ToFloat2()) - 0.5f*font.Measure(text).ToFloat2();
var screenPxPos = new float2((float)Math.Round(screenPos.X), (float)Math.Round(screenPos.Y));
font.DrawTextWithContrast(text, screenPxPos, color, Color.Black, 1);
}
public void RenderDebugGeometry(WorldRenderer wr)
{
var size = font.Measure(text).ToFloat2();
var offset = wr.ScreenPxPosition(pos) - 0.5f*size;
Game.Renderer.WorldLineRenderer.DrawRect(offset, offset + size, Color.Red);
}
}
}

View File

@@ -0,0 +1,181 @@
#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;
namespace OpenRA.Mods.RA.Graphics
{
public struct VoxelRenderable : IRenderable
{
readonly IEnumerable<VoxelAnimation> voxels;
readonly WPos pos;
readonly int zOffset;
readonly WRot camera;
readonly WRot lightSource;
readonly float[] lightAmbientColor;
readonly float[] lightDiffuseColor;
readonly PaletteReference palette;
readonly PaletteReference normalsPalette;
readonly PaletteReference shadowPalette;
readonly float scale;
// Generated at render-time
VoxelRenderProxy renderProxy;
public VoxelRenderable(IEnumerable<VoxelAnimation> voxels, WPos pos, int zOffset, WRot camera, float scale,
WRot lightSource, float[] lightAmbientColor, float[] lightDiffuseColor,
PaletteReference color, PaletteReference normals, PaletteReference shadow)
{
this.voxels = voxels;
this.pos = pos;
this.zOffset = zOffset;
this.scale = scale;
this.camera = camera;
this.lightSource = lightSource;
this.lightAmbientColor = lightAmbientColor;
this.lightDiffuseColor = lightDiffuseColor;
this.palette = color;
this.normalsPalette = normals;
this.shadowPalette = shadow;
this.renderProxy = null;
}
public WPos Pos { get { return pos; } }
public float Scale { get { return scale; } }
public PaletteReference Palette { get { return palette; } }
public int ZOffset { get { return zOffset; } }
public bool IsDecoration { get { return false; } }
public IRenderable WithScale(float newScale)
{
return new VoxelRenderable(voxels, pos, zOffset, camera, newScale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette);
}
public IRenderable WithPalette(PaletteReference newPalette)
{
return new VoxelRenderable(voxels, pos, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
newPalette, normalsPalette, shadowPalette);
}
public IRenderable WithZOffset(int newOffset)
{
return new VoxelRenderable(voxels, pos, newOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette);
}
public IRenderable OffsetBy(WVec vec)
{
return new VoxelRenderable(voxels, pos + vec, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette);
}
public IRenderable AsDecoration() { return this; }
// This will need generalizing once we support TS/RA2 terrain
static readonly float[] groundNormal = new float[] {0,0,1,1};
public void BeforeRender(WorldRenderer wr)
{
var draw = voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
renderProxy = Game.Renderer.WorldVoxelRenderer.RenderAsync(
wr, draw, camera, scale, groundNormal, lightSource,
lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette);
}
public void Render(WorldRenderer wr)
{
var pxOrigin = wr.ScreenPosition(pos);
var groundZ = 0.5f*(pxOrigin.Y - wr.ScreenZPosition(pos, 0));
var shadowOrigin = pxOrigin - groundZ*(new float2(renderProxy.ShadowDirection, 1));
var psb = renderProxy.ProjectedShadowBounds;
var sa = shadowOrigin + psb[0];
var sb = shadowOrigin + psb[2];
var sc = shadowOrigin + psb[1];
var sd = shadowOrigin + psb[3];
Game.Renderer.WorldRgbaSpriteRenderer.DrawSprite(renderProxy.ShadowSprite, sa, sb, sc, sd);
Game.Renderer.WorldRgbaSpriteRenderer.DrawSprite(renderProxy.Sprite, pxOrigin - 0.5f*renderProxy.Sprite.size);
}
public void RenderDebugGeometry(WorldRenderer wr)
{
var pxOrigin = wr.ScreenPosition(pos);
var groundZ = 0.5f*(pxOrigin.Y - wr.ScreenZPosition(pos, 0));
var shadowOrigin = pxOrigin - groundZ*(new float2(renderProxy.ShadowDirection, 1));
// Draw sprite rect
var offset = pxOrigin + renderProxy.Sprite.offset - 0.5f*renderProxy.Sprite.size;
Game.Renderer.WorldLineRenderer.DrawRect(offset, offset + renderProxy.Sprite.size, Color.Red);
// Draw transformed shadow sprite rect
var c = Color.Purple;
var psb = renderProxy.ProjectedShadowBounds;
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[1], shadowOrigin + psb[3], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[3], shadowOrigin + psb[0], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[0], shadowOrigin + psb[2], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[2], shadowOrigin + psb[1], c, c);
// Draw voxel bounding box
var draw = voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
var scaleTransform = Util.ScaleMatrix(scale, scale, scale);
var cameraTransform = Util.MakeFloatMatrix(camera.AsMatrix());
foreach (var v in draw)
{
var bounds = v.Voxel.Bounds(v.FrameFunc());
var worldTransform = v.RotationFunc().Reverse().Aggregate(scaleTransform,
(x,y) => Util.MatrixMultiply(x, Util.MakeFloatMatrix(y.AsMatrix())));
var pxOffset = wr.ScreenVector(v.OffsetFunc());
var pxPos = pxOrigin + new float2(pxOffset[0], pxOffset[1]);
var screenTransform = Util.MatrixMultiply(cameraTransform, worldTransform);
DrawBoundsBox(pxPos, screenTransform, bounds, Color.Yellow);
}
}
static readonly uint[] ix = new uint[] {0,0,0,0,3,3,3,3};
static readonly uint[] iy = new uint[] {1,1,4,4,1,1,4,4};
static readonly uint[] iz = new uint[] {2,5,2,5,2,5,2,5};
static void DrawBoundsBox(float2 pxPos, float[] transform, float[] bounds, Color c)
{
var corners = new float2[8];
for (var i = 0; i < 8; i++)
{
var vec = new float[] {bounds[ix[i]], bounds[iy[i]], bounds[iz[i]], 1};
var screen = Util.MatrixVectorMultiply(transform, vec);
corners[i] = pxPos + new float2(screen[0], screen[1]);
}
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[1], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[3], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[2], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[0], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[4], corners[5], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[5], corners[7], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[7], corners[6], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[6], corners[4], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[4], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[5], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[6], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[7], c, c);
}
}
}

View File

@@ -11,6 +11,7 @@
using System;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Mods.RA.Render;
namespace OpenRA.Mods.RA
{

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
[Desc("This actor will remain visible (but not updated visually) under fog, once discovered.")]
public class FrozenUnderFogInfo : ITraitInfo, Requires<BuildingInfo>, Requires<RenderSpritesInfo>
public class FrozenUnderFogInfo : ITraitInfo, Requires<BuildingInfo>
{
public readonly bool StartsRevealed = false;

View File

@@ -521,6 +521,12 @@
<Compile Include="Widgets\Logic\InstallMusicLogic.cs" />
<Compile Include="Render\WithActiveAnimation.cs" />
<Compile Include="SupportPowers\SpawnActorPower.cs" />
<Compile Include="Render\RenderSimple.cs" />
<Compile Include="Render\RenderSprites.cs" />
<Compile Include="Graphics\BeamRenderable.cs" />
<Compile Include="Graphics\ContrailRenderable.cs" />
<Compile Include="Graphics\TextRenderable.cs" />
<Compile Include="Graphics\VoxelRenderable.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Render

View File

@@ -0,0 +1,66 @@
#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;
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Render
{
public class RenderSimpleInfo : RenderSpritesInfo, ILegacyEditorRenderInfo, Requires<IBodyOrientationInfo>
{
public override object Create(ActorInitializer init) { return new RenderSimple(init.self); }
public virtual IEnumerable<IRenderable> RenderPreview(World world, ActorInfo ai, PaletteReference pr)
{
var anim = new Animation(world, RenderSimple.GetImage(ai), () => 0);
anim.PlayRepeating("idle");
return anim.Render(WPos.Zero, WVec.Zero, 0, pr, Scale);
}
public string EditorPalette { get { return Palette; } }
public string EditorImage(ActorInfo actor) { return RenderSimple.GetImage(actor); }
}
public class RenderSimple : RenderSprites, IAutoSelectionSize
{
public readonly Animation DefaultAnimation;
public RenderSimple(Actor self, Func<int> baseFacing)
: base(self)
{
DefaultAnimation = new Animation(self.World, GetImage(self), baseFacing);
Add("", DefaultAnimation);
}
public RenderSimple(Actor self)
: this(self, MakeFacingFunc(self))
{
DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle"));
self.Trait<IBodyOrientation>().SetAutodetectedFacings(DefaultAnimation.CurrentSequence.Facings);
}
public int2 SelectionSize(Actor self) { return AutoSelectionSize(self); }
public string NormalizeSequence(Actor self, string sequence)
{
return NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence);
}
public void PlayCustomAnim(Actor self, string name)
{
if (DefaultAnimation.HasSequence(name))
DefaultAnimation.PlayThen(NormalizeSequence(self, name),
() => DefaultAnimation.PlayRepeating(NormalizeSequence(self, "idle")));
}
}
}

View File

@@ -0,0 +1,189 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
using OpenRA.Primitives;
namespace OpenRA.Mods.RA.Render
{
public class RenderSpritesInfo : ITraitInfo
{
[Desc("Defaults to the actor name.")]
public readonly string Image = null;
[Desc("Custom palette name")]
public readonly string Palette = null;
[Desc("Custom PlayerColorPalette: BaseName")]
public readonly string PlayerPalette = "player";
[Desc("Change the sprite image size.")]
public readonly float Scale = 1f;
public virtual object Create(ActorInitializer init) { return new RenderSprites(init.self); }
}
public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged
{
class AnimationWrapper
{
public readonly AnimationWithOffset Animation;
public readonly string Palette;
public readonly bool IsPlayerPalette;
public PaletteReference PaletteReference { get; private set; }
public AnimationWrapper(AnimationWithOffset animation, string palette, bool isPlayerPalette)
{
Animation = animation;
Palette = palette;
IsPlayerPalette = isPlayerPalette;
}
public void CachePalette(WorldRenderer wr, Player owner)
{
PaletteReference = wr.Palette(IsPlayerPalette ? Palette + owner.InternalName : Palette);
}
public void OwnerChanged()
{
// Update the palette reference next time we draw
if (IsPlayerPalette)
PaletteReference = null;
}
public bool IsVisible
{
get
{
return Animation.DisableFunc == null || !Animation.DisableFunc();
}
}
}
Dictionary<string, AnimationWrapper> anims = new Dictionary<string, AnimationWrapper>();
public static Func<int> MakeFacingFunc(Actor self)
{
var facing = self.TraitOrDefault<IFacing>();
if (facing == null) return () => 0;
return () => facing.Facing;
}
readonly RenderSpritesInfo info;
string cachedImage = null;
public RenderSprites(Actor self)
{
info = self.Info.Traits.Get<RenderSpritesInfo>();
}
public static string GetImage(ActorInfo actor)
{
var Info = actor.Traits.Get<RenderSpritesInfo>();
return Info.Image ?? actor.Name;
}
public string GetImage(Actor self)
{
if (cachedImage != null)
return cachedImage;
return cachedImage = GetImage(self.Info);
}
protected void UpdatePalette()
{
foreach (var anim in anims.Values)
anim.OwnerChanged();
}
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { UpdatePalette(); }
public void OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner) { UpdatePalette(); }
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
{
foreach (var a in anims.Values)
{
if (!a.IsVisible)
continue;
if (a.PaletteReference == null)
{
var owner = self.EffectiveOwner != null && self.EffectiveOwner.Disguised ? self.EffectiveOwner.Owner : self.Owner;
a.CachePalette(wr, owner);
}
foreach (var r in a.Animation.Render(self, wr, a.PaletteReference, info.Scale))
yield return r;
}
}
public virtual void Tick(Actor self)
{
foreach (var a in anims.Values)
a.Animation.Animation.Tick();
}
public void Add(string key, AnimationWithOffset anim, string palette = null, bool isPlayerPalette = false)
{
// Use defaults
if (palette == null)
{
palette = info.Palette ?? info.PlayerPalette;
isPlayerPalette = info.Palette == null;
}
anims.Add(key, new AnimationWrapper(anim, palette, isPlayerPalette));
}
public void Remove(string key)
{
anims.Remove(key);
}
public static string NormalizeSequence(Animation anim, DamageState state, string sequence)
{
var states = new Pair<DamageState, string>[]
{
Pair.New(DamageState.Critical, "critical-"),
Pair.New(DamageState.Heavy, "damaged-"),
Pair.New(DamageState.Medium, "scratched-"),
Pair.New(DamageState.Light, "scuffed-")
};
// Remove existing damage prefix
foreach (var s in states)
{
if (sequence.StartsWith(s.Second))
{
sequence = sequence.Substring(s.Second.Length);
break;
}
}
foreach (var s in states)
if (state >= s.First && anim.HasSequence(s.Second + sequence))
return s.Second + sequence;
return sequence;
}
// Required by RenderSimple
protected int2 AutoSelectionSize(Actor self)
{
return anims.Values.Where(b => b.IsVisible
&& b.Animation.Animation.CurrentSequence != null)
.Select(a => (a.Animation.Animation.Image.size*info.Scale).ToInt2())
.FirstOrDefault();
}
}
}

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
using OpenRA.Mods.RA.Graphics;
namespace OpenRA.Mods.RA.Render
{

View File

@@ -12,6 +12,7 @@ using System;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Effects;
using OpenRA.Mods.RA.Render;
using OpenRA.Primitives;
using OpenRA.Traits;

View File

@@ -10,6 +10,7 @@
using OpenRA.Graphics;
using OpenRA.Traits;
using OpenRA.Mods.RA.Render;
namespace OpenRA.Mods.RA
{

View File

@@ -15,6 +15,7 @@ using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Mods.RA.Render;
using OpenRA.Network;
using OpenRA.Primitives;
using OpenRA.Traits;

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Render;
using OpenRA.Traits;
using OpenRA.Widgets;