Merge pull request #5008 from pchote/spritewidget

Split ShpImageWidget into SpriteWidget and SpriteSequenceWidget.
This commit is contained in:
Matthias Mailänder
2014-04-02 09:56:06 +02:00
13 changed files with 288 additions and 190 deletions

View File

@@ -110,6 +110,7 @@ NEW:
Fixed Obelisk of Light charge animation and sound not playing.
Replaced or improved several mouse cursors.
Added Minibibs for bibless buildings.
The Construction Yard fans now turn in the color picker preview.
Engine:
Converted Aircraft CruiseAltitude to world coordinates.
Converted Health Radius to world coordinates.

View File

@@ -194,7 +194,6 @@
<Compile Include="Widgets\ProgressBarWidget.cs" />
<Compile Include="Widgets\ScrollItemWidget.cs" />
<Compile Include="Widgets\ScrollPanelWidget.cs" />
<Compile Include="Widgets\ShpImageWidget.cs" />
<Compile Include="Widgets\SliderWidget.cs" />
<Compile Include="Widgets\TextFieldWidget.cs" />
<Compile Include="Widgets\VqaPlayerWidget.cs" />
@@ -232,6 +231,8 @@
<Compile Include="Effects\MoveFlash.cs" />
<Compile Include="MapCache.cs" />
<Compile Include="MapPreview.cs" />
<Compile Include="Widgets\SpriteWidget.cs" />
<Compile Include="Widgets\SpriteSequenceWidget.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">

View File

@@ -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<string> GetImage;
public Func<int> GetFrame;
public Func<string> 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();
}
}
}

View File

@@ -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<Animation> GetAnimation;
public Func<int> 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); }
}
}

View File

@@ -0,0 +1,72 @@
#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 SpriteWidget : Widget
{
public string Palette = "chrome";
public Func<string> GetPalette;
public Func<Sprite> GetSprite;
readonly WorldRenderer worldRenderer;
[ObjectCreator.UseCtor]
public SpriteWidget(WorldRenderer worldRenderer)
{
GetPalette = () => { return Palette; };
this.worldRenderer = worldRenderer;
}
protected SpriteWidget(SpriteWidget other)
: base(other)
{
Palette = other.Palette;
GetPalette = other.GetPalette;
GetSprite = other.GetSprite;
worldRenderer = other.worldRenderer;
}
public override Widget Clone() { return new SpriteWidget(this); }
Sprite cachedSprite = null;
string cachedPalette = null;
PaletteReference pr;
float2 offset = float2.Zero;
public override void Draw()
{
var sprite = GetSprite();
var palette = GetPalette();
if (sprite == null || palette == null)
return;
if (sprite != cachedSprite)
{
offset = 0.5f * (new float2(RenderBounds.Size) - sprite.size);
cachedSprite = sprite;
}
if (palette != cachedPalette)
{
pr = worldRenderer.Palette(palette);
cachedPalette = palette;
}
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + offset, pr);
}
}
}

View File

@@ -14,6 +14,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -23,17 +24,19 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
Widget panel;
ShpImageWidget spriteWidget;
TextFieldWidget filenameInput;
SliderWidget frameSlider;
ButtonWidget playButton, pauseButton;
ScrollPanelWidget assetList;
ScrollItemWidget template;
IFolder assetSource = null;
List<string> availableShps = new List<string>();
bool animateFrames = false;
PaletteFromFile currentPalette;
string currentPalette;
string currentFilename;
Sprite[] currentSprites;
int currentFrame;
static readonly string[] AllowedExtensions = { ".shp", ".r8", "tmp", ".tem", ".des", ".sno", ".int" };
@@ -41,94 +44,139 @@ namespace OpenRA.Mods.RA.Widgets.Logic
public AssetBrowserLogic(Widget widget, Action onExit, World world)
{
panel = widget;
var sourceDropdown = panel.Get<DropDownButtonWidget>("SOURCE_SELECTOR");
sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown);
sourceDropdown.GetText = () =>
{
var name = assetSource != null ? assetSource.Name.Replace(Platform.SupportDir, "^") : "All Packages";
if (name.Length > 15)
name = "..." + name.Substring(name.Length - 15);
return name;
};
assetSource = FileSystem.MountedFolders.First();
spriteWidget = panel.Get<ShpImageWidget>("SPRITE");
var ticker = panel.GetOrNull<LogicTickerWidget>("ANIMATION_TICKER");
if (ticker != null)
{
ticker.OnTick = () =>
{
if (animateFrames)
SelectNextFrame();
};
}
currentPalette = world.WorldActor.TraitsImplementing<PaletteFromFile>().First(p => p.Name == spriteWidget.Palette);
var sourceDropdown = panel.GetOrNull<DropDownButtonWidget>("SOURCE_SELECTOR");
if (sourceDropdown != null)
{
sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown);
sourceDropdown.GetText = () =>
{
var name = assetSource != null ? assetSource.Name.Replace(Platform.SupportDir, "^") : "All Packages";
if (name.Length > 15)
name = "..." + name.Substring(name.Length - 15);
var paletteDropDown = panel.Get<DropDownButtonWidget>("PALETTE_SELECTOR");
paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
paletteDropDown.GetText = () => currentPalette.Name;
return name;
};
}
var colorPreview = panel.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
colorPreview.Color = Game.Settings.Player.Color;
var spriteWidget = panel.GetOrNull<SpriteWidget>("SPRITE");
if (spriteWidget != null)
{
spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null;
currentPalette = spriteWidget.Palette;
spriteWidget.GetPalette = () => currentPalette;
}
var color = panel.Get<DropDownButtonWidget>("COLOR");
color.IsDisabled = () => currentPalette.Name != colorPreview.Palette;
color.OnMouseDown = _ => ShowColorDropDown(color, colorPreview, world);
var block = panel.Get<ColorBlockWidget>("COLORBLOCK");
block.GetColor = () => Game.Settings.Player.Color.RGB;
var paletteDropDown = panel.GetOrNull<DropDownButtonWidget>("PALETTE_SELECTOR");
if (paletteDropDown != null)
{
paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
paletteDropDown.GetText = () => currentPalette;
}
var colorPreview = panel.GetOrNull<ColorPreviewManagerWidget>("COLOR_MANAGER");
if (colorPreview != null)
colorPreview.Color = Game.Settings.Player.Color;
var colorDropdown = panel.GetOrNull<DropDownButtonWidget>("COLOR");
if (colorDropdown != null)
{
colorDropdown.IsDisabled = () => currentPalette != colorPreview.Palette;
colorDropdown.OnMouseDown = _ => ShowColorDropDown(colorDropdown, colorPreview, world);
panel.Get<ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB;
}
filenameInput = panel.Get<TextFieldWidget>("FILENAME_INPUT");
filenameInput.OnEnterKey = () => LoadAsset(filenameInput.Text);
var frameContainer = panel.GetOrNull("FRAME_SELECTOR");
if (frameContainer != null)
frameContainer.IsVisible = () => currentSprites != null && currentSprites.Length > 1;
frameSlider = panel.Get<SliderWidget>("FRAME_SLIDER");
frameSlider.MaximumValue = (float)spriteWidget.FrameCount;
frameSlider.Ticks = spriteWidget.FrameCount + 1;
frameSlider.IsVisible = () => spriteWidget.FrameCount > 0;
frameSlider.OnChange += x => { spriteWidget.Frame = (int)Math.Round(x); };
frameSlider.GetValue = () => spriteWidget.Frame;
frameSlider.OnChange += x => { currentFrame = (int)Math.Round(x); };
frameSlider.GetValue = () => currentFrame;
panel.Get<LabelWidget>("FRAME_COUNT").GetText = () => "{0} / {1}".F(spriteWidget.Frame + 1, spriteWidget.FrameCount + 1);
var frameText = panel.GetOrNull<LabelWidget>("FRAME_COUNT");
if (frameText != null)
frameText.GetText = () => "{0} / {1}".F(currentFrame + 1, currentSprites.Length);
playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
playButton.OnClick = () =>
var playButton = panel.GetOrNull<ButtonWidget>("BUTTON_PLAY");
if (playButton != null)
{
spriteWidget.LoopAnimation = true;
playButton.Visible = false;
pauseButton.Visible = true;
};
pauseButton = panel.Get<ButtonWidget>("BUTTON_PAUSE");
pauseButton.OnClick = () =>
{
spriteWidget.LoopAnimation = false;
playButton.Visible = true;
pauseButton.Visible = false;
};
playButton.OnClick = () => animateFrames = true;
playButton.IsVisible = () => !animateFrames;
}
panel.Get<ButtonWidget>("BUTTON_STOP").OnClick = () =>
var pauseButton = panel.GetOrNull<ButtonWidget>("BUTTON_PAUSE");
if (pauseButton != null)
{
spriteWidget.LoopAnimation = false;
frameSlider.Value = 0;
spriteWidget.Frame = 0;
playButton.Visible = true;
pauseButton.Visible = false;
};
pauseButton.OnClick = () => animateFrames = false;
pauseButton.IsVisible = () => animateFrames;
}
panel.Get<ButtonWidget>("BUTTON_NEXT").OnClick = () => { spriteWidget.RenderNextFrame(); };
panel.Get<ButtonWidget>("BUTTON_PREV").OnClick = () => { spriteWidget.RenderPreviousFrame(); };
panel.Get<ButtonWidget>("LOAD_BUTTON").OnClick = () =>
var stopButton = panel.GetOrNull<ButtonWidget>("BUTTON_STOP");
if (stopButton != null)
{
LoadAsset(filenameInput.Text);
};
stopButton.OnClick = () =>
{
frameSlider.Value = 0;
currentFrame = 0;
animateFrames = false;
};
}
var nextButton = panel.GetOrNull<ButtonWidget>("BUTTON_NEXT");
if (nextButton != null)
nextButton.OnClick = SelectNextFrame;
var prevButton = panel.GetOrNull<ButtonWidget>("BUTTON_PREV");
if (prevButton != null)
prevButton.OnClick = SelectPreviousFrame;
var loadButton = panel.GetOrNull<ButtonWidget>("LOAD_BUTTON");
if (loadButton != null)
loadButton.OnClick = () => LoadAsset(filenameInput.Text);
assetList = panel.Get<ScrollPanelWidget>("ASSET_LIST");
template = panel.Get<ScrollItemWidget>("ASSET_TEMPLATE");
PopulateAssetList();
panel.Get<ButtonWidget>("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
var closeButton = panel.GetOrNull<ButtonWidget>("CLOSE_BUTTON");
if (closeButton != null)
closeButton.OnClick = () => { Ui.CloseWindow(); onExit(); };
}
void SelectNextFrame()
{
currentFrame++;
if (currentFrame >= currentSprites.Length)
currentFrame = 0;
}
void SelectPreviousFrame()
{
currentFrame--;
if (currentFrame < 0)
currentFrame = currentSprites.Length - 1;
}
void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template)
{
var filename = Path.GetFileName(filepath);
var item = ScrollItemWidget.Setup(template,
() => spriteWidget.Image == filename,
() => currentFilename == filename,
() => { filenameInput.Text = filename; LoadAsset(filename); });
item.Get<LabelWidget>("TITLE").GetText = () => filepath;
@@ -143,10 +191,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (!FileSystem.Exists(filename))
return false;
spriteWidget.Frame = 0;
spriteWidget.Image = filename;
frameSlider.MaximumValue = (float)spriteWidget.FrameCount;
frameSlider.Ticks = spriteWidget.FrameCount + 1;
currentFilename = filename;
currentSprites = Game.modData.SpriteLoader.LoadAllSprites(filename);
currentFrame = 0;
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
frameSlider.Ticks = currentSprites.Length;
return true;
}
@@ -196,10 +246,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
Func<PaletteFromFile, ScrollItemWidget, ScrollItemWidget> setupItem = (palette, itemTemplate) =>
{
var name = palette.Name;
var item = ScrollItemWidget.Setup(itemTemplate,
() => currentPalette.Name == palette.Name,
() => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; });
item.Get<LabelWidget>("LABEL").GetText = () => palette.Name;
() => currentPalette == name,
() => currentPalette = name);
item.Get<LabelWidget>("LABEL").GetText = () => name;
return item;
};

View File

@@ -20,6 +20,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
[ObjectCreator.UseCtor]
public ColorPickerLogic(Widget widget, HSLColor initialColor, Action<HSLColor> onChange, WorldRenderer worldRenderer)
{
var ticker = widget.GetOrNull<LogicTickerWidget>("ANIMATE_PREVIEW");
if (ticker != null)
{
var preview = widget.Get<SpriteSequenceWidget>("PREVIEW");
var anim = preview.GetAnimation();
anim.PlayRepeating(anim.CurrentSequence.Name);
ticker.OnTick = () => anim.Tick();
}
var hueSlider = widget.Get<SliderWidget>("HUE");
var mixer = widget.Get<ColorMixerWidget>("MIXER");
var randomButton = widget.GetOrNull<ButtonWidget>("RANDOM_BUTTON");

View File

@@ -5,6 +5,7 @@ Container@ASSETBROWSER_PANEL:
Width:695
Height:435
Children:
LogicTicker@ANIMATION_TICKER:
ColorPreviewManager@COLOR_MANAGER:
Label@ASSETBROWSER_TITLE:
Width:PARENT_RIGHT
@@ -63,7 +64,6 @@ Container@ASSETBROWSER_PANEL:
Y:365
Width:160
Height:25
Text:mouse2.shp
Button@LOAD_BUTTON:
X:15
Y:395
@@ -104,10 +104,9 @@ Container@ASSETBROWSER_PANEL:
Height:325
Background:scrollpanel-bg
Children:
ShpImage@SPRITE:
Sprite@SPRITE:
Width:PARENT_RIGHT
Height:PARENT_BOTTOM
Image:mouse2
Container@FRAME_SELECTOR:
X:190
Y:395

View File

@@ -4,6 +4,7 @@ Background@COLOR_CHOOSER:
Width:234
Height:105
Children:
LogicTicker@ANIMATE_PREVIEW:
Background@HUEBG:
Background:panel-black
X:5
@@ -29,13 +30,14 @@ Background@COLOR_CHOOSER:
Y:2
Width:144
Height:72
ShpImage@FACT:
SpriteSequence@PREVIEW:
X:153
Y:1
Width:80
Height:73
Image:fact
Palette:colorpicker
Unit:fact
Sequence:idle
Button@RANDOM_BUTTON:
Key:tab
X:158

View File

@@ -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

View File

@@ -5,6 +5,7 @@ Background@ASSETBROWSER_PANEL:
Width:700
Height:500
Children:
LogicTicker@ANIMATION_TICKER:
ColorPreviewManager@COLOR_MANAGER:
Label@ASSETBROWSER_TITLE:
Y:20
@@ -58,7 +59,6 @@ Background@ASSETBROWSER_PANEL:
Y:395
Width:160
Height:25
Text:mouse.shp
Button@LOAD_BUTTON:
X:20
Y:425
@@ -99,10 +99,9 @@ Background@ASSETBROWSER_PANEL:
Height:330
Background:dialog3
Children:
ShpImage@SPRITE:
Sprite@SPRITE:
Width:PARENT_RIGHT
Height:PARENT_BOTTOM
Image:mouse
Container@FRAME_SELECTOR:
X:190
Y:425

View File

@@ -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

View File

@@ -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