Refactoring to remove static Rules & SequenceProvider
This commit is contained in:
@@ -69,10 +69,10 @@ namespace OpenRA
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
if (!Rules.Info.ContainsKey(name.ToLowerInvariant()))
|
||||
if (!world.Map.Rules.Actors.ContainsKey(name.ToLowerInvariant()))
|
||||
throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant()));
|
||||
|
||||
Info = Rules.Info[name.ToLowerInvariant()];
|
||||
Info = world.Map.Rules.Actors[name.ToLowerInvariant()];
|
||||
foreach (var trait in Info.TraitsInConstructOrder())
|
||||
AddTrait(trait.Create(init));
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ namespace OpenRA
|
||||
}, parent, id);
|
||||
}
|
||||
|
||||
// TODO: Delayed actions shouldn't be static or at least should be cleared when the map/world is changed
|
||||
static ActionQueue delayedActions = new ActionQueue();
|
||||
public static void RunAfterTick(Action a) { delayedActions.Add(a); }
|
||||
public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); }
|
||||
@@ -151,8 +152,11 @@ namespace OpenRA
|
||||
using (new PerfSample("render_widgets"))
|
||||
{
|
||||
Ui.Draw();
|
||||
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
|
||||
if (modData != null && modData.CursorProvider != null)
|
||||
{
|
||||
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
|
||||
modData.CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame);
|
||||
}
|
||||
}
|
||||
|
||||
using (new PerfSample("render_flip"))
|
||||
@@ -248,6 +252,7 @@ namespace OpenRA
|
||||
BeforeGameStart();
|
||||
|
||||
Map map;
|
||||
|
||||
using (new PerfTimer("PrepareMap"))
|
||||
map = modData.PrepareMap(mapUID);
|
||||
using (new PerfTimer("NewWorld"))
|
||||
@@ -354,7 +359,7 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
Console.WriteLine("Available mods:");
|
||||
foreach (var mod in Mod.AllMods)
|
||||
foreach (var mod in ModInformation.AllMods)
|
||||
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
|
||||
|
||||
InitializeWithMod(Settings.Game.Mod, args.GetValue("Launch.Replay", null));
|
||||
@@ -379,7 +384,7 @@ namespace OpenRA
|
||||
orderManager.Dispose();
|
||||
|
||||
// Fall back to default if the mod doesn't exist
|
||||
if (!Mod.AllMods.ContainsKey(mod))
|
||||
if (!ModInformation.AllMods.ContainsKey(mod))
|
||||
mod = new GameSettings().Mod;
|
||||
|
||||
Console.WriteLine("Loading mod: {0}", mod);
|
||||
|
||||
@@ -17,34 +17,10 @@ using OpenRA.Support;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Rules
|
||||
{
|
||||
public static Dictionary<string, ActorInfo> Info { get { return Game.modData.Rules.Actors; } }
|
||||
public static Dictionary<string, WeaponInfo> Weapons { get { return Game.modData.Rules.Weapons; } }
|
||||
public static Dictionary<string, SoundInfo> Voices { get { return Game.modData.Rules.Voices; } }
|
||||
public static Dictionary<string, SoundInfo> Notifications { get { return Game.modData.Rules.Notifications; } }
|
||||
public static Dictionary<string, MusicInfo> Music { get { return Game.modData.Rules.Music; } }
|
||||
public static Dictionary<string, string> Movies { get { return Game.modData.Rules.Movies; } }
|
||||
public static Dictionary<string, TileSet> TileSets { get { return Game.modData.Rules.TileSets; } }
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
{
|
||||
// HACK: Fallback for code that hasn't been updated yet
|
||||
Game.modData.Rules = new ModRules(Game.modData);
|
||||
Game.modData.Rules.ActivateMap(map);
|
||||
}
|
||||
|
||||
public static IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
|
||||
}
|
||||
|
||||
|
||||
public class ModRules
|
||||
public class RulesetCache
|
||||
{
|
||||
readonly ModData modData;
|
||||
|
||||
//
|
||||
// These contain all unique instances created from each mod/map combination
|
||||
//
|
||||
readonly Dictionary<string, ActorInfo> actorCache = new Dictionary<string, ActorInfo>();
|
||||
readonly Dictionary<string, WeaponInfo> weaponCache = new Dictionary<string, WeaponInfo>();
|
||||
readonly Dictionary<string, SoundInfo> voiceCache = new Dictionary<string, SoundInfo>();
|
||||
@@ -53,40 +29,60 @@ namespace OpenRA
|
||||
readonly Dictionary<string, string> movieCache = new Dictionary<string, string>();
|
||||
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
|
||||
|
||||
//
|
||||
// These are the instances needed for the current map
|
||||
//
|
||||
public Dictionary<string, ActorInfo> Actors { get; private set; }
|
||||
public Dictionary<string, WeaponInfo> Weapons { get; private set; }
|
||||
public Dictionary<string, SoundInfo> Voices { get; private set; }
|
||||
public Dictionary<string, SoundInfo> Notifications { get; private set; }
|
||||
public Dictionary<string, MusicInfo> Music { get; private set; }
|
||||
public Dictionary<string, string> Movies { get; private set; }
|
||||
public Dictionary<string, TileSet> TileSets { get; private set; }
|
||||
public Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
|
||||
|
||||
|
||||
public ModRules(ModData modData)
|
||||
public RulesetCache(ModData modData)
|
||||
{
|
||||
this.modData = modData;
|
||||
}
|
||||
|
||||
public void ActivateMap(Map map)
|
||||
public ModRuleset LoadModRules()
|
||||
{
|
||||
var m = modData.Manifest;
|
||||
using (new PerfTimer("Actors"))
|
||||
Actors = LoadYamlRules(actorCache, m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
using (new PerfTimer("Weapons"))
|
||||
Weapons = LoadYamlRules(weaponCache, m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
using (new PerfTimer("Voices"))
|
||||
Voices = LoadYamlRules(voiceCache, m.Voices, map.Voices, (k, _) => new SoundInfo(k.Value));
|
||||
using (new PerfTimer("Notifications"))
|
||||
Notifications = LoadYamlRules(notificationCache, m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value));
|
||||
|
||||
Dictionary<string, MusicInfo> music;
|
||||
Dictionary<string, string> movies;
|
||||
Dictionary<string, TileSet> tileSets;
|
||||
|
||||
using (new PerfTimer("Music"))
|
||||
Music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
music = LoadYamlRules(musicCache, m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
|
||||
using (new PerfTimer("Movies"))
|
||||
Movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
movies = LoadYamlRules(movieCache, m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
using (new PerfTimer("TileSets"))
|
||||
TileSets = LoadTileSets(tileSetCache, m.TileSets);
|
||||
tileSets = LoadTileSets(tileSetCache, m.TileSets);
|
||||
|
||||
return new ModRuleset(music, movies, tileSets);
|
||||
}
|
||||
|
||||
public MapRuleset LoadDefaultRules()
|
||||
{
|
||||
return LoadMapRules(new Map());
|
||||
}
|
||||
|
||||
public MapRuleset LoadMapRules(Map map)
|
||||
{
|
||||
var m = modData.Manifest;
|
||||
|
||||
Dictionary<string, ActorInfo> actors;
|
||||
Dictionary<string, WeaponInfo> weapons;
|
||||
Dictionary<string, SoundInfo> voices;
|
||||
Dictionary<string, SoundInfo> notifications;
|
||||
|
||||
OnProgress();
|
||||
using (new PerfTimer("Actors"))
|
||||
actors = LoadYamlRules(actorCache, m.Rules, map.RuleDefinitions, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
OnProgress();
|
||||
using (new PerfTimer("Weapons"))
|
||||
weapons = LoadYamlRules(weaponCache, m.Weapons, map.WeaponDefinitions, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
OnProgress();
|
||||
using (new PerfTimer("Voices"))
|
||||
voices = LoadYamlRules(voiceCache, m.Voices, map.VoiceDefinitions, (k, _) => new SoundInfo(k.Value));
|
||||
OnProgress();
|
||||
using (new PerfTimer("Notifications"))
|
||||
notifications = LoadYamlRules(notificationCache, m.Notifications, map.NotificationDefinitions, (k, _) => new SoundInfo(k.Value));
|
||||
|
||||
OnProgress();
|
||||
return new MapRuleset(LoadModRules(), actors, weapons, voices, notifications);
|
||||
}
|
||||
|
||||
Dictionary<string, T> LoadYamlRules<T>(
|
||||
@@ -131,7 +127,7 @@ namespace OpenRA
|
||||
}
|
||||
else
|
||||
{
|
||||
t = new TileSet(file);
|
||||
t = new TileSet(modData, file);
|
||||
itemCache.Add(file, t);
|
||||
|
||||
items.Add(t.Id, t);
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -28,6 +28,9 @@ namespace OpenRA.Graphics
|
||||
|
||||
public string Name { get { return name; } }
|
||||
|
||||
readonly SequenceProvider sequenceProvider;
|
||||
static SequenceProvider lastSequenceProvider;
|
||||
|
||||
public Animation(string name)
|
||||
: this(name, () => 0) {}
|
||||
|
||||
@@ -36,6 +39,17 @@ namespace OpenRA.Graphics
|
||||
this.name = name.ToLowerInvariant();
|
||||
this.tickFunc = () => {};
|
||||
this.facingFunc = facingFunc;
|
||||
|
||||
// TODO: This is wrong, don't use the static
|
||||
if (Game.orderManager != null && Game.orderManager.world != null && Game.orderManager.world.Map != null)
|
||||
sequenceProvider = Game.orderManager.world.Map.SequenceProvider;
|
||||
// HACK: This just makes sure we have a sequence provider in between map changes for delayed actions
|
||||
// It sucks but it can only be removed when we don't use the statics above but replace them with
|
||||
// a possible parameter on this constructor.
|
||||
if (sequenceProvider == null)
|
||||
sequenceProvider = lastSequenceProvider;
|
||||
else
|
||||
lastSequenceProvider = sequenceProvider;
|
||||
}
|
||||
|
||||
int CurrentFrame { get { return backwards ? CurrentSequence.Start + CurrentSequence.Length - frame - 1 : frame; } }
|
||||
@@ -66,7 +80,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
{
|
||||
@@ -81,7 +95,7 @@ namespace OpenRA.Graphics
|
||||
if (!HasSequence(sequenceName))
|
||||
return false;
|
||||
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
frame %= CurrentSequence.Length;
|
||||
return true;
|
||||
}
|
||||
@@ -90,7 +104,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
{
|
||||
@@ -114,7 +128,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = true;
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
CurrentSequence = sequenceProvider.GetSequence(name, sequenceName);
|
||||
frame = func();
|
||||
tickFunc = () => frame = func();
|
||||
}
|
||||
@@ -128,7 +142,7 @@ namespace OpenRA.Graphics
|
||||
Tick(40); // tick one frame
|
||||
}
|
||||
|
||||
public bool HasSequence(string seq) { return SequenceProvider.HasSequence(name, seq); }
|
||||
public bool HasSequence(string seq) { return sequenceProvider.HasSequence(name, seq); }
|
||||
|
||||
public void Tick(int t)
|
||||
{
|
||||
@@ -159,7 +173,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public Sequence GetSequence(string sequenceName)
|
||||
{
|
||||
return SequenceProvider.GetSequence(name, sequenceName);
|
||||
return sequenceProvider.GetSequence(name, sequenceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,23 +16,18 @@ using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class CursorProvider
|
||||
public class CursorProvider
|
||||
{
|
||||
static HardwarePalette palette;
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
static Cache<string, PaletteReference> palettes;
|
||||
HardwarePalette palette;
|
||||
Dictionary<string, CursorSequence> cursors;
|
||||
Cache<string, PaletteReference> palettes;
|
||||
|
||||
static PaletteReference CreatePaletteReference(string name)
|
||||
public Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
|
||||
|
||||
public CursorProvider(ModData modData)
|
||||
{
|
||||
var pal = palette.GetPalette(name);
|
||||
if (pal == null)
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
var sequenceFiles = modData.Manifest.Cursors;
|
||||
|
||||
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
|
||||
}
|
||||
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
{
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
|
||||
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
|
||||
@@ -49,26 +44,37 @@ namespace OpenRA.Graphics
|
||||
foreach (var p in sequences.NodesDict["Palettes"].Nodes)
|
||||
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
||||
|
||||
|
||||
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
|
||||
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
|
||||
LoadSequencesForCursor(s.Key, s.Value);
|
||||
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
|
||||
|
||||
palette.Initialize();
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(string cursorSrc, MiniYaml cursor)
|
||||
PaletteReference CreatePaletteReference(string name)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
var pal = palette.GetPalette(name);
|
||||
if (pal == null)
|
||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||
|
||||
foreach (var sequence in cursor.Nodes)
|
||||
cursors.Add(sequence.Key, new CursorSequence(cursorSrc, cursor.Value, sequence.Value));
|
||||
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
|
||||
}
|
||||
|
||||
public static bool HasCursorSequence(string cursor)
|
||||
void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor)
|
||||
{
|
||||
OnProgress();
|
||||
|
||||
foreach (var sequence in cursor.Nodes)
|
||||
cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value));
|
||||
}
|
||||
|
||||
public bool HasCursorSequence(string cursor)
|
||||
{
|
||||
return cursors.ContainsKey(cursor);
|
||||
}
|
||||
|
||||
public static void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame)
|
||||
public void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame)
|
||||
{
|
||||
var cursorSequence = GetCursorSequence(cursorName);
|
||||
var cursorSprite = cursorSequence.GetSprite(cursorFrame);
|
||||
@@ -80,13 +86,12 @@ namespace OpenRA.Graphics
|
||||
cursorSprite.size);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
public CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace OpenRA.Graphics
|
||||
|
||||
Sprite[] sprites;
|
||||
|
||||
public CursorSequence(string cursorSrc, string palette, MiniYaml info)
|
||||
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
|
||||
{
|
||||
sprites = Game.modData.SpriteLoader.LoadAllSprites(cursorSrc);
|
||||
sprites = loader.LoadAllSprites(cursorSrc);
|
||||
var d = info.NodesDict;
|
||||
|
||||
start = Exts.ParseIntegerInvariant(d["start"].Value);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -19,14 +19,8 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class Minimap
|
||||
{
|
||||
public static Bitmap TerrainBitmap(Map map)
|
||||
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
|
||||
{
|
||||
return TerrainBitmap(map, false);
|
||||
}
|
||||
|
||||
public static Bitmap TerrainBitmap(Map map, bool actualSize)
|
||||
{
|
||||
var tileset = Rules.TileSets[map.Tileset];
|
||||
var width = map.Bounds.Width;
|
||||
var height = map.Bounds.Height;
|
||||
|
||||
@@ -61,10 +55,9 @@ namespace OpenRA.Graphics
|
||||
|
||||
// Add the static resources defined in the map; if the map lives
|
||||
// in a world use AddCustomTerrain instead
|
||||
public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap)
|
||||
public static Bitmap AddStaticResources(TileSet tileset, Map map, Bitmap terrainBitmap)
|
||||
{
|
||||
Bitmap terrain = new Bitmap(terrainBitmap);
|
||||
var tileset = Rules.TileSets[map.Tileset];
|
||||
|
||||
var bitmapData = terrain.LockBits(terrain.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -81,7 +74,7 @@ namespace OpenRA.Graphics
|
||||
if (map.MapResources.Value[mapX, mapY].Type == 0)
|
||||
continue;
|
||||
|
||||
var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
var res = map.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].Type)
|
||||
.Select(t => t.TerrainType).FirstOrDefault();
|
||||
if (res == null)
|
||||
@@ -185,10 +178,10 @@ namespace OpenRA.Graphics
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap RenderMapPreview(Map map, bool actualSize)
|
||||
public static Bitmap RenderMapPreview(TileSet tileset, Map map, bool actualSize)
|
||||
{
|
||||
Bitmap terrain = TerrainBitmap(map, actualSize);
|
||||
return AddStaticResources(map, terrain);
|
||||
Bitmap terrain = TerrainBitmap(tileset, map, actualSize);
|
||||
return AddStaticResources(tileset, map, terrain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.Graphics
|
||||
public readonly int ShadowZOffset;
|
||||
public readonly int[] Frames;
|
||||
|
||||
public Sequence(string unit, string name, MiniYaml info)
|
||||
public Sequence(SpriteLoader loader, string unit, string name, MiniYaml info)
|
||||
{
|
||||
var srcOverride = info.Value;
|
||||
Name = name;
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
// Apply offset to each sprite in the sequence
|
||||
// Different sequences may apply different offsets to the same frame
|
||||
sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit).Select(
|
||||
sprites = loader.LoadAllSprites(srcOverride ?? unit).Select(
|
||||
s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray();
|
||||
|
||||
if (!d.ContainsKey("Length"))
|
||||
|
||||
@@ -17,102 +17,101 @@ using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class SequenceProvider
|
||||
public class SequenceProvider
|
||||
{
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
readonly Lazy<IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>> sequences;
|
||||
|
||||
public SequenceProvider(Map map)
|
||||
{
|
||||
return Game.modData.SequenceProvider.GetSequence(unitName, sequenceName);
|
||||
this.sequences = Exts.Lazy(() => map.Rules.TileSets[map.Tileset].Data.SequenceCache.LoadSequences(map));
|
||||
}
|
||||
|
||||
public static bool HasSequence(string unitName, string sequenceName)
|
||||
public Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
return Game.modData.SequenceProvider.HasSequence(unitName, sequenceName);
|
||||
try
|
||||
{
|
||||
return sequences.Value[unitName].Value[sequenceName];
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
if (sequences.Value.ContainsKey(unitName))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
else
|
||||
throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName));
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Sequences(string unitName)
|
||||
public bool HasSequence(string unitName, string sequenceName)
|
||||
{
|
||||
return Game.modData.SequenceProvider.Sequences(unitName);
|
||||
if (!sequences.Value.ContainsKey(unitName))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName));
|
||||
|
||||
return sequences.Value[unitName].Value.ContainsKey(sequenceName);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Sequences(string unitName)
|
||||
{
|
||||
if (!sequences.Value.ContainsKey(unitName))
|
||||
throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName));
|
||||
|
||||
return sequences.Value[unitName].Value.Keys;
|
||||
}
|
||||
}
|
||||
|
||||
public class ModSequenceProvider
|
||||
public class SequenceCache
|
||||
{
|
||||
readonly ModData modData;
|
||||
readonly TileSet tileSet;
|
||||
|
||||
readonly Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
|
||||
Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequences;
|
||||
readonly Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
|
||||
|
||||
public ModSequenceProvider(ModData modData)
|
||||
public Action OnProgress = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); };
|
||||
|
||||
public SequenceCache(ModData modData, TileSet tileSet)
|
||||
{
|
||||
this.modData = modData;
|
||||
this.tileSet = tileSet;
|
||||
}
|
||||
|
||||
public void ActivateMap(Map map)
|
||||
public IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> LoadSequences(Map map)
|
||||
{
|
||||
sequences = Load(modData.Manifest.Sequences, map.Tileset, map.Sequences);
|
||||
using (new Support.PerfTimer("LoadSequences"))
|
||||
return Load(map.SequenceDefinitions);
|
||||
}
|
||||
|
||||
public Dictionary<string, Lazy<Dictionary<string, Sequence>>> Load(string[] sequenceFiles, string tileset, List<MiniYamlNode> sequenceNodes)
|
||||
IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>> Load(List<MiniYamlNode> sequenceNodes)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
OnProgress();
|
||||
|
||||
var sequenceFiles = modData.Manifest.Sequences;
|
||||
|
||||
var nodes = sequenceFiles
|
||||
.Select(s => MiniYaml.FromFile(s))
|
||||
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
|
||||
|
||||
var items = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
|
||||
var items = new Dictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>();
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
// Sequence loading uses the active SpriteLoader that depends on the current map's tileset
|
||||
var key = node.Value.ToLines(node.Key).JoinWith("|");
|
||||
|
||||
var key = tileset + node.Value.ToLines(node.Key).JoinWith("|");
|
||||
|
||||
Lazy<Dictionary<string, Sequence>> t;
|
||||
Lazy<IReadOnlyDictionary<string, Sequence>> t;
|
||||
if (sequenceCache.TryGetValue(key, out t))
|
||||
{
|
||||
items.Add(node.Key, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = Exts.Lazy(() => node.Value.NodesDict.ToDictionary(x => x.Key, x => new Sequence(node.Key, x.Key, x.Value)));
|
||||
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
|
||||
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
|
||||
new Sequence(tileSet.Data.SpriteLoader, node.Key, x.Key, x.Value))));
|
||||
sequenceCache.Add(key, t);
|
||||
items.Add(node.Key, t);
|
||||
}
|
||||
|
||||
OnProgress();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return sequences[unitName].Value[sequenceName]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
if (sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
else
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have all sequences defined.".F(unitName));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSequence(string unitName, string sequenceName)
|
||||
{
|
||||
if (!sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName));
|
||||
|
||||
return sequences[unitName].Value.ContainsKey(sequenceName);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Sequences(string unitName)
|
||||
{
|
||||
if (!sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have all sequences defined.".F(unitName));
|
||||
|
||||
return sequences[unitName].Value.Keys;
|
||||
return new ReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>(items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class SpriteLoader
|
||||
{
|
||||
readonly SheetBuilder SheetBuilder;
|
||||
public readonly SheetBuilder SheetBuilder;
|
||||
readonly Cache<string, Sprite[]> sprites;
|
||||
readonly string[] exts;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA
|
||||
// Describes what is to be loaded in order to run a mod
|
||||
public class Manifest
|
||||
{
|
||||
public readonly Mod Mod;
|
||||
public readonly ModInformation Mod;
|
||||
public readonly string[]
|
||||
Folders, MapFolders, Rules, ServerTraits,
|
||||
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA
|
||||
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
|
||||
|
||||
Mod = FieldLoader.Load<Mod>(yaml["Metadata"]);
|
||||
Mod = FieldLoader.Load<ModInformation>(yaml["Metadata"]);
|
||||
Mod.Id = mod;
|
||||
|
||||
// TODO: Use fieldloader
|
||||
|
||||
@@ -18,6 +18,7 @@ using System.Text;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
@@ -94,13 +95,13 @@ namespace OpenRA
|
||||
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
||||
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
|
||||
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequences = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Notifications = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> Translations = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> SequenceDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> WeaponDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
|
||||
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
|
||||
|
||||
// Binary map data
|
||||
[FieldLoader.Ignore] public byte TileFormat = 1;
|
||||
@@ -110,6 +111,10 @@ namespace OpenRA
|
||||
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
|
||||
[FieldLoader.Ignore] public string[,] CustomTerrain;
|
||||
|
||||
[FieldLoader.Ignore] Lazy<MapRuleset> rules;
|
||||
public MapRuleset Rules { get { return rules != null ? rules.Value : null; } }
|
||||
public SequenceProvider SequenceProvider { get; private set; }
|
||||
|
||||
public static Map FromTileset(TileSet tileset)
|
||||
{
|
||||
var tile = tileset.Templates.First();
|
||||
@@ -128,6 +133,7 @@ namespace OpenRA
|
||||
Actors = Exts.Lazy(() => new Dictionary<string, ActorReference>()),
|
||||
Smudges = Exts.Lazy(() => new List<SmudgeReference>())
|
||||
};
|
||||
map.PostInit();
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -210,13 +216,13 @@ namespace OpenRA
|
||||
return ret;
|
||||
});
|
||||
|
||||
Rules = MiniYaml.NodesOrEmpty(yaml, "Rules");
|
||||
Sequences = MiniYaml.NodesOrEmpty(yaml, "Sequences");
|
||||
VoxelSequences = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
|
||||
Weapons = MiniYaml.NodesOrEmpty(yaml, "Weapons");
|
||||
Voices = MiniYaml.NodesOrEmpty(yaml, "Voices");
|
||||
Notifications = MiniYaml.NodesOrEmpty(yaml, "Notifications");
|
||||
Translations = MiniYaml.NodesOrEmpty(yaml, "Translations");
|
||||
RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules");
|
||||
SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences");
|
||||
VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
|
||||
WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons");
|
||||
VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
|
||||
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
|
||||
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
|
||||
|
||||
CustomTerrain = new string[MapSize.X, MapSize.Y];
|
||||
|
||||
@@ -233,6 +239,19 @@ namespace OpenRA
|
||||
|
||||
if (Container.Exists("map.png"))
|
||||
CustomPreview = new Bitmap(Container.GetContent("map.png"));
|
||||
|
||||
PostInit();
|
||||
}
|
||||
|
||||
void PostInit()
|
||||
{
|
||||
rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this));
|
||||
SequenceProvider = new SequenceProvider(this);
|
||||
}
|
||||
|
||||
public MapRuleset PreloadRules()
|
||||
{
|
||||
return rules.Value;
|
||||
}
|
||||
|
||||
public CPos[] GetSpawnPoints()
|
||||
@@ -282,13 +301,13 @@ namespace OpenRA
|
||||
);
|
||||
|
||||
root.Add(new MiniYamlNode("Smudges", MiniYaml.FromList<SmudgeReference>(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));
|
||||
root.Add(new MiniYamlNode("Translations", null, Translations));
|
||||
root.Add(new MiniYamlNode("Rules", null, RuleDefinitions));
|
||||
root.Add(new MiniYamlNode("Sequences", null, SequenceDefinitions));
|
||||
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions));
|
||||
root.Add(new MiniYamlNode("Weapons", null, WeaponDefinitions));
|
||||
root.Add(new MiniYamlNode("Voices", null, VoiceDefinitions));
|
||||
root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions));
|
||||
root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions));
|
||||
|
||||
var entries = new Dictionary<string, byte[]>();
|
||||
entries.Add("map.bin", SaveBinaryData());
|
||||
@@ -452,7 +471,7 @@ namespace OpenRA
|
||||
|
||||
public void MakeDefaultPlayers()
|
||||
{
|
||||
var firstRace = OpenRA.Rules.Info["world"].Traits
|
||||
var firstRace = Rules.Actors["world"].Traits
|
||||
.WithInterface<CountryInfo>().First(c => c.Selectable).Race;
|
||||
|
||||
if (!Players.ContainsKey("Neutral"))
|
||||
@@ -489,10 +508,10 @@ namespace OpenRA
|
||||
});
|
||||
}
|
||||
|
||||
public void FixOpenAreas()
|
||||
public void FixOpenAreas(MapRuleset rules)
|
||||
{
|
||||
var r = new Random();
|
||||
var tileset = OpenRA.Rules.TileSets[Tileset];
|
||||
var tileset = rules.TileSets[Tileset];
|
||||
|
||||
for (var j = Bounds.Top; j < Bounds.Bottom; j++)
|
||||
{
|
||||
|
||||
14
OpenRA.Game/Map/MapCache.cs
Executable file → Normal file
14
OpenRA.Game/Map/MapCache.cs
Executable file → Normal file
@@ -27,30 +27,30 @@ namespace OpenRA
|
||||
{
|
||||
public static readonly MapPreview UnknownMap = new MapPreview(null, null);
|
||||
readonly Cache<string, MapPreview> previews;
|
||||
readonly Manifest manifest;
|
||||
readonly ModData modData;
|
||||
readonly SheetBuilder sheetBuilder;
|
||||
Thread previewLoaderThread;
|
||||
object syncRoot = new object();
|
||||
Queue<MapPreview> generateMinimap = new Queue<MapPreview>();
|
||||
|
||||
public MapCache(Manifest m)
|
||||
public MapCache(ModData modData)
|
||||
{
|
||||
manifest = m;
|
||||
this.modData = modData;
|
||||
previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, this));
|
||||
sheetBuilder = new SheetBuilder(SheetType.BGRA);
|
||||
}
|
||||
|
||||
public void LoadMaps()
|
||||
{
|
||||
var paths = manifest.MapFolders.SelectMany(f => FindMapsIn(f));
|
||||
var paths = modData.Manifest.MapFolders.SelectMany(f => FindMapsIn(f));
|
||||
foreach (var path in paths)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (new Support.PerfTimer(path))
|
||||
{
|
||||
var map = new Map(path, manifest.Mod.Id);
|
||||
if (manifest.MapCompatibility.Contains(map.RequiresMod))
|
||||
var map = new Map(path, modData.Manifest.Mod.Id);
|
||||
if (modData.Manifest.MapCompatibility.Contains(map.RequiresMod))
|
||||
previews[map.Uid].UpdateFromMap(map);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ namespace OpenRA
|
||||
// the next render cycle.
|
||||
// (d) Any partially written bytes from the next minimap is in an
|
||||
// unallocated area, and will be committed in the next cycle.
|
||||
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(p.Map, true);
|
||||
var bitmap = p.CustomPreview ?? Minimap.RenderMapPreview(modData.ModRules.TileSets[p.Map.Tileset], p.Map, true);
|
||||
p.Minimap = sheetBuilder.Add(bitmap);
|
||||
|
||||
lock (syncRoot)
|
||||
|
||||
65
OpenRA.Game/Map/Ruleset.cs
Normal file
65
OpenRA.Game/Map/Ruleset.cs
Normal 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class ModRuleset
|
||||
{
|
||||
public readonly IReadOnlyDictionary<string, MusicInfo> Music;
|
||||
public readonly IReadOnlyDictionary<string, string> Movies;
|
||||
public readonly IReadOnlyDictionary<string, TileSet> TileSets;
|
||||
|
||||
public ModRuleset(ModRuleset other)
|
||||
{
|
||||
this.Music = other.Music;
|
||||
this.Movies = other.Movies;
|
||||
this.TileSets = other.TileSets;
|
||||
}
|
||||
|
||||
public ModRuleset(
|
||||
IDictionary<string, MusicInfo> music,
|
||||
IDictionary<string, string> movies,
|
||||
IDictionary<string, TileSet> tileSets)
|
||||
{
|
||||
this.Music = new ReadOnlyDictionary<string, MusicInfo>(music);
|
||||
this.Movies = new ReadOnlyDictionary<string, string>(movies);
|
||||
this.TileSets = new ReadOnlyDictionary<string, TileSet>(tileSets);
|
||||
}
|
||||
|
||||
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
|
||||
}
|
||||
|
||||
public class MapRuleset : ModRuleset
|
||||
{
|
||||
public readonly IReadOnlyDictionary<string, ActorInfo> Actors;
|
||||
public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons;
|
||||
public readonly IReadOnlyDictionary<string, SoundInfo> Voices;
|
||||
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
|
||||
|
||||
public MapRuleset(
|
||||
ModRuleset modRuleset,
|
||||
IDictionary<string, ActorInfo> actors,
|
||||
IDictionary<string, WeaponInfo> weapons,
|
||||
IDictionary<string, SoundInfo> voices,
|
||||
IDictionary<string, SoundInfo> notifications)
|
||||
: base(modRuleset)
|
||||
{
|
||||
this.Actors = new ReadOnlyDictionary<string, ActorInfo>(actors);
|
||||
this.Weapons = new ReadOnlyDictionary<string, WeaponInfo>(weapons);
|
||||
this.Voices = new ReadOnlyDictionary<string, SoundInfo>(voices);
|
||||
this.Notifications = new ReadOnlyDictionary<string, SoundInfo>(notifications);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -8,21 +8,23 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class TerrainTypeInfo
|
||||
{
|
||||
public string Type;
|
||||
public string[] TargetTypes = { };
|
||||
public string[] AcceptsSmudgeType = { };
|
||||
public bool IsWater = false; // TODO: Remove this
|
||||
public Color Color;
|
||||
public string CustomCursor;
|
||||
public readonly string Type;
|
||||
public readonly string[] TargetTypes = { };
|
||||
public readonly string[] AcceptsSmudgeType = { };
|
||||
public readonly bool IsWater = false; // TODO: Remove this
|
||||
public readonly Color Color;
|
||||
public readonly string CustomCursor;
|
||||
|
||||
public TerrainTypeInfo() { }
|
||||
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
|
||||
@@ -32,19 +34,26 @@ namespace OpenRA
|
||||
|
||||
public class TileTemplate
|
||||
{
|
||||
public ushort Id;
|
||||
public string Image;
|
||||
public int[] Frames;
|
||||
public int2 Size;
|
||||
public bool PickAny;
|
||||
public string Category;
|
||||
public readonly ushort Id;
|
||||
public readonly string Image;
|
||||
public readonly int[] Frames;
|
||||
public readonly int2 Size;
|
||||
public readonly bool PickAny;
|
||||
public readonly string Category;
|
||||
|
||||
[FieldLoader.LoadUsing("LoadTiles")]
|
||||
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
|
||||
public readonly Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
|
||||
|
||||
public TileTemplate() { }
|
||||
public TileTemplate(MiniYaml my) { FieldLoader.Load(this, my); }
|
||||
|
||||
public TileTemplate(ushort id, string image, int2 size)
|
||||
{
|
||||
this.Id = id;
|
||||
this.Image = image;
|
||||
this.Size = size;
|
||||
}
|
||||
|
||||
static object LoadTiles(MiniYaml y)
|
||||
{
|
||||
return y.NodesDict["Tiles"].NodesDict.ToDictionary(
|
||||
@@ -73,24 +82,39 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public class TileSetData
|
||||
{
|
||||
Lazy<SpriteLoader> spriteLoader;
|
||||
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
|
||||
|
||||
public readonly SequenceCache SequenceCache;
|
||||
|
||||
public TileSetData(ModData modData, TileSet tileSet)
|
||||
{
|
||||
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
|
||||
SequenceCache = new SequenceCache(modData, tileSet);
|
||||
}
|
||||
}
|
||||
|
||||
public class TileSet
|
||||
{
|
||||
public string Name;
|
||||
public string Id;
|
||||
public int SheetSize = 512;
|
||||
public string Palette;
|
||||
public string PlayerPalette;
|
||||
public string[] Extensions;
|
||||
public int WaterPaletteRotationBase = 0x60;
|
||||
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
|
||||
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
|
||||
public string[] EditorTemplateOrder;
|
||||
public readonly string Name;
|
||||
public readonly string Id;
|
||||
public readonly int SheetSize = 512;
|
||||
public readonly string Palette;
|
||||
public readonly string PlayerPalette;
|
||||
public readonly string[] Extensions;
|
||||
public readonly int WaterPaletteRotationBase = 0x60;
|
||||
public readonly Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
|
||||
public readonly Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
|
||||
public readonly string[] EditorTemplateOrder;
|
||||
|
||||
static readonly string[] Fields = { "Name", "Id", "SheetSize", "Palette", "Extensions" };
|
||||
|
||||
public TileSet() { }
|
||||
[FieldLoader.IgnoreAttribute]
|
||||
public readonly TileSetData Data;
|
||||
|
||||
public TileSet(string filepath)
|
||||
public TileSet(ModData modData, string filepath)
|
||||
{
|
||||
var yaml = MiniYaml.DictFromFile(filepath);
|
||||
|
||||
@@ -104,6 +128,16 @@ namespace OpenRA
|
||||
// Templates
|
||||
Templates = yaml["Templates"].NodesDict.Values
|
||||
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
|
||||
|
||||
Data = new TileSetData(modData, this);
|
||||
}
|
||||
|
||||
public TileSet(string name, string id, string palette, string[] extensions)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Id = id;
|
||||
this.Palette = palette;
|
||||
this.Extensions = extensions;
|
||||
}
|
||||
|
||||
public void Save(string filepath)
|
||||
@@ -139,5 +173,7 @@ namespace OpenRA
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
37
OpenRA.Game/ModData.cs
Executable file → Normal file
37
OpenRA.Game/ModData.cs
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -25,11 +25,14 @@ namespace OpenRA
|
||||
public readonly WidgetLoader WidgetLoader;
|
||||
public readonly MapCache MapCache;
|
||||
public ILoadScreen LoadScreen = null;
|
||||
public SheetBuilder SheetBuilder;
|
||||
public SpriteLoader SpriteLoader;
|
||||
public VoxelLoader VoxelLoader;
|
||||
public ModSequenceProvider SequenceProvider;
|
||||
public ModRules Rules;
|
||||
public readonly RulesetCache RulesetCache;
|
||||
public CursorProvider CursorProvider { get; private set; }
|
||||
|
||||
Lazy<ModRuleset> modRules;
|
||||
public ModRuleset ModRules { get { return modRules.Value; } }
|
||||
Lazy<MapRuleset> defaultRules;
|
||||
public MapRuleset DefaultRules { get { return defaultRules.Value; } }
|
||||
|
||||
public ModData(string mod)
|
||||
{
|
||||
@@ -40,14 +43,16 @@ namespace OpenRA
|
||||
LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
|
||||
LoadScreen.Display();
|
||||
WidgetLoader = new WidgetLoader(this);
|
||||
MapCache = new MapCache(Manifest);
|
||||
SequenceProvider = new ModSequenceProvider(this);
|
||||
Rules = new ModRules(this);
|
||||
RulesetCache = new RulesetCache(this);
|
||||
MapCache = new MapCache(this);
|
||||
|
||||
// HACK: Mount only local folders so we have a half-working environment for the asset installer
|
||||
GlobalFileSystem.UnmountAll();
|
||||
foreach (var dir in Manifest.Folders)
|
||||
GlobalFileSystem.Mount(dir);
|
||||
|
||||
modRules = Exts.Lazy(() => RulesetCache.LoadModRules());
|
||||
defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());
|
||||
}
|
||||
|
||||
public void InitializeLoaders()
|
||||
@@ -56,10 +61,9 @@ namespace OpenRA
|
||||
// horribly when you use ModData in unexpected ways.
|
||||
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
|
||||
ChromeProvider.Initialize(Manifest.Chrome);
|
||||
SheetBuilder = new SheetBuilder(SheetType.Indexed);
|
||||
SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
|
||||
VoxelLoader = new VoxelLoader();
|
||||
CursorProvider.Initialize(Manifest.Cursors);
|
||||
|
||||
CursorProvider = new CursorProvider(this);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Languages { get; private set; }
|
||||
@@ -79,7 +83,7 @@ namespace OpenRA
|
||||
var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal);
|
||||
Languages = yaml.Select(t => t.Key).ToArray();
|
||||
|
||||
yaml = MiniYaml.MergeLiberal(map.Translations, yaml);
|
||||
yaml = MiniYaml.MergeLiberal(map.TranslationDefinitions, yaml);
|
||||
|
||||
foreach (var y in yaml)
|
||||
{
|
||||
@@ -122,14 +126,11 @@ namespace OpenRA
|
||||
// Mount map package so custom assets can be used. TODO: check priority.
|
||||
GlobalFileSystem.Mount(GlobalFileSystem.OpenPackage(map.Path, null, int.MaxValue));
|
||||
|
||||
using (new Support.PerfTimer("Rules.ActivateMap"))
|
||||
Rules.ActivateMap(map);
|
||||
SpriteLoader = new SpriteLoader(Rules.TileSets[map.Tileset].Extensions, SheetBuilder);
|
||||
using (new Support.PerfTimer("Map.LoadRules"))
|
||||
map.PreloadRules();
|
||||
|
||||
using (new Support.PerfTimer("SequenceProvider.ActivateMap"))
|
||||
SequenceProvider.ActivateMap(map);
|
||||
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
|
||||
|
||||
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequences);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -14,9 +14,9 @@ using System.Linq;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Mod
|
||||
public class ModInformation
|
||||
{
|
||||
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
|
||||
public static readonly Dictionary<string, ModInformation> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
|
||||
|
||||
public string Id;
|
||||
public string Title;
|
||||
@@ -24,9 +24,9 @@ namespace OpenRA
|
||||
public string Version;
|
||||
public string Author;
|
||||
|
||||
public static Dictionary<string, Mod> ValidateMods(string[] mods)
|
||||
public static Dictionary<string, ModInformation> ValidateMods(string[] mods)
|
||||
{
|
||||
var ret = new Dictionary<string, Mod>();
|
||||
var ret = new Dictionary<string, ModInformation>();
|
||||
foreach (var m in mods)
|
||||
{
|
||||
var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine);
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA
|
||||
if (!yaml.NodesDict.ContainsKey("Metadata"))
|
||||
continue;
|
||||
|
||||
var mod = FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]);
|
||||
var mod = FieldLoader.Load<ModInformation>(yaml.NodesDict["Metadata"]);
|
||||
mod.Id = m;
|
||||
|
||||
ret.Add(m, mod);
|
||||
@@ -99,7 +99,6 @@
|
||||
<Compile Include="Game.cs" />
|
||||
<Compile Include="GameRules\ActorInfo.cs" />
|
||||
<Compile Include="GameRules\MusicInfo.cs" />
|
||||
<Compile Include="GameRules\Rules.cs" />
|
||||
<Compile Include="GameRules\SoundInfo.cs" />
|
||||
<Compile Include="GameRules\WeaponInfo.cs" />
|
||||
<Compile Include="Graphics\Animation.cs" />
|
||||
@@ -244,6 +243,10 @@
|
||||
<Compile Include="Scripting\ScriptMemberExts.cs" />
|
||||
<Compile Include="Scripting\ScriptPlayerInterface.cs" />
|
||||
<Compile Include="Traits\Player\FixedColorPalette.cs" />
|
||||
<Compile Include="Primitives\ReadOnlyDictionary.cs" />
|
||||
<Compile Include="ModInformation.cs" />
|
||||
<Compile Include="Map\Ruleset.cs" />
|
||||
<Compile Include="GameRules\RulesetCache.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FileSystem\D2kSoundResources.cs" />
|
||||
@@ -303,7 +306,6 @@
|
||||
<Compile Include="Hotkey.cs" />
|
||||
<Compile Include="Keycode.cs" />
|
||||
<Compile Include="MiniYaml.cs" />
|
||||
<Compile Include="Mod.cs" />
|
||||
<Compile Include="Platform.cs" />
|
||||
<Compile Include="StreamExts.cs" />
|
||||
<Compile Include="Map\Map.cs" />
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA
|
||||
|
||||
static CountryInfo ChooseCountry(World world, string name)
|
||||
{
|
||||
var selectableCountries = Rules.Info["world"].Traits
|
||||
var selectableCountries = world.Map.Rules.Actors["world"].Traits
|
||||
.WithInterface<CountryInfo>().Where( c => c.Selectable )
|
||||
.ToArray();
|
||||
|
||||
|
||||
90
OpenRA.Game/Primitives/ReadOnlyDictionary.cs
Normal file
90
OpenRA.Game/Primitives/ReadOnlyDictionary.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
#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 System.Collections.Generic;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// A minimal read only dictionary interface for .NET 4
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .NET 4.5 has an implementation built-in, this code is not meant to
|
||||
/// duplicate it but provide a compatible interface that can be replaced
|
||||
/// when we switch to .NET 4.5 or higher.
|
||||
/// </remarks>
|
||||
public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
|
||||
{
|
||||
int Count { get; }
|
||||
TValue this[TKey key] { get; }
|
||||
IEnumerable<TKey> Keys { get; }
|
||||
IEnumerable<TValue> Values { get; }
|
||||
|
||||
bool ContainsKey(TKey key);
|
||||
bool TryGetValue(TKey key, out TValue value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A minimal read only dictionary for .NET 4 implemented as a wrapper
|
||||
/// around an IDictionary.
|
||||
/// </summary>
|
||||
public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
|
||||
{
|
||||
private readonly IDictionary<TKey, TValue> dict;
|
||||
|
||||
public ReadOnlyDictionary()
|
||||
: this(new Dictionary<TKey, TValue>())
|
||||
{
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary(IDictionary<TKey, TValue> dict)
|
||||
{
|
||||
if (dict == null)
|
||||
throw new ArgumentNullException("dict");
|
||||
|
||||
this.dict = dict;
|
||||
}
|
||||
|
||||
#region IReadOnlyDictionary implementation
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return dict.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
return dict.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public int Count { get { return dict.Count; } }
|
||||
|
||||
public TValue this[TKey key] { get { return dict[key]; } }
|
||||
|
||||
public IEnumerable<TKey> Keys { get { return dict.Keys; } }
|
||||
|
||||
public IEnumerable<TValue> Values { get { return dict.Values; } }
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return dict.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return dict.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -296,15 +296,18 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
// Returns true if played successfully
|
||||
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
|
||||
public static bool PlayPredefined(MapRuleset ruleset, Player p, Actor voicedUnit, string type, string definition, string variant, bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
|
||||
{
|
||||
if (ruleset == null)
|
||||
throw new ArgumentNullException("ruleset");
|
||||
|
||||
if (definition == null)
|
||||
return false;
|
||||
|
||||
if (Rules.Voices == null || Rules.Notifications == null)
|
||||
if (ruleset.Voices == null || ruleset.Notifications == null)
|
||||
return false;
|
||||
|
||||
var rules = (voicedUnit != null) ? Rules.Voices[type] : Rules.Notifications[type];
|
||||
var rules = (voicedUnit != null) ? ruleset.Voices[type] : ruleset.Notifications[type];
|
||||
if (rules == null)
|
||||
return false;
|
||||
|
||||
@@ -366,7 +369,7 @@ namespace OpenRA
|
||||
return false;
|
||||
|
||||
var type = mi.Voice.ToLowerInvariant();
|
||||
return PlayPredefined(null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
|
||||
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, true, WPos.Zero, 1f, true);
|
||||
}
|
||||
|
||||
public static bool PlayVoiceLocal(string phrase, Actor voicedUnit, string variant, WPos pos, float volume)
|
||||
@@ -379,15 +382,18 @@ namespace OpenRA
|
||||
return false;
|
||||
|
||||
var type = mi.Voice.ToLowerInvariant();
|
||||
return PlayPredefined(null, voicedUnit, type, phrase, variant, false, pos, volume, true);
|
||||
return PlayPredefined(voicedUnit.World.Map.Rules, null, voicedUnit, type, phrase, variant, false, pos, volume, true);
|
||||
}
|
||||
|
||||
public static bool PlayNotification(Player player, string type, string notification, string variant)
|
||||
public static bool PlayNotification(MapRuleset rules, Player player, string type, string notification, string variant)
|
||||
{
|
||||
if (rules == null)
|
||||
throw new ArgumentNullException("rules");
|
||||
|
||||
if (type == null || notification == null)
|
||||
return false;
|
||||
|
||||
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
|
||||
return PlayPredefined(rules, player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -118,7 +118,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
if (Ore > 0.8 * OreCapacity)
|
||||
{
|
||||
Sound.PlayNotification(Owner, "Speech", "SilosNeeded", Owner.Country.Race);
|
||||
Sound.PlayNotification(self.World.Map.Rules, Owner, "Speech", "SilosNeeded", Owner.Country.Race);
|
||||
AlertSilo = true;
|
||||
}
|
||||
else
|
||||
@@ -163,14 +163,14 @@ namespace OpenRA.Traits
|
||||
public void playCashTickUp(Actor self)
|
||||
{
|
||||
if (Game.Settings.Sound.CashTicks)
|
||||
Sound.PlayNotification(self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
|
||||
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
|
||||
}
|
||||
|
||||
public void playCashTickDown(Actor self)
|
||||
{
|
||||
if (Game.Settings.Sound.CashTicks && nextCashTickTime == 0)
|
||||
{
|
||||
Sound.PlayNotification(self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
|
||||
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
|
||||
nextCashTickTime = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenRA.Traits
|
||||
|
||||
public PipType PipColor = PipType.Yellow;
|
||||
|
||||
public object Create(ActorInitializer init) { return new ResourceType(this); }
|
||||
public object Create(ActorInitializer init) { return new ResourceType(this, init); }
|
||||
}
|
||||
|
||||
public class ResourceType : IWorldLoaded
|
||||
@@ -41,13 +41,13 @@ namespace OpenRA.Traits
|
||||
public PaletteReference Palette { get; private set; }
|
||||
public readonly Dictionary<string, Sprite[]> Variants;
|
||||
|
||||
public ResourceType(ResourceTypeInfo info)
|
||||
public ResourceType(ResourceTypeInfo info, ActorInitializer init)
|
||||
{
|
||||
this.Info = info;
|
||||
Variants = new Dictionary<string, Sprite[]>();
|
||||
foreach (var v in info.Variants)
|
||||
{
|
||||
var seq = SequenceProvider.GetSequence("resources", v);
|
||||
var seq = init.world.Map.SequenceProvider.GetSequence("resources", v);
|
||||
var sprites = Exts.MakeArray(seq.Length, x => seq.GetSprite(x));
|
||||
Variants.Add(v, sprites);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -11,6 +11,8 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
{
|
||||
@@ -53,8 +55,13 @@ namespace OpenRA.Widgets
|
||||
public Action OnDoubleClick = () => {};
|
||||
public Action<KeyInput> OnKeyPress = _ => {};
|
||||
|
||||
public ButtonWidget()
|
||||
readonly MapRuleset rules;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public ButtonWidget(MapRuleset rules)
|
||||
{
|
||||
this.rules = rules;
|
||||
|
||||
GetText = () => { return Text; };
|
||||
GetColor = () => TextColor;
|
||||
GetColorDisabled = () => TextColorDisabled;
|
||||
@@ -70,6 +77,8 @@ namespace OpenRA.Widgets
|
||||
protected ButtonWidget(ButtonWidget other)
|
||||
: base(other)
|
||||
{
|
||||
this.rules = other.rules;
|
||||
|
||||
Text = other.Text;
|
||||
Font = other.Font;
|
||||
TextColor = other.TextColor;
|
||||
@@ -113,10 +122,10 @@ namespace OpenRA.Widgets
|
||||
if (!IsDisabled())
|
||||
{
|
||||
OnKeyPress(e);
|
||||
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
|
||||
Sound.PlayNotification(rules, null, "Sounds", "ClickSound", null);
|
||||
}
|
||||
else
|
||||
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
|
||||
Sound.PlayNotification(rules, null, "Sounds", "ClickDisabledSound", null);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -153,12 +162,12 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
OnMouseDown(mi);
|
||||
Depressed = true;
|
||||
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
|
||||
Sound.PlayNotification(rules, null, "Sounds", "ClickSound", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
YieldMouseFocus(mi);
|
||||
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
|
||||
Sound.PlayNotification(rules, null, "Sounds", "ClickDisabledSound", null);
|
||||
}
|
||||
}
|
||||
else if (mi.Event == MouseInputEvent.Move && HasMouseFocus)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -11,6 +11,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
{
|
||||
@@ -23,7 +24,9 @@ namespace OpenRA.Widgets
|
||||
public int CheckOffset = 2;
|
||||
public bool HasPressedState = ChromeMetrics.Get<bool>("CheckboxPressedState");
|
||||
|
||||
public CheckboxWidget()
|
||||
[ObjectCreator.UseCtor]
|
||||
public CheckboxWidget(MapRuleset rules)
|
||||
: base(rules)
|
||||
{
|
||||
GetCheckType = () => CheckType;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -12,6 +12,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
{
|
||||
@@ -20,7 +21,9 @@ namespace OpenRA.Widgets
|
||||
Widget panel;
|
||||
MaskWidget fullscreenMask;
|
||||
|
||||
public DropDownButtonWidget() { }
|
||||
[ObjectCreator.UseCtor]
|
||||
public DropDownButtonWidget(MapRuleset rules)
|
||||
: base(rules) { }
|
||||
|
||||
protected DropDownButtonWidget(DropDownButtonWidget widget) : base(widget) { }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -9,6 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Widgets
|
||||
{
|
||||
@@ -17,7 +19,9 @@ namespace OpenRA.Widgets
|
||||
public string ItemKey;
|
||||
public string BaseName = "scrollitem";
|
||||
|
||||
public ScrollItemWidget()
|
||||
[ObjectCreator.UseCtor]
|
||||
public ScrollItemWidget(MapRuleset rules)
|
||||
: base(rules)
|
||||
{
|
||||
IsVisible = () => false;
|
||||
VisualHeight = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -18,10 +18,13 @@ namespace OpenRA
|
||||
{
|
||||
public class WidgetLoader
|
||||
{
|
||||
Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
|
||||
readonly Dictionary<string, MiniYamlNode> widgets = new Dictionary<string, MiniYamlNode>();
|
||||
readonly ModData modData;
|
||||
|
||||
public WidgetLoader(ModData modData)
|
||||
{
|
||||
this.modData = modData;
|
||||
|
||||
foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromFile(a)))
|
||||
foreach( var w in file )
|
||||
{
|
||||
@@ -55,6 +58,8 @@ namespace OpenRA
|
||||
if (child.Key != "Children")
|
||||
FieldLoader.LoadField(widget, child.Key, child.Value.Value);
|
||||
|
||||
if (!args.ContainsKey("rules"))
|
||||
args = new WidgetArgs(args) { { "rules", modData.DefaultRules } };
|
||||
widget.Initialize(args);
|
||||
|
||||
foreach (var child in node.Value.Nodes)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* 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,
|
||||
@@ -125,7 +125,7 @@ namespace OpenRA
|
||||
orderGenerator_ = new UnitOrderGenerator();
|
||||
Map = map;
|
||||
|
||||
TileSet = Rules.TileSets[Map.Tileset];
|
||||
TileSet = map.Rules.TileSets[Map.Tileset];
|
||||
SharedRandom = new XRandom(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||
|
||||
WorldActor = CreateActor("World", new TypeDictionary());
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace OpenRA
|
||||
var selectable = a.Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
if (selectable == null) return null;
|
||||
var v = selectable.Voice;
|
||||
return (v == null) ? null : Rules.Voices[v.ToLowerInvariant()];
|
||||
return (v == null) ? null : a.World.Map.Rules.Voices[v.ToLowerInvariant()];
|
||||
}
|
||||
|
||||
public static void PlayVoiceForOrders(this World w, Order[] orders)
|
||||
|
||||
Reference in New Issue
Block a user