diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index 13d7e8921d..21a5ef3d03 100644
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -194,7 +194,6 @@
-
@@ -233,6 +232,7 @@
+
diff --git a/OpenRA.Game/Widgets/ShpImageWidget.cs b/OpenRA.Game/Widgets/ShpImageWidget.cs
deleted file mode 100644
index 5c1dabaa0b..0000000000
--- a/OpenRA.Game/Widgets/ShpImageWidget.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-#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 OpenRA.Graphics;
-
-namespace OpenRA.Widgets
-{
- public class ShpImageWidget : Widget
- {
- public string Image = "";
- public int Frame = 0;
- public string Palette = "chrome";
- public bool LoopAnimation = false;
-
- public Func GetImage;
- public Func GetFrame;
- public Func GetPalette;
-
- readonly WorldRenderer worldRenderer;
-
- [ObjectCreator.UseCtor]
- public ShpImageWidget(WorldRenderer worldRenderer)
- {
- GetImage = () => { return Image; };
- GetFrame = () => { return Frame; };
- GetPalette = () => { return Palette; };
-
- this.worldRenderer = worldRenderer;
- }
-
- protected ShpImageWidget(ShpImageWidget other)
- : base(other)
- {
- Image = other.Image;
- Frame = other.Frame;
- Palette = other.Palette;
- LoopAnimation = other.LoopAnimation;
-
- GetImage = other.GetImage;
- GetFrame = other.GetFrame;
- GetPalette = other.GetPalette;
-
- worldRenderer = other.worldRenderer;
- }
-
- public override Widget Clone() { return new ShpImageWidget(this); }
-
- Sprite sprite = null;
- string cachedImage = null;
- int cachedFrame = -1;
- float2 cachedOffset = float2.Zero;
-
- public override void Draw()
- {
- var image = GetImage();
- var frame = GetFrame();
- var palette = GetPalette();
-
- if (image != cachedImage || frame != cachedFrame)
- {
- sprite = Game.modData.SpriteLoader.LoadAllSprites(image)[frame];
- cachedImage = image;
- cachedFrame = frame;
- cachedOffset = 0.5f * (new float2(RenderBounds.Size) - sprite.size);
- }
-
- Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + cachedOffset, worldRenderer.Palette(palette));
- }
-
- public int FrameCount
- {
- get { return Game.modData.SpriteLoader.LoadAllSprites(Image).Length-1; }
- }
-
- public void RenderNextFrame()
- {
- if (Frame < FrameCount)
- Frame++;
- else
- Frame = 0;
- }
-
- public void RenderPreviousFrame()
- {
- if (Frame > 0)
- Frame--;
- else
- Frame = FrameCount;
- }
-
- public override void Tick()
- {
- if (LoopAnimation)
- RenderNextFrame();
- }
- }
-}
diff --git a/OpenRA.Game/Widgets/SpriteSequenceWidget.cs b/OpenRA.Game/Widgets/SpriteSequenceWidget.cs
new file mode 100644
index 0000000000..e4535bb203
--- /dev/null
+++ b/OpenRA.Game/Widgets/SpriteSequenceWidget.cs
@@ -0,0 +1,65 @@
+#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 OpenRA.Graphics;
+
+namespace OpenRA.Widgets
+{
+ public class SpriteSequenceWidget : SpriteWidget
+ {
+ public string Unit = null;
+ public string Sequence = null;
+ public int Frame = 0;
+ public int Facing = 0;
+
+ public Func GetAnimation;
+ public Func GetFacing;
+
+ [ObjectCreator.UseCtor]
+ public SpriteSequenceWidget(WorldRenderer worldRenderer)
+ : base(worldRenderer)
+ {
+ GetAnimation = () => null;
+ }
+
+ public override void Initialize(WidgetArgs args)
+ {
+ base.Initialize(args);
+
+ if (Unit != null && Sequence != null)
+ {
+ var anim = new Animation(Unit, () => Facing);
+ anim.PlayFetchIndex(Sequence, () => Frame);
+ GetAnimation = () => anim;
+ }
+
+ GetSprite = () =>
+ {
+ var anim = GetAnimation();
+ return anim != null ? anim.Image : null;
+ };
+ }
+
+ protected SpriteSequenceWidget(SpriteSequenceWidget other)
+ : base(other)
+ {
+ Unit = other.Unit;
+ Sequence = other.Sequence;
+ Frame = other.Frame;
+ Facing = other.Facing;
+
+ GetAnimation = other.GetAnimation;
+ GetFacing = other.GetFacing;
+ }
+
+ public override Widget Clone() { return new SpriteSequenceWidget(this); }
+ }
+}
diff --git a/mods/cnc/chrome/color-picker.yaml b/mods/cnc/chrome/color-picker.yaml
index 0f6bd53063..e8c2c35b0f 100644
--- a/mods/cnc/chrome/color-picker.yaml
+++ b/mods/cnc/chrome/color-picker.yaml
@@ -29,13 +29,14 @@ Background@COLOR_CHOOSER:
Y:2
Width:144
Height:72
- ShpImage@FACT:
+ SpriteSequence@FACT:
X:153
Y:1
Width:80
Height:73
- Image:fact
Palette:colorpicker
+ Unit:fact
+ Sequence:idle
Button@RANDOM_BUTTON:
Key:tab
X:158
diff --git a/mods/d2k/chrome/color-picker.yaml b/mods/d2k/chrome/color-picker.yaml
index 0d4991736e..60d87803f2 100644
--- a/mods/d2k/chrome/color-picker.yaml
+++ b/mods/d2k/chrome/color-picker.yaml
@@ -29,14 +29,15 @@ Background@COLOR_CHOOSER:
Y:2
Width:144
Height:72
- ShpImage@FACT:
+ SpriteSequence@FACT:
X:153
Y:1
Width:80
Height:73
- Image:DATA.R8
- Frame:1936
Palette:colorpicker
+ Unit:carryall
+ Sequence:idle
+ Facing:104
Button@RANDOM_BUTTON:
Key:tab
X:158
diff --git a/mods/ra/chrome/color-picker.yaml b/mods/ra/chrome/color-picker.yaml
index 0daef841a9..779d1de3c4 100644
--- a/mods/ra/chrome/color-picker.yaml
+++ b/mods/ra/chrome/color-picker.yaml
@@ -29,13 +29,14 @@ Background@COLOR_CHOOSER:
Y:2
Width:144
Height:72
- ShpImage@FACT:
+ SpriteSequence@FACT:
X:153
Y:1
Width:80
Height:73
- Image:fact
Palette:colorpicker
+ Unit:fact
+ Sequence:idle
Button@RANDOM_BUTTON:
Key:tab
X:158
diff --git a/mods/ts/chrome/color-picker.yaml b/mods/ts/chrome/color-picker.yaml
index 6e33ea9771..110cf34f99 100644
--- a/mods/ts/chrome/color-picker.yaml
+++ b/mods/ts/chrome/color-picker.yaml
@@ -29,13 +29,14 @@ Background@COLOR_CHOOSER:
Y:2
Width:144
Height:72
- ShpImage@GTCNST:
+ SpriteSequence@PREVIEW:
X:153
Y:1-40
Width:80
Height:73
- Image:gtcnstmk
Palette:colorpicker
+ Unit:gacnst
+ Sequence:make
Button@RANDOM_BUTTON:
Key:tab
X:158