diff --git a/OpenRA.FileFormats/Manifest.cs b/OpenRA.FileFormats/Manifest.cs index 4fc63cc62f..54c46ea58e 100644 --- a/OpenRA.FileFormats/Manifest.cs +++ b/OpenRA.FileFormats/Manifest.cs @@ -20,7 +20,7 @@ namespace OpenRA.FileFormats { public readonly string[] Mods, Folders, Rules, ServerTraits, - Sequences, Cursors, Chrome, Assemblies, ChromeLayout, + Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout, Weapons, Voices, Notifications, Music, Movies, TileSets, ChromeMetrics, PackageContents; @@ -42,6 +42,7 @@ namespace OpenRA.FileFormats Rules = YamlList(yaml, "Rules"); ServerTraits = YamlList(yaml, "ServerTraits"); Sequences = YamlList(yaml, "Sequences"); + VoxelSequences = YamlList(yaml, "VoxelSequences"); Cursors = YamlList(yaml, "Cursors"); Chrome = YamlList(yaml, "Chrome"); Assemblies = YamlList(yaml, "Assemblies"); diff --git a/OpenRA.Game/Graphics/VoxelLoader.cs b/OpenRA.Game/Graphics/VoxelLoader.cs index bf016e8b93..89ad57590d 100644 --- a/OpenRA.Game/Graphics/VoxelLoader.cs +++ b/OpenRA.Game/Graphics/VoxelLoader.cs @@ -35,6 +35,7 @@ namespace OpenRA.Graphics { SheetBuilder sheetBuilder; + Cache, Voxel> voxels; IVertexBuffer vertexBuffer; List vertices; int totalVertexCount; @@ -42,6 +43,7 @@ namespace OpenRA.Graphics public VoxelLoader() { + voxels = new Cache, Voxel>(LoadFile); vertices = new List(); totalVertexCount = 0; cachedVertexCount = 0; @@ -190,5 +192,17 @@ namespace OpenRA.Graphics return vertexBuffer; } } + + Voxel LoadFile(Pair files) + { + var vxl = new VxlReader(FileSystem.OpenWithExts(files.First, ".vxl")); + var hva = new HvaReader(FileSystem.OpenWithExts(files.Second, ".hva")); + return new Voxel(this, vxl, hva); + } + + public Voxel Load(string vxl, string hva) + { + return voxels[Pair.New(vxl, hva)]; + } } } diff --git a/OpenRA.Game/Graphics/VoxelProvider.cs b/OpenRA.Game/Graphics/VoxelProvider.cs new file mode 100644 index 0000000000..e9f764fb31 --- /dev/null +++ b/OpenRA.Game/Graphics/VoxelProvider.cs @@ -0,0 +1,88 @@ +#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; + +namespace OpenRA.Graphics +{ + public static class VoxelProvider + { + static Dictionary> units; + + public static void Initialize(string[] voxelFiles, List voxelNodes) + { + units = new Dictionary>(); + + var sequences = voxelFiles + .Select(s => MiniYaml.FromFile(s)) + .Aggregate(voxelNodes, MiniYaml.MergeLiberal); + + foreach (var s in sequences) + LoadVoxelsForUnit(s.Key, s.Value); + + Game.modData.VoxelLoader.RefreshBuffer(); + } + + static Voxel LoadVoxel(string unit, string name, MiniYaml info) + { + var vxl = unit; + var hva = unit; + if (info.Value != null) + { + var fields = info.Value.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries); + if (fields.Length >= 1) + vxl = hva = fields[0].Trim(); + + if (fields.Length >= 2) + hva = fields[1].Trim(); + } + + return Game.modData.VoxelLoader.Load(vxl, hva); + } + + static void LoadVoxelsForUnit(string unit, MiniYaml sequences) + { + Game.modData.LoadScreen.Display(); + try + { + var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => LoadVoxel(unit,x.Key,x.Value)); + units.Add(unit, seq); + } + catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art + } + + public static Voxel GetVoxel(string unitName, string voxelName) + { + try { return units[unitName][voxelName]; } + catch (KeyNotFoundException) + { + if (units.ContainsKey(unitName)) + throw new InvalidOperationException( + "Unit `{0}` does not have a voxel `{1}`".F(unitName, voxelName)); + else + throw new InvalidOperationException( + "Unit `{0}` does not have any voxels defined.".F(unitName)); + } + } + + public static bool HasVoxel(string unit, string seq) + { + if (!units.ContainsKey(unit)) + throw new InvalidOperationException( + "Unit `{0}` does not have any voxels defined.".F(unit)); + + return units[unit].ContainsKey(seq); + } + } +} diff --git a/OpenRA.Game/Map.cs b/OpenRA.Game/Map.cs index 45a590f93b..9b532ecedf 100644 --- a/OpenRA.Game/Map.cs +++ b/OpenRA.Game/Map.cs @@ -59,6 +59,7 @@ namespace OpenRA [FieldLoader.Ignore] public List Rules = new List(); [FieldLoader.Ignore] public List Sequences = new List(); + [FieldLoader.Ignore] public List VoxelSequences = new List(); [FieldLoader.Ignore] public List Weapons = new List(); [FieldLoader.Ignore] public List Voices = new List(); [FieldLoader.Ignore] public List Notifications = new List(); @@ -150,6 +151,7 @@ namespace OpenRA Rules = NodesOrEmpty(yaml, "Rules"); Sequences = NodesOrEmpty(yaml, "Sequences"); + VoxelSequences = NodesOrEmpty(yaml, "VoxelSequences"); Weapons = NodesOrEmpty(yaml, "Weapons"); Voices = NodesOrEmpty(yaml, "Voices"); Notifications = NodesOrEmpty(yaml, "Notifications"); @@ -206,6 +208,7 @@ namespace OpenRA root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList( Smudges.Value ))); root.Add(new MiniYamlNode("Rules", null, Rules)); root.Add(new MiniYamlNode("Sequences", null, Sequences)); + root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequences)); root.Add(new MiniYamlNode("Weapons", null, Weapons)); root.Add(new MiniYamlNode("Voices", null, Voices)); root.Add(new MiniYamlNode("Notifications", null, Notifications)); diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 453e4a0fe1..65a8fa2d43 100755 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -78,7 +78,7 @@ namespace OpenRA SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder); // TODO: Don't load the sequences for assets that are not used in this tileset. Maybe use the existing EditorTilesetFilters. SequenceProvider.Initialize(Manifest.Sequences, map.Sequences); - + VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequences); return map; } diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 7012afba9f..01c53d1d11 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -229,6 +229,7 @@ +