diff --git a/Makefile b/Makefile index 45c4733b64..343d413e01 100644 --- a/Makefile +++ b/Makefile @@ -93,8 +93,8 @@ STD_MOD_DEPS = $(STD_MOD_LIBS) $(ralint_TARGET) mod_ra_SRCS := $(shell find OpenRA.Mods.RA/ -iname '*.cs') mod_ra_TARGET = mods/ra/OpenRA.Mods.RA.dll mod_ra_KIND = library -mod_ra_DEPS = $(STD_MOD_DEPS) -mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) +mod_ra_DEPS = $(STD_MOD_DEPS) $(utility_TARGET) +mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(utility_TARGET) mod_ra_EXTRA_CMDS = mono --debug RALint.exe ra PROGRAMS += mod_ra mod_ra: $(mod_ra_TARGET) diff --git a/OpenRA.FileFormats/Filesystem/FileSystem.cs b/OpenRA.FileFormats/Filesystem/FileSystem.cs index 396b719763..c2e1004c45 100644 --- a/OpenRA.FileFormats/Filesystem/FileSystem.cs +++ b/OpenRA.FileFormats/Filesystem/FileSystem.cs @@ -18,19 +18,21 @@ namespace OpenRA.FileFormats { public static class FileSystem { - static List mountedFolders = new List(); + static List MountedFolders = new List(); static Cache> allFiles = new Cache>( _ => new List() ); + public static List FolderPaths = new List(); + static void MountInner(IFolder folder) { - mountedFolders.Add(folder); + MountedFolders.Add(folder); - foreach( var hash in folder.AllFileHashes() ) + foreach (var hash in folder.AllFileHashes()) { var l = allFiles[hash]; - if( !l.Contains( folder ) ) - l.Add( folder ); + if (!l.Contains(folder)) + l.Add(folder); } } @@ -78,6 +80,9 @@ namespace OpenRA.FileFormats if (name.StartsWith("^")) name = Platform.SupportDir+name.Substring(1); + if (Directory.Exists(name)) + FolderPaths.Add(name); + var a = (Action)(() => FileSystem.MountInner(OpenPackage(name))); if (optional) @@ -89,28 +94,29 @@ namespace OpenRA.FileFormats public static void UnmountAll() { - mountedFolders.Clear(); + MountedFolders.Clear(); + FolderPaths.Clear(); allFiles = new Cache>( _ => new List() ); } public static bool Unmount(IFolder mount) { - return (mountedFolders.RemoveAll(f => f == mount) > 0); + return (MountedFolders.RemoveAll(f => f == mount) > 0); } public static void Mount(IFolder mount) { - if (!mountedFolders.Contains(mount)) mountedFolders.Add(mount); + if (!MountedFolders.Contains(mount)) MountedFolders.Add(mount); } - public static void LoadFromManifest( Manifest manifest ) + public static void LoadFromManifest(Manifest manifest) { UnmountAll(); foreach (var dir in manifest.Folders) Mount(dir); foreach (var pkg in manifest.Packages) Mount(pkg); } - static Stream GetFromCache( Cache> index, string filename ) + static Stream GetFromCache(Cache> index, string filename) { var folder = index[PackageEntry.HashFilename(filename)] .Where(x => x.Exists(filename)) @@ -125,21 +131,21 @@ namespace OpenRA.FileFormats public static Stream Open(string filename) { return OpenWithExts(filename, ""); } - public static Stream OpenWithExts( string filename, params string[] exts ) + public static Stream OpenWithExts(string filename, params string[] exts) { if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 ) { foreach( var ext in exts ) { - var s = GetFromCache( allFiles, filename + ext ); - if( s != null ) + var s = GetFromCache(allFiles, filename + ext); + if (s != null) return s; } } - foreach( var ext in exts ) + foreach (var ext in exts) { - var folder = mountedFolders + var folder = MountedFolders .Where(x => x.Exists(filename + ext)) .OrderByDescending(x => x.Priority) .FirstOrDefault(); @@ -151,7 +157,7 @@ namespace OpenRA.FileFormats throw new FileNotFoundException("File not found: {0}".F(filename), filename); } - public static bool Exists(string filename) { return mountedFolders.Any(f => f.Exists(filename)); } + public static bool Exists(string filename) { return MountedFolders.Any(f => f.Exists(filename)); } static Dictionary assemblyCache = new Dictionary(); diff --git a/OpenRA.FileFormats/Graphics/ShpReader.cs b/OpenRA.FileFormats/Graphics/ShpReader.cs index 2ccf5d76e1..0795b2696a 100644 --- a/OpenRA.FileFormats/Graphics/ShpReader.cs +++ b/OpenRA.FileFormats/Graphics/ShpReader.cs @@ -62,9 +62,9 @@ namespace OpenRA.FileFormats int recurseDepth = 0; - public ShpReader( Stream stream ) + public ShpReader(Stream stream) { - using( var reader = new BinaryReader( stream ) ) + using (var reader = new BinaryReader(stream)) { ImageCount = reader.ReadUInt16(); reader.ReadUInt16(); @@ -73,60 +73,60 @@ namespace OpenRA.FileFormats Height = reader.ReadUInt16(); reader.ReadUInt32(); - for( int i = 0 ; i < ImageCount ; i++ ) - headers.Add( new ImageHeader( reader ) ); + for (int i = 0 ; i < ImageCount ; i++) + headers.Add(new ImageHeader(reader)); - new ImageHeader( reader ); // end-of-file header - new ImageHeader( reader ); // all-zeroes header + new ImageHeader(reader); // end-of-file header + new ImageHeader(reader); // all-zeroes header var offsets = headers.ToDictionary(h => h.Offset, h =>h); - for( int i = 0 ; i < ImageCount ; i++ ) + for (int i = 0 ; i < ImageCount ; i++) { var h = headers[ i ]; - if( h.Format == Format.Format20 ) - h.RefImage = headers[ i - 1 ]; + if (h.Format == Format.Format20) + h.RefImage = headers[i - 1]; - else if( h.Format == Format.Format40 ) - if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) ) - throw new InvalidDataException( "Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset) ); + else if (h.Format == Format.Format40) + if (!offsets.TryGetValue(h.RefOffset, out h.RefImage)) + throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset)); } - foreach( ImageHeader h in headers ) - Decompress( stream, h ); + foreach (ImageHeader h in headers) + Decompress(stream, h); } } - public ImageHeader this[ int index ] + public ImageHeader this[int index] { - get { return headers[ index ]; } + get { return headers[index]; } } - void Decompress( Stream stream, ImageHeader h ) + void Decompress(Stream stream, ImageHeader h) { - if( recurseDepth > ImageCount ) - throw new InvalidDataException( "Format20/40 headers contain infinite loop" ); + if (recurseDepth > ImageCount) + throw new InvalidDataException("Format20/40 headers contain infinite loop"); - switch( h.Format ) + switch(h.Format) { case Format.Format20: case Format.Format40: { - if( h.RefImage.Image == null ) + if (h.RefImage.Image == null) { ++recurseDepth; - Decompress( stream, h.RefImage ); + Decompress(stream, h.RefImage); --recurseDepth; } - h.Image = CopyImageData( h.RefImage.Image ); + h.Image = CopyImageData(h.RefImage.Image); Format40.DecodeInto(ReadCompressedData(stream, h), h.Image); break; } case Format.Format80: { - var imageBytes = new byte[ Width * Height ]; - Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes ); + var imageBytes = new byte[Width * Height]; + Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes); h.Image = imageBytes; break; } @@ -135,11 +135,11 @@ namespace OpenRA.FileFormats } } - static byte[] ReadCompressedData( Stream stream, ImageHeader h ) + static byte[] ReadCompressedData(Stream stream, ImageHeader h) { stream.Position = h.Offset; - // Actually, far too big. There's no length field with the correct length though :( - var compressedLength = (int)( stream.Length - stream.Position ); + // TODO: Actually, far too big. There's no length field with the correct length though :( + var compressedLength = (int)(stream.Length - stream.Position); var compressedBytes = new byte[ compressedLength ]; stream.Read( compressedBytes, 0, compressedLength ); @@ -147,11 +147,11 @@ namespace OpenRA.FileFormats return compressedBytes; } - byte[] CopyImageData( byte[] baseImage ) + byte[] CopyImageData(byte[] baseImage) { - var imageData = new byte[ Width * Height ]; - for( int i = 0 ; i < Width * Height ; i++ ) - imageData[ i ] = baseImage[ i ]; + var imageData = new byte[Width * Height]; + for (int i = 0 ; i < Width * Height ; i++) + imageData[i] = baseImage[i]; return imageData; } diff --git a/OpenRA.FileFormats/Manifest.cs b/OpenRA.FileFormats/Manifest.cs index 1db3f1bbf1..989574cb62 100644 --- a/OpenRA.FileFormats/Manifest.cs +++ b/OpenRA.FileFormats/Manifest.cs @@ -9,6 +9,7 @@ #endregion using System.Collections.Generic; +using System.IO; using System.Linq; namespace OpenRA.FileFormats @@ -20,7 +21,8 @@ namespace OpenRA.FileFormats public readonly string[] Mods, Folders, Packages, Rules, ServerTraits, Sequences, Cursors, Chrome, Assemblies, ChromeLayout, - Weapons, Voices, Notifications, Music, Movies, TileSets, ChromeMetrics; + Weapons, Voices, Notifications, Music, Movies, TileSets, + ChromeMetrics, PackageContents; public readonly MiniYaml LoadScreen; public readonly Dictionary> Fonts; public readonly int TileSize = 24; @@ -29,7 +31,7 @@ namespace OpenRA.FileFormats { Mods = mods; var yaml = new MiniYaml(null, mods - .Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml")) + .Select(m => MiniYaml.FromFile("mods{0}{1}{0}mod.yaml".F(Path.DirectorySeparatorChar, m))) .Aggregate(MiniYaml.MergeLiberal)).NodesDict; // TODO: Use fieldloader @@ -49,6 +51,7 @@ namespace OpenRA.FileFormats Movies = YamlList(yaml, "Movies"); TileSets = YamlList(yaml, "TileSets"); ChromeMetrics = YamlList(yaml, "ChromeMetrics"); + PackageContents = YamlList(yaml, "PackageContents"); LoadScreen = yaml["LoadScreen"]; Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key, diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 3e8a69fa0f..28b59218cb 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -238,7 +238,7 @@ namespace OpenRA public static Dictionary CurrentMods { - get { return Mod.AllMods.Where( k => modData.Manifest.Mods.Contains( k.Key )).ToDictionary( k => k.Key, k => k.Value ); } + get { return Mod.AllMods.Where(k => modData.Manifest.Mods.Contains(k.Key)).ToDictionary(k => k.Key, k => k.Value); } } static Modifiers modifiers; diff --git a/OpenRA.Game/GameRules/Rules.cs b/OpenRA.Game/GameRules/Rules.cs index bf0d6fd4d5..2b6842ff01 100755 --- a/OpenRA.Game/GameRules/Rules.cs +++ b/OpenRA.Game/GameRules/Rules.cs @@ -25,6 +25,7 @@ namespace OpenRA public static Dictionary Music; public static Dictionary Movies; public static Dictionary TileSets; + public static Dictionary PackageContents; public static void LoadRules(Manifest m, Map map) { @@ -35,6 +36,7 @@ namespace OpenRA Notifications = LoadYamlRules(m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value)); Music = LoadYamlRules(m.Music, new List(), (k, _) => new MusicInfo(k.Key, k.Value)); Movies = LoadYamlRules(m.Movies, new List(), (k, v) => k.Value.Value); + PackageContents = LoadYamlRules(m.PackageContents, new List(), (k, v) => k.Value.Value); TileSets = new Dictionary(); foreach (var file in m.TileSets) @@ -46,7 +48,7 @@ namespace OpenRA static Dictionary LoadYamlRules(string[] files, List dict, Func, T> f) { - var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict,MiniYaml.MergeLiberal); + var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict, MiniYaml.MergeLiberal); var yy = y.ToDictionary( x => x.Key, x => x.Value ); return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy)); } diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index 97134fc646..ca6e7f49b9 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -16,11 +16,11 @@ namespace OpenRA.Graphics { public class SpriteLoader { - public SpriteLoader( string[] exts, SheetBuilder sheetBuilder ) + public SpriteLoader(string[] exts, SheetBuilder sheetBuilder) { SheetBuilder = sheetBuilder; this.exts = exts; - sprites = new Cache( LoadSprites ); + sprites = new Cache(LoadSprites); } readonly SheetBuilder SheetBuilder; diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index f5c298d4b7..51d9f11fb8 100755 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -29,14 +29,14 @@ namespace OpenRA public SheetBuilder SheetBuilder; public SpriteLoader SpriteLoader; - public ModData( params string[] mods ) + public ModData(params string[] mods) { - Manifest = new Manifest( mods ); - ObjectCreator = new ObjectCreator( Manifest ); + Manifest = new Manifest(mods); + ObjectCreator = new ObjectCreator(Manifest); LoadScreen = ObjectCreator.CreateObject(Manifest.LoadScreen.Value); LoadScreen.Init(Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value)); LoadScreen.Display(); - WidgetLoader = new WidgetLoader( this ); + WidgetLoader = new WidgetLoader(this); } public void LoadInitialAssets(bool enumMaps) diff --git a/OpenRA.Game/Widgets/ScrollPanelWidget.cs b/OpenRA.Game/Widgets/ScrollPanelWidget.cs index b227547bb2..b88c15b112 100644 --- a/OpenRA.Game/Widgets/ScrollPanelWidget.cs +++ b/OpenRA.Game/Widgets/ScrollPanelWidget.cs @@ -26,6 +26,7 @@ namespace OpenRA.Widgets public string Background = "scrollpanel-bg"; public int ContentHeight = 0; public ILayout Layout; + public int MinimumThumbSize = 10; protected float ListOffset = 0; protected bool UpPressed = false; protected bool DownPressed = false; @@ -79,7 +80,7 @@ namespace OpenRA.Widgets var ScrollbarHeight = rb.Height - 2 * ScrollbarWidth; - var thumbHeight = ContentHeight == 0 ? 0 : (int)(ScrollbarHeight*Math.Min(rb.Height*1f/ContentHeight, 1f)); + var thumbHeight = ContentHeight == 0 ? 0 : Math.Max(MinimumThumbSize, (int)(ScrollbarHeight*Math.Min(rb.Height*1f/ContentHeight, 1f))); var thumbOrigin = rb.Y + ScrollbarWidth + (int)((ScrollbarHeight - thumbHeight)*(-1f*ListOffset/(ContentHeight - rb.Height))); if (thumbHeight == ScrollbarHeight) thumbHeight = 0; @@ -206,7 +207,7 @@ namespace OpenRA.Widgets { var rb = RenderBounds; var ScrollbarHeight = rb.Height - 2 * ScrollbarWidth; - var thumbHeight = ContentHeight == 0 ? 0 : (int)(ScrollbarHeight*Math.Min(rb.Height*1f/ContentHeight, 1f)); + var thumbHeight = ContentHeight == 0 ? 0 : Math.Max(MinimumThumbSize, (int)(ScrollbarHeight*Math.Min(rb.Height*1f/ContentHeight, 1f))); var oldOffset = ListOffset; ListOffset += (int)((lastMouseLocation.Y - mi.Location.Y)*(ContentHeight - rb.Height)*1f/(ScrollbarHeight - thumbHeight)); ListOffset = Math.Min(0,Math.Max(rb.Height - ContentHeight, ListOffset)); diff --git a/OpenRA.Game/Widgets/ShpImageWidget.cs b/OpenRA.Game/Widgets/ShpImageWidget.cs index 88388f1aca..7198598ccb 100644 --- a/OpenRA.Game/Widgets/ShpImageWidget.cs +++ b/OpenRA.Game/Widgets/ShpImageWidget.cs @@ -18,6 +18,7 @@ namespace OpenRA.Widgets public string Image = ""; public int Frame = 0; public string Palette = "chrome"; + public bool LoopAnimation = false; public Func GetImage; public Func GetFrame; @@ -26,12 +27,13 @@ namespace OpenRA.Widgets readonly WorldRenderer worldRenderer; [ObjectCreator.UseCtor] - public ShpImageWidget( WorldRenderer worldRenderer) + public ShpImageWidget(WorldRenderer worldRenderer) : base() { GetImage = () => { return Image; }; GetFrame = () => { return Frame; }; GetPalette = () => { return Palette; }; + this.worldRenderer = worldRenderer; } @@ -41,9 +43,12 @@ namespace OpenRA.Widgets Image = other.Image; Frame = other.Frame; Palette = other.Palette; + LoopAnimation = other.LoopAnimation; + GetImage = other.GetImage; GetFrame = other.GetFrame; GetPalette = other.GetPalette; + worldRenderer = other.worldRenderer; } @@ -68,5 +73,32 @@ namespace OpenRA.Widgets Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin, worldRenderer, 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/SliderWidget.cs b/OpenRA.Game/Widgets/SliderWidget.cs index 545cfd161f..d172914f8f 100755 --- a/OpenRA.Game/Widgets/SliderWidget.cs +++ b/OpenRA.Game/Widgets/SliderWidget.cs @@ -24,10 +24,15 @@ namespace OpenRA.Widgets public float MinimumValue = 0; public float MaximumValue = 1; public float Value = 0; + public Func GetValue; protected bool isMoving = false; - public SliderWidget() : base() {} + public SliderWidget() + : base() + { + GetValue = () => Value; + } public SliderWidget(SliderWidget other) : base(other) @@ -38,6 +43,7 @@ namespace OpenRA.Widgets MaximumValue = other.MaximumValue; Value = other.Value; TrackHeight = other.TrackHeight; + GetValue = other.GetValue; } void UpdateValue(float newValue) @@ -53,7 +59,7 @@ namespace OpenRA.Widgets if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi)) return false; if (!Focused) return false; - switch( mi.Event ) + switch(mi.Event) { case MouseInputEvent.Up: isMoving = false; @@ -99,6 +105,8 @@ namespace OpenRA.Widgets if (!IsVisible()) return; + Value = GetValue(); + var tr = ThumbRect; var rb = RenderBounds; var trackWidth = rb.Width; diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs index ad179c422f..7120dacc3e 100644 --- a/OpenRA.Game/Widgets/WidgetUtils.cs +++ b/OpenRA.Game/Widgets/WidgetUtils.cs @@ -227,6 +227,12 @@ namespace OpenRA.Widgets return Mod.AllMods[mod].Title; } + public static string ActiveModId() + { + var mod = Game.modData.Manifest.Mods[0]; + return Mod.AllMods[mod].Id; + } + public static string ChooseInitialMap(string map) { var availableMaps = Game.modData.AvailableMaps; diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index f1ef383574..cc11db4350 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -436,6 +436,8 @@ + + @@ -448,6 +450,10 @@ OpenRA.Game False + + {F33337BE-CB69-4B24-850F-07D23E408DDF} + OpenRA.Utility + diff --git a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs new file mode 100644 index 0000000000..91da7972ee --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs @@ -0,0 +1,261 @@ +#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.Collections.Generic; +using System.IO; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.GameRules; +using OpenRA.Graphics; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets.Logic +{ + public class AssetBrowserLogic + { + Widget panel; + + static ShpImageWidget spriteImage; + static TextFieldWidget filenameInput; + static SliderWidget frameSlider; + static ButtonWidget playButton, pauseButton; + static ScrollPanelWidget assetList; + static ScrollItemWidget template; + + public enum SourceType { Folders, Packages } + public static SourceType AssetSource = SourceType.Folders; + + public static List AvailableShps = new List(); + + [ObjectCreator.UseCtor] + public AssetBrowserLogic(Widget widget, Action onExit, World world) + { + panel = widget; + + var sourceDropdown = panel.Get("SOURCE_SELECTOR"); + sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); + sourceDropdown.GetText = () => AssetSource == SourceType.Folders ? "Folders" + : AssetSource == SourceType.Packages ? "Packages" : "None"; + sourceDropdown.Disabled = !Rules.PackageContents.Keys.Any(); + + spriteImage = panel.Get("SPRITE"); + + filenameInput = panel.Get("FILENAME_INPUT"); + filenameInput.Text = spriteImage.Image+".shp"; + filenameInput.OnEnterKey = () => LoadAsset(filenameInput.Text); + + frameSlider = panel.Get("FRAME_SLIDER"); + frameSlider.MaximumValue = (float)spriteImage.FrameCount; + frameSlider.Ticks = spriteImage.FrameCount+1; + frameSlider.OnChange += x => { spriteImage.Frame = (int)Math.Round(x); }; + frameSlider.GetValue = () => spriteImage.Frame; + + panel.Get("FRAME_COUNT").GetText = () => "{0}/{1}".F(spriteImage.Frame, spriteImage.FrameCount); + + playButton = panel.Get("BUTTON_PLAY"); + playButton.OnClick = () => + { + spriteImage.LoopAnimation = true; + playButton.Visible = false; + pauseButton.Visible = true; + }; + pauseButton = panel.Get("BUTTON_PAUSE"); + pauseButton.OnClick = () => + { + spriteImage.LoopAnimation = false; + playButton.Visible = true; + pauseButton.Visible = false; + }; + + panel.Get("BUTTON_STOP").OnClick = () => + { + spriteImage.LoopAnimation = false; + frameSlider.Value = 0; + spriteImage.Frame = 0; + playButton.Visible = true; + pauseButton.Visible = false; + }; + + panel.Get("BUTTON_NEXT").OnClick = () => { spriteImage.RenderNextFrame(); }; + panel.Get("BUTTON_PREV").OnClick = () => { spriteImage.RenderPreviousFrame(); }; + + panel.Get("LOAD_BUTTON").OnClick = () => + { + LoadAsset(filenameInput.Text); + }; + + assetList = panel.Get("ASSET_LIST"); + template = panel.Get("ASSET_TEMPLATE"); + PopulateAssetList(); + + var palette = (WidgetUtils.ActiveModId() == "d2k") ? "d2k.pal" : "egopal.pal"; + + panel.Get("EXPORT_BUTTON").OnClick = () => + { + var ExtractGameFiles = new string[][] + { + new string[] {"--extract", WidgetUtils.ActiveModId(), palette, "--userdir"}, + new string[] {"--extract", WidgetUtils.ActiveModId(), "{0}.shp".F(spriteImage.Image), "--userdir"}, + }; + + var ExportToPng = new string[][] + { + new string[] {"--png", Platform.SupportDir+"{0}.shp".F(spriteImage.Image), Platform.SupportDir+palette}, + }; + + var ImportFromPng = new string[][] { }; + + var args = new WidgetArgs() + { + { "ExtractGameFiles", ExtractGameFiles }, + { "ExportToPng", ExportToPng }, + { "ImportFromPng", ImportFromPng} + }; + + Ui.OpenWindow("CONVERT_ASSETS_PANEL", args); + }; + + panel.Get("EXTRACT_BUTTON").OnClick = () => + { + var ExtractGameFilesList = new List(); + var ExportToPngList = new List(); + + ExtractGameFilesList.Add(new string[] { "--extract", WidgetUtils.ActiveModId(), palette, "--userdir"} ); + + foreach (var shp in AvailableShps) + { + ExtractGameFilesList.Add(new string[] { "--extract", WidgetUtils.ActiveModId(), shp, "--userdir" } ); + ExportToPngList.Add(new string[] { "--png", Platform.SupportDir+shp, Platform.SupportDir+palette } ); + Console.WriteLine(Platform.SupportDir+shp); + } + + var ExtractGameFiles = ExtractGameFilesList.ToArray(); + var ExportToPng = ExportToPngList.ToArray(); + var ImportFromPng = new string[][] { }; + + var args = new WidgetArgs() + { + { "ExtractGameFiles", ExtractGameFiles }, + { "ExportToPng", ExportToPng }, + { "ImportFromPng", ImportFromPng} + }; + + Ui.OpenWindow("CONVERT_ASSETS_PANEL", args); + }; + + + panel.Get("IMPORT_BUTTON").OnClick = () => + { + var imageSizeInput = panel.Get("IMAGE_SIZE_INPUT"); + var imageFilename = panel.Get("IMAGE_FILENAME_INPUT"); + + var ExtractGameFiles = new string[][] { }; + var ExportToPng = new string[][] { }; + var ImportFromPng = new string[][] + { + new string[] {"--shp", Platform.SupportDir+imageFilename.Text, imageSizeInput.Text}, + }; + + var args = new WidgetArgs() + { + { "ExtractGameFiles", ExtractGameFiles }, + { "ExportToPng", ExportToPng }, + { "ImportFromPng", ImportFromPng} + }; + + Ui.OpenWindow("CONVERT_ASSETS_PANEL", args); + }; + + panel.Get("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; + } + + static void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template) + { + var sprite = Path.GetFileNameWithoutExtension(filepath); + var filename = Path.GetFileName(filepath); + + var item = ScrollItemWidget.Setup(template, + () => spriteImage != null && spriteImage.Image == sprite, + () => LoadAsset(sprite)); + item.Get("TITLE").GetText = () => filename; + + list.AddChild(item); + } + + static bool LoadAsset(string sprite) + { + if (sprite == null) + return false; + + if (!sprite.ToLower().Contains("r8")) + { + filenameInput.Text = sprite+".shp"; + sprite = Path.GetFileNameWithoutExtension(sprite); + } + + spriteImage.Frame = 0; + spriteImage.Image = sprite; + frameSlider.MaximumValue = (float)spriteImage.FrameCount; + frameSlider.Ticks = spriteImage.FrameCount+1; + return true; + } + + public static bool ShowSourceDropdown(DropDownButtonWidget dropdown) + { + var options = new Dictionary() + { + { "Folders", SourceType.Folders }, + { "Packages", SourceType.Packages }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => AssetSource == options[o], + () => { AssetSource = options[o]; PopulateAssetList(); }); + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + return true; + } + + public static void PopulateAssetList() + { + assetList.RemoveChildren(); + AvailableShps.Clear(); + + if (AssetSource == SourceType.Folders) + { + foreach (var folder in FileSystem.FolderPaths) + { + if (Directory.Exists(folder)) + { + var shps = Directory.GetFiles(folder, "*.shp"); + foreach (var shp in shps) + { + AddAsset(assetList, shp, template); + AvailableShps.Add(Path.GetFileName(shp)); + } + } + } + } + + if (AssetSource == SourceType.Packages) + foreach (var hiddenFile in Rules.PackageContents.Keys) + { + AddAsset(assetList, hiddenFile, template); + AvailableShps.Add(hiddenFile); + } + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs new file mode 100644 index 0000000000..8c1f537a9d --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/Logic/ConvertGameFilesLogic.cs @@ -0,0 +1,113 @@ +#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.IO; +using System.Linq; +using System.Threading; +using System.Diagnostics; +using OpenRA.FileFormats; +using OpenRA.FileFormats.Graphics; +using OpenRA.Widgets; +using OpenRA.Utility; + +namespace OpenRA.Mods.RA.Widgets.Logic +{ + public class ConvertGameFilesLogic + { + Widget panel; + ProgressBarWidget progressBar; + LabelWidget statusLabel; + ButtonWidget retryButton, backButton; + Widget extractingContainer; + + string[][] ExtractGameFiles, ExportToPng, ImportFromPng; + + [ObjectCreator.UseCtor] + public ConvertGameFilesLogic(Widget widget, string[][] ExtractGameFiles, string[][] ExportToPng, string[][] ImportFromPng) + { + panel = widget.Get("CONVERT_ASSETS_PANEL"); + progressBar = panel.Get("PROGRESS_BAR"); + statusLabel = panel.Get("STATUS_LABEL"); + + backButton = panel.Get("BACK_BUTTON"); + backButton.OnClick = Ui.CloseWindow; + + retryButton = panel.Get("RETRY_BUTTON"); + retryButton.OnClick = Extract; + + extractingContainer = panel.Get("EXTRACTING"); + + this.ExtractGameFiles = ExtractGameFiles; + this.ExportToPng = ExportToPng; + this.ImportFromPng = ImportFromPng; + + Extract(); + } + + void Extract() + { + backButton.IsDisabled = () => true; + retryButton.IsDisabled = () => true; + extractingContainer.IsVisible = () => true; + + var onError = (Action)(s => Game.RunAfterTick(() => + { + statusLabel.GetText = () => "Error: "+s; + backButton.IsDisabled = () => false; + retryButton.IsDisabled = () => false; + })); + + var t = new Thread( _ => + { + try + { + for (int i = 0; i < ExtractGameFiles.Length; i++) + { + progressBar.Percentage = i*100/ExtractGameFiles.Count(); + statusLabel.GetText = () => "Extracting..."; + Utility.Command.ExtractFiles(ExtractGameFiles[i]); + } + + for (int i = 0; i < ExportToPng.Length; i++) + { + progressBar.Percentage = i*100/ExportToPng.Count(); + statusLabel.GetText = () => "Exporting SHP to PNG..."; + Utility.Command.ConvertShpToPng(ExportToPng[i]); + } + + for (int i = 0; i < ImportFromPng.Length; i++) + { + progressBar.Percentage = i*100/ImportFromPng.Count(); + statusLabel.GetText = () => "Converting PNG to SHP..."; + Utility.Command.ConvertPngToShp(ImportFromPng[i]); + } + + Game.RunAfterTick(() => + { + progressBar.Percentage = 100; + statusLabel.GetText = () => "Done. Check {0}".F(Platform.SupportDir); + backButton.IsDisabled = () => false; + }); + } + catch (FileNotFoundException f) + { + onError(f.FileName+" not found."); + } + catch (Exception e) + { + onError(e.Message); + } + + }) { IsBackground = true }; + t.Start(); + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs index 46f713596b..2ad69c8871 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -14,7 +14,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic { public class MainMenuButtonsLogic { - enum MenuType { Main, None } MenuType Menu = MenuType.Main; @@ -73,6 +72,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic }); }; + widget.Get("MAINMENU_BUTTON_ASSET_BROWSER").OnClick = () => + { + Menu = MenuType.None; + Game.OpenWindow("ASSETBROWSER_BG", new WidgetArgs() + { + { "onExit", () => Menu = MenuType.Main } + }); + }; + widget.Get("MAINMENU_BUTTON_QUIT").OnClick = () => Game.Exit(); } diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 82f321abad..15d9611fb6 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -55,7 +55,7 @@ namespace OpenRA.Utility ShpWriter.Write(destStream, width, srcImage.Height, srcImage.ToFrames(width)); - Console.WriteLine(dest+" saved"); + Console.WriteLine(dest+" saved."); } static IEnumerable ToFrames(this Bitmap bitmap, int width) @@ -108,10 +108,11 @@ namespace OpenRA.Utility x += srcImage.Width; - bitmap.UnlockBits( data ); + bitmap.UnlockBits(data); } bitmap.Save(dest); + Console.WriteLine(dest+" saved"); } } @@ -348,8 +349,8 @@ namespace OpenRA.Utility if (template.Value == null) throw new InvalidOperationException("No such template '{0}'".F(templateName)); - using( var image = tileset.RenderTemplate(template.Value.Id, palette) ) - image.Save( Path.ChangeExtension( templateName, ".png" ) ); + using (var image = tileset.RenderTemplate(template.Value.Id, palette)) + image.Save(Path.ChangeExtension(templateName, ".png")); } } @@ -359,17 +360,17 @@ namespace OpenRA.Utility var dest = args[2]; Dune2ShpReader srcImage = null; - using( var s = File.OpenRead( src ) ) + using(var s = File.OpenRead(src)) srcImage = new Dune2ShpReader(s); var size = srcImage.First().Size; - if (!srcImage.All( im => im.Size == size )) + if (!srcImage.All(im => im.Size == size)) throw new InvalidOperationException("All the frames must be the same size to convert from Dune2 to RA"); - using( var destStream = File.Create(dest) ) + using (var destStream = File.Create(dest)) ShpWriter.Write(destStream, size.Width, size.Height, - srcImage.Select( im => im.Image )); + srcImage.Select(im => im.Image)); } public static void ExtractFiles(string[] args) @@ -380,14 +381,18 @@ namespace OpenRA.Utility var manifest = new Manifest(mods); FileSystem.LoadFromManifest(manifest); - foreach( var f in files ) + foreach (var f in files) { + if (f == "--userdir") + break; + var src = FileSystem.Open(f); if (src == null) throw new InvalidOperationException("File not found: {0}".F(f)); var data = src.ReadAllBytes(); - - File.WriteAllBytes( f, data ); + var output = args.Contains("--userdir") ? Platform.SupportDir+f : f; + File.WriteAllBytes(output, data); + Console.WriteLine(output+" saved."); } } diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index 7fae4fb735..d891ef2218 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -60,7 +60,7 @@ namespace OpenRA.Utility Console.WriteLine(" --shp PNGFILE FRAMEWIDTH Convert a single PNG with multiple frames appended after another to a SHP"); Console.WriteLine(" --png SHPFILE PALETTE [--noshadow] Convert a SHP to a PNG containing all of its frames, optionally removing the shadow"); Console.WriteLine(" --fromd2 DUNE2SHP C&CSHP Convert a Dune II SHP (C&C mouse cursor) to C&C SHP format."); - Console.WriteLine(" --extract MOD[,MOD]* FILES Extract files from mod packages"); + Console.WriteLine(" --extract MOD[,MOD]* FILES [--userdir] Extract files from mod packages to the current (or user) directory"); Console.WriteLine(" --tmp-png MOD[,MOD]* THEATER FILES Extract terrain tiles to PNG"); Console.WriteLine(" --remap SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP Remap SHPs to another palette"); Console.WriteLine(" --r8 R8FILE PALETTE START END FILENAME [--noshadow] [--infrantry] [--vehicle] [--projectile] [--building] [--wall] [--tileset] Convert Dune 2000 DATA.R8 to PNGs choosing start- and endframe as well as type for correct offset to append multiple frames to one PNG named by filename optionally removing the shadow."); diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index a306881e58..9b6a4fa3fb 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -29,6 +29,8 @@ Packages: ~scores2.mix ~transit.mix +PackageContents: + Rules: mods/cnc/rules/defaults.yaml mods/cnc/rules/system.yaml diff --git a/mods/d2k/chrome/mainmenu.yaml b/mods/d2k/chrome/mainmenu.yaml index 2e762ef458..c9092ef014 100644 --- a/mods/d2k/chrome/mainmenu.yaml +++ b/mods/d2k/chrome/mainmenu.yaml @@ -2,7 +2,7 @@ Background@MAINMENU: X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - HEIGHT)/2 Width:250 - Height:420 + Height:460 Visible:true Logic:MainMenuButtonsLogic Children: @@ -63,11 +63,18 @@ Background@MAINMENU: Height:25 Text:Replay Viewer Font:Bold - Button@MAINMENU_BUTTON_QUIT: + Button@MAINMENU_BUTTON_ASSET_BROWSER: X:45 Y:350 Width:160 Height:25 + Text:Asset Browser + Font:Bold + Button@MAINMENU_BUTTON_QUIT: + X:45 + Y:390 + Width:160 + Height:25 Text:Quit Font:Bold Background@PERF_BG: diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 6c759fa3b1..dbebb7c280 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -21,6 +21,8 @@ Packages: ~main.mix conquer.mix +PackageContents: + Rules: mods/d2k/rules/system.yaml mods/d2k/rules/defaults.yaml @@ -66,6 +68,9 @@ ChromeLayout: mods/ra/chrome/cheats.yaml mods/ra/chrome/musicplayer.yaml mods/d2k/chrome/tooltips.yaml + mods/ra/chrome/assetbrowser.yaml + mods/ra/chrome/convertassets.yaml + Weapons: mods/d2k/weapons/defaults.yaml mods/d2k/weapons/explosions.yaml diff --git a/mods/ra/bits/desert/br1a.shp b/mods/ra/bits/desert/br1a.shp deleted file mode 100644 index 5b051ad067..0000000000 Binary files a/mods/ra/bits/desert/br1a.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br1b.shp b/mods/ra/bits/desert/br1b.shp deleted file mode 100644 index 19e97f6b3d..0000000000 Binary files a/mods/ra/bits/desert/br1b.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br1c.shp b/mods/ra/bits/desert/br1c.shp deleted file mode 100644 index e2fb891432..0000000000 Binary files a/mods/ra/bits/desert/br1c.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br1x.shp b/mods/ra/bits/desert/br1x.shp deleted file mode 100644 index 184593b0fc..0000000000 Binary files a/mods/ra/bits/desert/br1x.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br2a.shp b/mods/ra/bits/desert/br2a.shp deleted file mode 100644 index 30db9909bc..0000000000 Binary files a/mods/ra/bits/desert/br2a.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br2b.shp b/mods/ra/bits/desert/br2b.shp deleted file mode 100644 index 3ed2328f64..0000000000 Binary files a/mods/ra/bits/desert/br2b.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br2c.shp b/mods/ra/bits/desert/br2c.shp deleted file mode 100644 index 1261082a6b..0000000000 Binary files a/mods/ra/bits/desert/br2c.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br2x.shp b/mods/ra/bits/desert/br2x.shp deleted file mode 100644 index 0b1ce734dc..0000000000 Binary files a/mods/ra/bits/desert/br2x.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3a.shp b/mods/ra/bits/desert/br3a.shp deleted file mode 100644 index 602c082224..0000000000 Binary files a/mods/ra/bits/desert/br3a.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3b.shp b/mods/ra/bits/desert/br3b.shp deleted file mode 100644 index bd110e9062..0000000000 Binary files a/mods/ra/bits/desert/br3b.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3c.shp b/mods/ra/bits/desert/br3c.shp deleted file mode 100644 index 651e6c53f7..0000000000 Binary files a/mods/ra/bits/desert/br3c.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3d.shp b/mods/ra/bits/desert/br3d.shp deleted file mode 100644 index 522aa5bcef..0000000000 Binary files a/mods/ra/bits/desert/br3d.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3e.shp b/mods/ra/bits/desert/br3e.shp deleted file mode 100644 index 78e6e22e96..0000000000 Binary files a/mods/ra/bits/desert/br3e.shp and /dev/null differ diff --git a/mods/ra/bits/desert/br3f.shp b/mods/ra/bits/desert/br3f.shp deleted file mode 100644 index 53488c796f..0000000000 Binary files a/mods/ra/bits/desert/br3f.shp and /dev/null differ diff --git a/mods/ra/chrome/assetbrowser.yaml b/mods/ra/chrome/assetbrowser.yaml new file mode 100644 index 0000000000..fb77ec748c --- /dev/null +++ b/mods/ra/chrome/assetbrowser.yaml @@ -0,0 +1,203 @@ +Background@ASSETBROWSER_BG: + Logic:AssetBrowserLogic + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Width:700 + Height:410 + Children: + Label@ASSETBROWSER_TITLE: + X:0 + Y:20 + Width:PARENT_RIGHT + Height:25 + Text:Game Asset Viewer & Converter + Align:Center + Font:Bold + DropDownButton@SOURCE_SELECTOR: + X:40 + Y:45 + Width:160 + Height:25 + Font:Bold + Text:Folders + ScrollPanel@ASSET_LIST: + X:40 + Y:80 + Width:160 + Height:190 + Children: + ScrollItem@ASSET_TEMPLATE: + Width:PARENT_RIGHT-27 + Height:25 + X:2 + Y:0 + Visible:false + Children: + Label@TITLE: + X:10 + Width:PARENT_RIGHT-20 + Height:25 + TextField@FILENAME_INPUT: + X:40 + Y:280 + Width:140 + Height:25 + Button@LOAD_BUTTON: + X:40 + Y:310 + Width:140 + Height:25 + Text:Load + Font:Bold + Key:return + Label@PREVIEW_TITLE: + X:320 + Y:45 + Width:PARENT_RIGHT + Height:25 + Text:Preview + Font:Bold + Background@SPRITE_BG: + X:220 + Y:80 + Width:250 + Height:250 + Background:dialog4 + Children: + ShpImage@SPRITE: + X:4 + Y:4 + Width:246 + Height:246 + Image:mouse + Palette:colorpicker + Label@ACTIONS_TITLE: + X:PARENT_RIGHT - 150 + Y:45 + Width:PARENT_RIGHT + Height:25 + Text:Actions + Font:Bold + Button@EXPORT_BUTTON: + X:PARENT_RIGHT - 200 + Y:80 + Width:160 + Height:25 + Text:Selected to PNG + Font:Bold + Button@EXTRACT_BUTTON: + X:PARENT_RIGHT - 200 + Y:115 + Width:160 + Height:25 + Text:Extract all to PNG + Font:Bold + TextField@IMAGE_FILENAME_INPUT: + X:PARENT_RIGHT - 200 + Y:PARENT_BOTTOM - 235 + Width:100 + Height:25 + Text:pixelart.png + TextField@IMAGE_SIZE_INPUT: + X:PARENT_RIGHT - 90 + Y:PARENT_BOTTOM - 235 + Width:50 + Height:25 + Text:width + Button@IMPORT_BUTTON: + X:PARENT_RIGHT - 200 + Y:PARENT_BOTTOM - 200 + Width:160 + Height:25 + Text:Import from PNG + Font:Bold + Button@CLOSE_BUTTON: + X:PARENT_RIGHT - 200 + Y:PARENT_BOTTOM - 115 + Width:160 + Height:25 + Text:Close + Font:Bold + Key:escape + Container@FRAME_SELECTOR: + X:45 + Y:360 + Children: + Button@BUTTON_PREV: + X:0 + Y:0 + Width:25 + Height:25 + Children: + Image@IMAGE_PREV: + X:0 + Y:0 + Width:25 + Height:25 + ImageCollection:music + ImageName:prev + Button@BUTTON_PLAY: + X:35 + Y:0 + Width:25 + Height:25 + Children: + Image@IMAGE_PLAY: + X:0 + Y:0 + Width:25 + Height:25 + ImageCollection:music + ImageName:play + Button@BUTTON_PAUSE: + Visible: no + X:35 + Y:0 + Width:25 + Height:25 + Children: + Image@IMAGE_PAUSE: + X:0 + Y:0 + Width:25 + Height:25 + ImageCollection:music + ImageName:pause + Button@BUTTON_STOP: + X:70 + Y:0 + Width:25 + Height:25 + Children: + Image@IMAGE_STOP: + X:0 + Y:0 + Width:25 + Height:25 + ImageCollection:music + ImageName:stop + Button@BUTTON_NEXT: + X:105 + Y:0 + Width:25 + Height:25 + Children: + Image@IMAGE_NEXT: + X:0 + Y:0 + Width:25 + Height:25 + ImageCollection:music + ImageName:next + Slider@FRAME_SLIDER: + X:160 + Y:0 + Width:410 + Height:20 + MinimumValue: 0 + Label@FRAME_COUNT: + X:585 + Y:0 + Width:25 + Height:25 + Font:Bold \ No newline at end of file diff --git a/mods/ra/chrome/convertassets.yaml b/mods/ra/chrome/convertassets.yaml new file mode 100644 index 0000000000..ecd4cc73af --- /dev/null +++ b/mods/ra/chrome/convertassets.yaml @@ -0,0 +1,47 @@ +Background@CONVERT_ASSETS_PANEL: + Logic:ConvertGameFilesLogic + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Width:500 + Height:160 + Children: + Label@TITLE: + X:0 + Y:20 + Width:PARENT_RIGHT + Height:25 + Text:Extracting and Converting Gamefiles + Align:Center + Font:Bold + Container@EXTRACTING: + Width:PARENT_RIGHT + Height:PARENT_BOTTOM + Visible: false + Children: + ProgressBar@PROGRESS_BAR: + X:50 + Y:55 + Width:PARENT_RIGHT - 100 + Height:25 + Label@STATUS_LABEL: + X:50 + Y:80 + Width:PARENT_RIGHT - 100 + Height:25 + Align:Left + Button@RETRY_BUTTON: + X:PARENT_RIGHT - 280 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Text:Retry + Font:Bold + Key:return + Button@BACK_BUTTON: + X:PARENT_RIGHT - 140 + Y:PARENT_BOTTOM - 45 + Width:120 + Height:25 + Text:Back + Font:Bold + Key:escape \ No newline at end of file diff --git a/mods/ra/chrome/mainmenu.yaml b/mods/ra/chrome/mainmenu.yaml index 08b9df2ef7..caac30da30 100644 --- a/mods/ra/chrome/mainmenu.yaml +++ b/mods/ra/chrome/mainmenu.yaml @@ -23,7 +23,7 @@ Container@MAINMENU: X:(WINDOW_RIGHT - WIDTH)/8 Y:(WINDOW_BOTTOM - HEIGHT)/2 Width:250 - Height:505 + Height:555 Logic:MainMenuButtonsLogic Children: Label@MAINMENU_LABEL_TITLE: @@ -83,11 +83,18 @@ Container@MAINMENU: Height:35 Text:Replay Viewer Font:Bold - Button@MAINMENU_BUTTON_QUIT: + Button@MAINMENU_BUTTON_ASSET_BROWSER: X:45 Y:430 Width:160 Height:35 + Text:Asset Browser + Font:Bold + Button@MAINMENU_BUTTON_QUIT: + X:45 + Y:480 + Width:160 + Height:35 Text:Quit Font:Bold Background@PERF_BG: diff --git a/mods/ra/mix/conquer.yaml b/mods/ra/mix/conquer.yaml new file mode 100644 index 0000000000..83bba64bc1 --- /dev/null +++ b/mods/ra/mix/conquer.yaml @@ -0,0 +1,227 @@ +# conquer.mix filename list for the game asset browser +#appear1.aud: +#beepy6.aud: +#briefing.aud: +#clock1.aud: +#country1.aud: +#country4.aud: +#keystrok.aud: +#mapwipe2.aud: +#mapwipe5.aud: +#scold1.aud: +#sfx4.aud: +#toney10.aud: +#toney4.aud: +#toney7.aud: +#type.fnt: +#alibackh.pcx: +#sovback.pcx: +120mm.shp: +1tnk.shp:light tank +2tnk.shp:medium tank +3tnk.shp:heavy tank +4tnk.shp:mammoth tank +50cal.shp: +afld.shp: +afldmake.shp: +agun.shp: +agunmake.shp: +apc.shp: +apwr.shp: +apwrmake.shp: +armor.shp: +art-exp1.shp: +arty.shp: +atek.shp: +atekmake.shp: +atomicdn.shp: +atomicup.shp: +atomsfx.shp: +badr.shp: +bar3bhr.shp: +bar3blu.shp: +bar3red.shp: +bar3rhr.shp: +barb.shp: +barl.shp: +barr.shp: +barrmake.shp: +bio.shp: +biomake.shp: +bomb.shp: +bomblet.shp: +brik.shp: +brl3.shp: +burn-l.shp: +burn-m.shp: +burn-s.shp: +ca.shp: +chronbox.shp: +countrya.shp: +countrye.shp: +credsa.shp: +credsahr.shp: +credsu.shp: +credsuhr.shp: +cycl.shp: +dd.shp: +deviator.shp: +dog.shp: +dogbullt.shp: +dollar.shp: +dome.shp: +domemake.shp: +dragon.shp: +earth.shp: +ebtn-dn.shp: +electdog.shp: +empulse.shp: +fact.shp: +factmake.shp: +fb1.shp: +fb2.shp: +fball1.shp: +fcom.shp: +fenc.shp: +fire1.shp: +fire2.shp: +fire3.shp: +fire4.shp: +fix.shp: +fixmake.shp: +flagfly.shp: +flak.shp: +flmspt.shp: +fpls.shp: +fpower.shp: +frag1.shp: +ftnk.shp: +ftur.shp: +fturmake.shp: +gap.shp: +gapmake.shp: +gpsbox.shp: +gun.shp: +gunfire.shp: +gunmake.shp: +h2o_exp1.shp: +h2o_exp2.shp: +h2o_exp3.shp: +harv.shp: +heli.shp: +hind.shp: +hisc1-hr.shp: +hisc2-hr.shp: +hiscore1.shp: +hiscore2.shp: +hosp.shp: +hospmake.shp: +hpad.shp: +hpadmake.shp: +invulbox.shp: +invun.shp: +iron.shp: +ironmake.shp: +jeep.shp: +kenn.shp: +kennmake.shp: +litning.shp: +lrotor.shp: +lst.shp: +mcv.shp: +mgg.shp: +mgun.shp: +mhq.shp: +mig.shp: +mine.shp: +minigun.shp: +minp.shp: +minpmake.shp: +minv.shp: +minvmake.shp: +miss.shp: +missile.shp: +missile2.shp: +mlrs.shp: +mnly.shp: +mrj.shp: +napalm1.shp: +napalm2.shp: +napalm3.shp: +orca.shp: +parabomb.shp: +parabox.shp: +parach.shp: +patriot.shp: +pbox.shp: +pboxmake.shp: +pdox.shp: +pdoxmake.shp: +piff.shp: +piffpiff.shp: +powr.shp: +powrmake.shp: +pt.shp: +pumpmake.shp: +radarfrm.shp: +rapid.shp: +rrotor.shp: +sam.shp: +samfire.shp: +sammake.shp: +sbag.shp: +scrate.shp: +select.shp: +repair.shp: +shadow.shp: +silo.shp: +silomake.shp: +smig.shp: +smoke_m.shp: +smokey.shp: +smokland.shp: +sonarbox.shp: +speed.shp: +spen.shp: +spenmake.shp: +sputdoor.shp: +sputnik.shp: +ss.shp: +ssam.shp: +stealth2.shp: +stek.shp: +stekmake.shp: +stnk.shp: +syrd.shp: +syrdmake.shp: +tent.shp: +tentmake.shp: +time.shp: +timehr.shp: +tquake.shp: +tran.shp: +truk.shp: +tsla.shp: +tslamake.shp: +turr.shp: +twinkle1.shp: +twinkle2.shp: +twinkle3.shp: +u2.shp: +v19.shp: +v2.shp: +v2rl.shp: +veh-hit1.shp: +veh-hit2.shp: +wake.shp: +wcrate.shp: +weap.shp: +weap2.shp: +weapmake.shp: +wood.shp: +wwcrate.shp: +yak.shp: +#trans.icn: +#ali-tran.wsa: +#mltiplyr.wsa: +#sov-tran.wsa: \ No newline at end of file diff --git a/mods/ra/mix/hires.yaml b/mods/ra/mix/hires.yaml new file mode 100644 index 0000000000..61bf1bcb3e --- /dev/null +++ b/mods/ra/mix/hires.yaml @@ -0,0 +1,135 @@ +# hires.mix filename list for the game asset browser +1tnkicon.shp: +2tnkicon.shp: +3tnkicon.shp: +4tnkicon.shp: +afldicon.shp: +agunicon.shp: +apcicon.shp: +apwricon.shp: +artyicon.shp: +atekicon.shp: +atomicon.shp: +badricon.shp: +barricon.shp: +brikicon.shp: +btn-dn.shp: +btn-pl.shp: +btn-st.shp: +btn-up.shp: +c1.shp: +c2.shp: +caicon.shp: +camicon.shp: +chan.shp: +clock.shp: +dd-bkgnd.shp: +dd-botm.shp: +dd-crnr.shp: +dd-edge.shp: +dd-left.shp: +dd-right.shp: +dd-top.shp: +ddicon.shp: +delphi.shp: +dogicon.shp: +domeicon.shp: +domficon.shp: +e1.shp: +e1icon.shp: +e2.shp: +e2icon.shp: +e3.shp: +e3icon.shp: +e4.shp: +e4icon.shp: +e5.shp: +e6.shp: +e6icon.shp: +e7.shp: +e7icon.shp: +einstein.shp: +facficon.shp: +facticon.shp: +fencicon.shp: +fixicon.shp: +fturicon.shp: +gapicon.shp: +gnrl.shp: +gpssicon.shp: +gunicon.shp: +harvicon.shp: +hboxicon.shp: +heliicon.shp: +hindicon.shp: +hpadicon.shp: +infxicon.shp: +ironicon.shp: +jeepicon.shp: +kennicon.shp: +lsticon.shp: +map.shp: +mcvicon.shp: +medi.shp: +mediicon.shp: +mggicon.shp: +migicon.shp: +mnlyicon.shp: +mrjicon.shp: +msloicon.shp: +natoradr.shp: +nradrfrm.shp: +pbmbicon.shp: +pboxicon.shp: +pdoxicon.shp: +pinficon.shp: +pips.shp: +power.shp: +powerbar.shp: +powricon.shp: +procicon.shp: +pticon.shp: +pulse.shp: +repair.shp: +samicon.shp: +sbagicon.shp: +sell.shp: +side1na.shp: +side1us.shp: +side2na.shp: +side2us.shp: +side3na.shp: +side3us.shp: +#sidebar.shp:will crash +siloicon.shp: +smigicon.shp: +sonricon.shp: +speficon.shp: +spenicon.shp: +spy.shp: +spyicon.shp: +ssicon.shp: +stekicon.shp: +strip.shp: +stripdn.shp: +stripna.shp: +stripup.shp: +stripus.shp: +syrdicon.shp: +syrficon.shp: +tabs.shp: +tenticon.shp: +thf.shp: +thficon.shp: +tranicon.shp: +trukicon.shp: +tslaicon.shp: +u2icon.shp: +uradrfrm.shp: +ussrradr.shp: +v2rlicon.shp: +warpicon.shp: +weaficon.shp: +weapicon.shp: +yakicon.shp: +#mouse.shp:Dune II format \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 9be827a088..76cb2a1749 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -29,6 +29,10 @@ Packages: ~movies1.mix ~movies2.mix +PackageContents: + mods/ra/mix/conquer.yaml + mods/ra/mix/hires.yaml + Rules: mods/ra/rules/defaults.yaml mods/ra/rules/system.yaml @@ -73,6 +77,8 @@ ChromeLayout: mods/ra/chrome/cheats.yaml mods/ra/chrome/musicplayer.yaml mods/ra/chrome/tooltips.yaml + mods/ra/chrome/assetbrowser.yaml + mods/ra/chrome/convertassets.yaml Weapons: mods/ra/weapons.yaml