diff --git a/CHANGELOG b/CHANGELOG index 1d19909214..4c3c330f15 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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. diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 6d13a70cd9..21a5ef3d03 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -194,7 +194,6 @@ - @@ -232,6 +231,8 @@ + + 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/OpenRA.Game/Widgets/SpriteWidget.cs b/OpenRA.Game/Widgets/SpriteWidget.cs new file mode 100644 index 0000000000..6e81dc8cbf --- /dev/null +++ b/OpenRA.Game/Widgets/SpriteWidget.cs @@ -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 GetPalette; + public Func 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); + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs index 7644831c93..5d7af738b3 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs @@ -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 availableShps = new List(); + 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("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("SPRITE"); + var ticker = panel.GetOrNull("ANIMATION_TICKER"); + if (ticker != null) + { + ticker.OnTick = () => + { + if (animateFrames) + SelectNextFrame(); + }; + } - currentPalette = world.WorldActor.TraitsImplementing().First(p => p.Name == spriteWidget.Palette); + var sourceDropdown = panel.GetOrNull("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("PALETTE_SELECTOR"); - paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); - paletteDropDown.GetText = () => currentPalette.Name; + return name; + }; + } - var colorPreview = panel.Get("COLOR_MANAGER"); - colorPreview.Color = Game.Settings.Player.Color; + var spriteWidget = panel.GetOrNull("SPRITE"); + if (spriteWidget != null) + { + spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; + currentPalette = spriteWidget.Palette; + spriteWidget.GetPalette = () => currentPalette; + } - var color = panel.Get("COLOR"); - color.IsDisabled = () => currentPalette.Name != colorPreview.Palette; - color.OnMouseDown = _ => ShowColorDropDown(color, colorPreview, world); - var block = panel.Get("COLORBLOCK"); - block.GetColor = () => Game.Settings.Player.Color.RGB; + var paletteDropDown = panel.GetOrNull("PALETTE_SELECTOR"); + if (paletteDropDown != null) + { + paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); + paletteDropDown.GetText = () => currentPalette; + } + + var colorPreview = panel.GetOrNull("COLOR_MANAGER"); + if (colorPreview != null) + colorPreview.Color = Game.Settings.Player.Color; + + var colorDropdown = panel.GetOrNull("COLOR"); + if (colorDropdown != null) + { + colorDropdown.IsDisabled = () => currentPalette != colorPreview.Palette; + colorDropdown.OnMouseDown = _ => ShowColorDropDown(colorDropdown, colorPreview, world); + panel.Get("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB; + } filenameInput = panel.Get("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("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("FRAME_COUNT").GetText = () => "{0} / {1}".F(spriteWidget.Frame + 1, spriteWidget.FrameCount + 1); + var frameText = panel.GetOrNull("FRAME_COUNT"); + if (frameText != null) + frameText.GetText = () => "{0} / {1}".F(currentFrame + 1, currentSprites.Length); - playButton = panel.Get("BUTTON_PLAY"); - playButton.OnClick = () => + var playButton = panel.GetOrNull("BUTTON_PLAY"); + if (playButton != null) { - spriteWidget.LoopAnimation = true; - playButton.Visible = false; - pauseButton.Visible = true; - }; - pauseButton = panel.Get("BUTTON_PAUSE"); - pauseButton.OnClick = () => - { - spriteWidget.LoopAnimation = false; - playButton.Visible = true; - pauseButton.Visible = false; - }; + playButton.OnClick = () => animateFrames = true; + playButton.IsVisible = () => !animateFrames; + } - panel.Get("BUTTON_STOP").OnClick = () => + var pauseButton = panel.GetOrNull("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("BUTTON_NEXT").OnClick = () => { spriteWidget.RenderNextFrame(); }; - panel.Get("BUTTON_PREV").OnClick = () => { spriteWidget.RenderPreviousFrame(); }; - - panel.Get("LOAD_BUTTON").OnClick = () => + var stopButton = panel.GetOrNull("BUTTON_STOP"); + if (stopButton != null) { - LoadAsset(filenameInput.Text); - }; + stopButton.OnClick = () => + { + frameSlider.Value = 0; + currentFrame = 0; + animateFrames = false; + }; + } + + var nextButton = panel.GetOrNull("BUTTON_NEXT"); + if (nextButton != null) + nextButton.OnClick = SelectNextFrame; + + var prevButton = panel.GetOrNull("BUTTON_PREV"); + if (prevButton != null) + prevButton.OnClick = SelectPreviousFrame; + + var loadButton = panel.GetOrNull("LOAD_BUTTON"); + if (loadButton != null) + loadButton.OnClick = () => LoadAsset(filenameInput.Text); assetList = panel.Get("ASSET_LIST"); template = panel.Get("ASSET_TEMPLATE"); PopulateAssetList(); - panel.Get("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; + var closeButton = panel.GetOrNull("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("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 setupItem = (palette, itemTemplate) => { + var name = palette.Name; var item = ScrollItemWidget.Setup(itemTemplate, - () => currentPalette.Name == palette.Name, - () => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; }); - item.Get("LABEL").GetText = () => palette.Name; + () => currentPalette == name, + () => currentPalette = name); + item.Get("LABEL").GetText = () => name; + return item; }; diff --git a/OpenRA.Mods.RA/Widgets/Logic/ColorPickerLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ColorPickerLogic.cs index 9ebb8231b1..56aa541566 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ColorPickerLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ColorPickerLogic.cs @@ -20,6 +20,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic [ObjectCreator.UseCtor] public ColorPickerLogic(Widget widget, HSLColor initialColor, Action onChange, WorldRenderer worldRenderer) { + var ticker = widget.GetOrNull("ANIMATE_PREVIEW"); + if (ticker != null) + { + var preview = widget.Get("PREVIEW"); + var anim = preview.GetAnimation(); + anim.PlayRepeating(anim.CurrentSequence.Name); + ticker.OnTick = () => anim.Tick(); + } + var hueSlider = widget.Get("HUE"); var mixer = widget.Get("MIXER"); var randomButton = widget.GetOrNull("RANDOM_BUTTON"); diff --git a/mods/cnc/chrome/assetbrowser.yaml b/mods/cnc/chrome/assetbrowser.yaml index 6cce12007f..73cb7518d3 100644 --- a/mods/cnc/chrome/assetbrowser.yaml +++ b/mods/cnc/chrome/assetbrowser.yaml @@ -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 diff --git a/mods/cnc/chrome/color-picker.yaml b/mods/cnc/chrome/color-picker.yaml index 0f6bd53063..4084b7e437 100644 --- a/mods/cnc/chrome/color-picker.yaml +++ b/mods/cnc/chrome/color-picker.yaml @@ -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 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/assetbrowser.yaml b/mods/ra/chrome/assetbrowser.yaml index bf01849800..ace25b9e70 100644 --- a/mods/ra/chrome/assetbrowser.yaml +++ b/mods/ra/chrome/assetbrowser.yaml @@ -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 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