Update copyright header. Normalize line endings to LF.

This commit is contained in:
Paul Chote
2011-02-13 10:38:57 +13:00
parent ea5e2c0588
commit 094907c1a9
489 changed files with 43614 additions and 43613 deletions

206
INSTALL
View File

@@ -1,103 +1,103 @@
Copyright 2007-2010 The OpenRA Developers (see AUTHORS) Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
This file is part of OpenRA, which is free software. It is made 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 available to you under the terms of the GNU General Public License
as published by the Free Software Foundation. For more information, as published by the Free Software Foundation. For more information,
see LICENSE. see COPYING.
To run OpenRA, several files are needed from the original game disks. To run OpenRA, several files are needed from the original game disks.
The required files for the Red Alert mod are: The required files for the Red Alert mod are:
EITHER: EITHER:
* conquer.mix * conquer.mix
* temperat.mix * temperat.mix
* interior.mix * interior.mix
* snow.mix * snow.mix
* sounds.mix * sounds.mix
* allies.mix * allies.mix
* russian.mix * russian.mix
OR: OR:
* main.mix * main.mix
AND: AND:
* redalert.mix * redalert.mix
These need to be copied into the mods/ra/packages/ directory. These need to be copied into the mods/ra/packages/ directory.
The required files for the Command and Conquer mod are: The required files for the Command and Conquer mod are:
* cclocal.mix * cclocal.mix
* speech.mix * speech.mix
* conquer.mix * conquer.mix
* sounds.mix * sounds.mix
* tempicnh.mix * tempicnh.mix
* temperat.mix * temperat.mix
* winter.mix * winter.mix
* desert.mix * desert.mix
These need to be copied into the mods/cnc/packages/ directory. These need to be copied into the mods/cnc/packages/ directory.
If you have a case-sensitive filesystem you must change the filenames to If you have a case-sensitive filesystem you must change the filenames to
lower case. lower case.
The files can be downloaded from: The files can be downloaded from:
http://open-ra.org/get-dependency.php?file=ra-packages for the Red Alert files and http://open-ra.org/get-dependency.php?file=ra-packages for the Red Alert files and
http://open-ra.org/get-dependency.php?file=cnc-packages for the Command & Conquer files. http://open-ra.org/get-dependency.php?file=cnc-packages for the Command & Conquer files.
Alternatively: Alternatively:
Red Alert and C&C have been released by EA Games as freeware. They can be Red Alert and C&C have been released by EA Games as freeware. They can be
downloaded from http://www.commandandconquer.com/classic downloaded from http://www.commandandconquer.com/classic
Unfortunately the installer is 16-bit and so wont run on 64-bit operating Unfortunately the installer is 16-bit and so wont run on 64-bit operating
systems. This can be worked around by using the Red Alert Setup Manager systems. This can be worked around by using the Red Alert Setup Manager
(http://ra.afraid.org/html/downloads/utilities-3.html). (http://ra.afraid.org/html/downloads/utilities-3.html).
Make sure you apply the no-CD protection fix so all the files needed Make sure you apply the no-CD protection fix so all the files needed
are installed to the hard drive. are installed to the hard drive.
Dependencies - Make sure you have these installed, or you'll Dependencies - Make sure you have these installed, or you'll
have very strange errors. have very strange errors.
WINDOWS: WINDOWS:
* .NET Framework >= 3.5-SP1 * .NET Framework >= 3.5-SP1
(http://www.microsoft.com/downloads/details.aspx?FamilyID=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en) (http://www.microsoft.com/downloads/details.aspx?FamilyID=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en)
* Tao Framework >= 2.1.0 * Tao Framework >= 2.1.0
This is now bundled with OpenRA, copy the files in thirdparty/Tao to the game root directory. This is now bundled with OpenRA, copy the files in thirdparty/Tao to the game root directory.
* OpenAL >= 1.1 * OpenAL >= 1.1
(http://connect.creativelabs.com/openal/Downloads/oalinst.zip) (http://connect.creativelabs.com/openal/Downloads/oalinst.zip)
* Cg Toolkit >= 2.2 * Cg Toolkit >= 2.2
(http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe) (http://developer.download.nvidia.com/cg/Cg_2.2/Cg-2.2_October2009_Setup.exe)
To compile OpenRA, open the OpenRA.sln solution in the main folder, To compile OpenRA, open the OpenRA.sln solution in the main folder,
or build it from the command-line with MSBuild. or build it from the command-line with MSBuild.
Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert Run the game with `OpenRA.Game.exe Game.Mods=ra` for Red Alert
or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer or `OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer
UBUNTU (substitute comparable packages for other linux distros): UBUNTU (substitute comparable packages for other linux distros):
* mono-gmcs * mono-gmcs
* freetype * freetype
* libmono-corlib1.0-cil * libmono-corlib1.0-cil
* libmono-winforms2.0-cil * libmono-winforms2.0-cil
* libopenal1 * libopenal1
* libsdl1.2-dev * libsdl1.2-dev
* nvidia-cg-toolkit (download the latest version from * nvidia-cg-toolkit (download the latest version from
http://developer.nvidia.com/object/cg_download.html) http://developer.nvidia.com/object/cg_download.html)
OpenRA is incompatible with Compiz, please disable desktop effects when trying OpenRA is incompatible with Compiz, please disable desktop effects when trying
to run OpenRA or the game will crash. to run OpenRA or the game will crash.
You will need to copy the third party dependencies (.dll and .config) from the You will need to copy the third party dependencies (.dll and .config) from the
thirdparty and thirdparty/Tao directories into the game root, or install them permanently into thirdparty and thirdparty/Tao directories into the game root, or install them permanently into
your GAC with the following script your GAC with the following script
#!/bin/sh #!/bin/sh
gacutil -i thirdparty/Tao/Tao.Cg.dll gacutil -i thirdparty/Tao/Tao.Cg.dll
gacutil -i thirdparty/Tao/Tao.OpenGl.dll gacutil -i thirdparty/Tao/Tao.OpenGl.dll
gacutil -i thirdparty/Tao/Tao.OpenAl.dll gacutil -i thirdparty/Tao/Tao.OpenAl.dll
gacutil -i thirdparty/Tao/Tao.Sdl.dll gacutil -i thirdparty/Tao/Tao.Sdl.dll
gacutil -i thirdparty/Tao/Tao.FreeType.dll gacutil -i thirdparty/Tao/Tao.FreeType.dll
gacutil -i thirdparty/ICSharpCode.SharpZipLib.dll gacutil -i thirdparty/ICSharpCode.SharpZipLib.dll
To compile OpenRA, run `make' from the command line. To compile OpenRA, run `make' from the command line.
Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert
or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer

View File

@@ -1,36 +1,36 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
class ActorTemplate class ActorTemplate
{ {
public Bitmap Bitmap; public Bitmap Bitmap;
public ActorInfo Info; public ActorInfo Info;
public EditorAppearanceInfo Appearance; public EditorAppearanceInfo Appearance;
} }
class BrushTemplate class BrushTemplate
{ {
public Bitmap Bitmap; public Bitmap Bitmap;
public ushort N; public ushort N;
} }
class ResourceTemplate class ResourceTemplate
{ {
public Bitmap Bitmap; public Bitmap Bitmap;
public ResourceTypeInfo Info; public ResourceTypeInfo Info;
public int Value; public int Value;
} }
} }

View File

@@ -1,55 +1,55 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics; using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
class ActorTool : ITool class ActorTool : ITool
{ {
ActorTemplate Actor; ActorTemplate Actor;
public ActorTool(ActorTemplate actor) { this.Actor = actor; } public ActorTool(ActorTemplate actor) { this.Actor = actor; }
public void Preview(Surface surface, SGraphics g) public void Preview(Surface surface, SGraphics g)
{ {
/* todo: include the player /* todo: include the player
* in the brush so we can color new buildings too */ * in the brush so we can color new buildings too */
surface.DrawActor(g, surface.GetBrushLocation(), Actor, null); surface.DrawActor(g, surface.GetBrushLocation(), Actor, null);
} }
public void Apply(Surface surface) public void Apply(Surface surface)
{ {
if (surface.Map.Actors.Value.Any(a => a.Value.Location() == surface.GetBrushLocation())) if (surface.Map.Actors.Value.Any(a => a.Value.Location() == surface.GetBrushLocation()))
return; return;
var owner = "Neutral"; var owner = "Neutral";
var id = NextActorName(surface); var id = NextActorName(surface);
surface.Map.Actors.Value[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant()) surface.Map.Actors.Value[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant())
{ {
new LocationInit( surface.GetBrushLocation() ), new LocationInit( surface.GetBrushLocation() ),
new OwnerInit( owner) new OwnerInit( owner)
}; };
} }
string NextActorName(Surface surface) string NextActorName(Surface surface)
{ {
var id = 0; var id = 0;
for (; ; ) for (; ; )
{ {
var possible = "Actor{0}".F(id++); var possible = "Actor{0}".F(id++);
if (!surface.Map.Actors.Value.ContainsKey(possible)) return possible; if (!surface.Map.Actors.Value.ContainsKey(possible)) return possible;
} }
} }
} }
} }

View File

@@ -1,123 +1,123 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics; using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
class BrushTool : ITool class BrushTool : ITool
{ {
BrushTemplate Brush; BrushTemplate Brush;
public BrushTool(BrushTemplate brush) { this.Brush = brush; } public BrushTool(BrushTemplate brush) { this.Brush = brush; }
public void Apply(Surface surface) public void Apply(Surface surface)
{ {
// change the bits in the map // change the bits in the map
var tile = surface.TileSet.Tiles[Brush.N]; var tile = surface.TileSet.Tiles[Brush.N];
var template = surface.TileSet.Templates[Brush.N]; var template = surface.TileSet.Templates[Brush.N];
var pos = surface.GetBrushLocation(); var pos = surface.GetBrushLocation();
if (surface.GetModifiers() == Keys.Shift) if (surface.GetModifiers() == Keys.Shift)
{ {
FloodFillWithBrush(surface, pos); FloodFillWithBrush(surface, pos);
return; return;
} }
for (var u = 0; u < template.Size.X; u++) for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++) for (var v = 0; v < template.Size.Y; v++)
{ {
if (surface.Map.IsInMap(new int2(u, v) + pos)) if (surface.Map.IsInMap(new int2(u, v) + pos))
{ {
var z = u + v * template.Size.X; var z = u + v * template.Size.X;
if (tile.TileBitmapBytes[z] != null) if (tile.TileBitmapBytes[z] != null)
surface.Map.MapTiles.Value[u + pos.X, v + pos.Y] = surface.Map.MapTiles.Value[u + pos.X, v + pos.Y] =
new TileReference<ushort, byte> new TileReference<ushort, byte>
{ {
type = Brush.N, type = Brush.N,
index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z, index = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
}; };
var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize); var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize);
if (surface.Chunks.ContainsKey(ch)) if (surface.Chunks.ContainsKey(ch))
{ {
surface.Chunks[ch].Dispose(); surface.Chunks[ch].Dispose();
surface.Chunks.Remove(ch); surface.Chunks.Remove(ch);
} }
} }
} }
} }
public void Preview(Surface surface, SGraphics g) public void Preview(Surface surface, SGraphics g)
{ {
g.DrawImage(Brush.Bitmap, g.DrawImage(Brush.Bitmap,
surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X, surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X,
surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y, surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y,
Brush.Bitmap.Width * surface.Zoom, Brush.Bitmap.Width * surface.Zoom,
Brush.Bitmap.Height * surface.Zoom); Brush.Bitmap.Height * surface.Zoom);
} }
void FloodFillWithBrush(Surface s, int2 pos) void FloodFillWithBrush(Surface s, int2 pos)
{ {
var queue = new Queue<int2>(); var queue = new Queue<int2>();
var replace = s.Map.MapTiles.Value[pos.X, pos.Y]; var replace = s.Map.MapTiles.Value[pos.X, pos.Y];
var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y]; var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y];
Action<int, int> MaybeEnqueue = (x, y) => Action<int, int> MaybeEnqueue = (x, y) =>
{ {
if (s.Map.IsInMap(x, y) && !touched[x, y]) if (s.Map.IsInMap(x, y) && !touched[x, y])
{ {
queue.Enqueue(new int2(x, y)); queue.Enqueue(new int2(x, y));
touched[x, y] = true; touched[x, y] = true;
} }
}; };
queue.Enqueue(pos); queue.Enqueue(pos);
while (queue.Count > 0) while (queue.Count > 0)
{ {
var p = queue.Dequeue(); var p = queue.Dequeue();
if (!s.Map.MapTiles.Value[p.X, p.Y].Equals(replace)) if (!s.Map.MapTiles.Value[p.X, p.Y].Equals(replace))
continue; continue;
var a = FindEdge(s, p, new int2(-1, 0), replace); var a = FindEdge(s, p, new int2(-1, 0), replace);
var b = FindEdge(s, p, new int2(1, 0), replace); var b = FindEdge(s, p, new int2(1, 0), replace);
for (var x = a.X; x <= b.X; x++) for (var x = a.X; x <= b.X; x++)
{ {
s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, index = (byte)0 }; s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, index = (byte)0 };
if (s.Map.MapTiles.Value[x, p.Y - 1].Equals(replace)) if (s.Map.MapTiles.Value[x, p.Y - 1].Equals(replace))
MaybeEnqueue(x, p.Y - 1); MaybeEnqueue(x, p.Y - 1);
if (s.Map.MapTiles.Value[x, p.Y + 1].Equals(replace)) if (s.Map.MapTiles.Value[x, p.Y + 1].Equals(replace))
MaybeEnqueue(x, p.Y + 1); MaybeEnqueue(x, p.Y + 1);
} }
} }
/* todo: optimize */ /* todo: optimize */
foreach (var ch in s.Chunks.Values) ch.Dispose(); foreach (var ch in s.Chunks.Values) ch.Dispose();
s.Chunks.Clear(); s.Chunks.Clear();
} }
int2 FindEdge(Surface s, int2 p, int2 d, TileReference<ushort, byte> replace) int2 FindEdge(Surface s, int2 p, int2 d, TileReference<ushort, byte> replace)
{ {
for (; ; ) for (; ; )
{ {
var q = p + d; var q = p + d;
if (!s.Map.IsInMap(q)) return p; if (!s.Map.IsInMap(q)) return p;
if (!s.Map.MapTiles.Value[q.X, q.Y].Equals(replace)) return p; if (!s.Map.MapTiles.Value[q.X, q.Y].Equals(replace)) return p;
p = q; p = q;
} }
} }
} }
} }

View File

@@ -1,415 +1,415 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
public partial class Form1 : Form public partial class Form1 : Form
{ {
public Form1(string[] mods) public Form1(string[] mods)
{ {
InitializeComponent(); InitializeComponent();
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly; AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
currentMod = mods.FirstOrDefault() ?? "ra"; currentMod = mods.FirstOrDefault() ?? "ra";
toolStripComboBox1.Items.AddRange(Mod.AllMods.Keys.ToArray()); toolStripComboBox1.Items.AddRange(Mod.AllMods.Keys.ToArray());
toolStripComboBox1.SelectedIndexChanged += (_, e) => toolStripComboBox1.SelectedIndexChanged += (_, e) =>
{ {
tilePalette.SuspendLayout(); tilePalette.SuspendLayout();
actorPalette.SuspendLayout(); actorPalette.SuspendLayout();
resourcePalette.SuspendLayout(); resourcePalette.SuspendLayout();
tilePalette.Controls.Clear(); tilePalette.Controls.Clear();
actorPalette.Controls.Clear(); actorPalette.Controls.Clear();
resourcePalette.Controls.Clear(); resourcePalette.Controls.Clear();
tilePalette.ResumeLayout(); tilePalette.ResumeLayout();
actorPalette.ResumeLayout(); actorPalette.ResumeLayout();
resourcePalette.ResumeLayout(); resourcePalette.ResumeLayout();
surface1.Bind(null, null, null); surface1.Bind(null, null, null);
pmMiniMap.Image = null; pmMiniMap.Image = null;
currentMod = toolStripComboBox1.SelectedItem as string; currentMod = toolStripComboBox1.SelectedItem as string;
Text = "OpenRA Editor (mod:{0})".F(currentMod); Text = "OpenRA Editor (mod:{0})".F(currentMod);
Game.modData = new ModData(currentMod); Game.modData = new ModData(currentMod);
FileSystem.LoadFromManifest(Game.modData.Manifest); FileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map()); Rules.LoadRules(Game.modData.Manifest, new Map());
loadedMapName = null; loadedMapName = null;
}; };
toolStripComboBox1.SelectedItem = currentMod; toolStripComboBox1.SelectedItem = currentMod;
surface1.AfterChange += OnMapChanged; surface1.AfterChange += OnMapChanged;
surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s; surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s;
} }
void OnMapChanged() void OnMapChanged()
{ {
MakeDirty(); MakeDirty();
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true)); pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
} }
void MakeDirty() { dirty = true; } void MakeDirty() { dirty = true; }
string loadedMapName; string loadedMapName;
string currentMod = "ra"; string currentMod = "ra";
TileSet tileset; TileSet tileset;
bool dirty = false; bool dirty = false;
void LoadMap(string mapname) void LoadMap(string mapname)
{ {
tilePalette.Controls.Clear(); tilePalette.Controls.Clear();
actorPalette.Controls.Clear(); actorPalette.Controls.Clear();
resourcePalette.Controls.Clear(); resourcePalette.Controls.Clear();
loadedMapName = mapname; loadedMapName = mapname;
// load the map // load the map
var map = new Map(mapname); var map = new Map(mapname);
// upgrade maps that have no player definitions. editor doesnt care, // upgrade maps that have no player definitions. editor doesnt care,
// but this breaks the game pretty badly. // but this breaks the game pretty badly.
if (map.Players.Count == 0) if (map.Players.Count == 0)
map.Players.Add("Neutral", new PlayerReference("Neutral", map.Players.Add("Neutral", new PlayerReference("Neutral",
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true)); Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
PrepareMapResources(Game.modData.Manifest, map); PrepareMapResources(Game.modData.Manifest, map);
dirty = false; dirty = false;
} }
void NewMap(Map map) void NewMap(Map map)
{ {
tilePalette.Controls.Clear(); tilePalette.Controls.Clear();
actorPalette.Controls.Clear(); actorPalette.Controls.Clear();
resourcePalette.Controls.Clear(); resourcePalette.Controls.Clear();
loadedMapName = null; loadedMapName = null;
PrepareMapResources(Game.modData.Manifest, map); PrepareMapResources(Game.modData.Manifest, map);
MakeDirty(); MakeDirty();
} }
// this code is insanely stupid, and mostly my fault -- chrisf // this code is insanely stupid, and mostly my fault -- chrisf
void PrepareMapResources(Manifest manifest, Map map) void PrepareMapResources(Manifest manifest, Map map)
{ {
Rules.LoadRules(manifest, map); Rules.LoadRules(manifest, map);
tileset = Rules.TileSets[map.Tileset]; tileset = Rules.TileSets[map.Tileset];
tileset.LoadTiles(); tileset.LoadTiles();
var palette = new Palette(FileSystem.Open(tileset.Palette), true); var palette = new Palette(FileSystem.Open(tileset.Palette), true);
surface1.Bind(map, tileset, palette); surface1.Bind(map, tileset, palette);
// construct the palette of tiles // construct the palette of tiles
var palettes = new[] { tilePalette, actorPalette, resourcePalette }; var palettes = new[] { tilePalette, actorPalette, resourcePalette };
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); } foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
foreach (var t in tileset.Templates) foreach (var t in tileset.Templates)
{ {
try try
{ {
var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette); var bitmap = RenderUtils.RenderTemplate(tileset, (ushort)t.Key, palette);
var ibox = new PictureBox var ibox = new PictureBox
{ {
Image = bitmap, Image = bitmap,
Width = bitmap.Width / 2, Width = bitmap.Width / 2,
Height = bitmap.Height / 2, Height = bitmap.Height / 2,
SizeMode = PictureBoxSizeMode.StretchImage SizeMode = PictureBoxSizeMode.StretchImage
}; };
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key }; var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate)); ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
var template = t.Value; var template = t.Value;
tilePalette.Controls.Add(ibox); tilePalette.Controls.Add(ibox);
tt.SetToolTip(ibox, tt.SetToolTip(ibox,
"{1}:{0} ({2}x{3})".F( "{1}:{0} ({2}x{3})".F(
template.Image, template.Image,
template.Id, template.Id,
template.Size.X, template.Size.X,
template.Size.Y)); template.Size.Y));
} }
catch { } catch { }
} }
var actorTemplates = new List<ActorTemplate>(); var actorTemplates = new List<ActorTemplate>();
foreach (var a in Rules.Info.Keys) foreach (var a in Rules.Info.Keys)
{ {
try try
{ {
var info = Rules.Info[a]; var info = Rules.Info[a];
if (!info.Traits.Contains<RenderSimpleInfo>()) continue; if (!info.Traits.Contains<RenderSimpleInfo>()) continue;
var template = RenderUtils.RenderActor(info, tileset, palette); var template = RenderUtils.RenderActor(info, tileset, palette);
var ibox = new PictureBox var ibox = new PictureBox
{ {
Image = template.Bitmap, Image = template.Bitmap,
Width = 32, Width = 32,
Height = 32, Height = 32,
SizeMode = PictureBoxSizeMode.Zoom, SizeMode = PictureBoxSizeMode.Zoom,
BorderStyle = BorderStyle.FixedSingle BorderStyle = BorderStyle.FixedSingle
}; };
ibox.Click += (_, e) => surface1.SetTool(new ActorTool(template)); ibox.Click += (_, e) => surface1.SetTool(new ActorTool(template));
actorPalette.Controls.Add(ibox); actorPalette.Controls.Add(ibox);
tt.SetToolTip(ibox, tt.SetToolTip(ibox,
"{0}".F( "{0}".F(
info.Name)); info.Name));
actorTemplates.Add(template); actorTemplates.Add(template);
} }
catch { } catch { }
} }
surface1.BindActorTemplates(actorTemplates); surface1.BindActorTemplates(actorTemplates);
var resourceTemplates = new List<ResourceTemplate>(); var resourceTemplates = new List<ResourceTemplate>();
foreach (var a in Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()) foreach (var a in Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>())
{ {
try try
{ {
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette); var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette);
var ibox = new PictureBox var ibox = new PictureBox
{ {
Image = template.Bitmap, Image = template.Bitmap,
Width = 32, Width = 32,
Height = 32, Height = 32,
SizeMode = PictureBoxSizeMode.Zoom, SizeMode = PictureBoxSizeMode.Zoom,
BorderStyle = BorderStyle.FixedSingle BorderStyle = BorderStyle.FixedSingle
}; };
ibox.Click += (_, e) => surface1.SetTool(new ResourceTool(template)); ibox.Click += (_, e) => surface1.SetTool(new ResourceTool(template));
resourcePalette.Controls.Add(ibox); resourcePalette.Controls.Add(ibox);
tt.SetToolTip(ibox, tt.SetToolTip(ibox,
"{0}:{1}cr".F( "{0}:{1}cr".F(
template.Info.Name, template.Info.Name,
template.Info.ValuePerUnit)); template.Info.ValuePerUnit));
resourceTemplates.Add(template); resourceTemplates.Add(template);
} }
catch { } catch { }
} }
surface1.BindResourceTemplates(resourceTemplates); surface1.BindResourceTemplates(resourceTemplates);
foreach (var p in palettes) foreach (var p in palettes)
{ {
p.Visible = true; p.Visible = true;
p.ResumeLayout(); p.ResumeLayout();
} }
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true)); pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
propertiesToolStripMenuItem.Enabled = true; propertiesToolStripMenuItem.Enabled = true;
resizeToolStripMenuItem.Enabled = true; resizeToolStripMenuItem.Enabled = true;
spawnpointsToolStripMenuItem.Enabled = true; spawnpointsToolStripMenuItem.Enabled = true;
saveToolStripMenuItem.Enabled = true; saveToolStripMenuItem.Enabled = true;
saveAsToolStripMenuItem.Enabled = true; saveAsToolStripMenuItem.Enabled = true;
mnuMinimapToPNG.Enabled = true; // todo: what is this VB naming bullshit doing here? mnuMinimapToPNG.Enabled = true; // todo: what is this VB naming bullshit doing here?
} }
void ResizeClicked(object sender, EventArgs e) void ResizeClicked(object sender, EventArgs e)
{ {
using (var rd = new ResizeDialog()) using (var rd = new ResizeDialog())
{ {
rd.width.Value = surface1.Map.MapSize.X; rd.width.Value = surface1.Map.MapSize.X;
rd.height.Value = surface1.Map.MapSize.Y; rd.height.Value = surface1.Map.MapSize.Y;
rd.cordonLeft.Value = surface1.Map.Bounds.Left; rd.cordonLeft.Value = surface1.Map.Bounds.Left;
rd.cordonTop.Value = surface1.Map.Bounds.Top; rd.cordonTop.Value = surface1.Map.Bounds.Top;
rd.cordonRight.Value = surface1.Map.Bounds.Right; rd.cordonRight.Value = surface1.Map.Bounds.Right;
rd.cordonBottom.Value = surface1.Map.Bounds.Bottom; rd.cordonBottom.Value = surface1.Map.Bounds.Bottom;
if (DialogResult.OK != rd.ShowDialog()) if (DialogResult.OK != rd.ShowDialog())
return; return;
surface1.Map.ResizeCordon((int)rd.cordonLeft.Value, surface1.Map.ResizeCordon((int)rd.cordonLeft.Value,
(int)rd.cordonTop.Value, (int)rd.cordonTop.Value,
(int)rd.cordonRight.Value, (int)rd.cordonRight.Value,
(int)rd.cordonBottom.Value); (int)rd.cordonBottom.Value);
if ((int)rd.width.Value != surface1.Map.MapSize.X || (int)rd.height.Value != surface1.Map.MapSize.Y) if ((int)rd.width.Value != surface1.Map.MapSize.X || (int)rd.height.Value != surface1.Map.MapSize.Y)
{ {
surface1.Map.Resize((int)rd.width.Value, (int)rd.height.Value); surface1.Map.Resize((int)rd.width.Value, (int)rd.height.Value);
surface1.Bind(surface1.Map, surface1.TileSet, surface1.Palette); // rebind it to invalidate all caches surface1.Bind(surface1.Map, surface1.TileSet, surface1.Palette); // rebind it to invalidate all caches
} }
surface1.Invalidate(); surface1.Invalidate();
} }
} }
void SaveClicked(object sender, EventArgs e) void SaveClicked(object sender, EventArgs e)
{ {
if (loadedMapName == null) if (loadedMapName == null)
SaveAsClicked(sender, e); SaveAsClicked(sender, e);
else else
{ {
surface1.Map.Save(loadedMapName); surface1.Map.Save(loadedMapName);
dirty = false; dirty = false;
} }
} }
void SaveAsClicked(object sender, EventArgs e) void SaveAsClicked(object sender, EventArgs e)
{ {
using (var nms = new MapSelect(currentMod)) using (var nms = new MapSelect(currentMod))
{ {
nms.txtNew.ReadOnly = false; nms.txtNew.ReadOnly = false;
nms.btnOk.Text = "Save"; nms.btnOk.Text = "Save";
nms.txtNew.Text = "unnamed"; nms.txtNew.Text = "unnamed";
nms.txtPathOut.ReadOnly = false; nms.txtPathOut.ReadOnly = false;
if (DialogResult.OK == nms.ShowDialog()) if (DialogResult.OK == nms.ShowDialog())
{ {
if (nms.txtNew.Text == "") if (nms.txtNew.Text == "")
nms.txtNew.Text = "unnamed"; nms.txtNew.Text = "unnamed";
// TODO: Allow the user to choose map format (directory vs oramap) // TODO: Allow the user to choose map format (directory vs oramap)
loadedMapName = Path.Combine(nms.MapFolderPath, nms.txtNew.Text + ".oramap"); loadedMapName = Path.Combine(nms.MapFolderPath, nms.txtNew.Text + ".oramap");
SaveClicked(sender, e); SaveClicked(sender, e);
} }
} }
} }
void OpenClicked(object sender, EventArgs e) void OpenClicked(object sender, EventArgs e)
{ {
using (var nms = new MapSelect(currentMod)) using (var nms = new MapSelect(currentMod))
{ {
nms.txtNew.ReadOnly = true; nms.txtNew.ReadOnly = true;
nms.txtPathOut.ReadOnly = true; nms.txtPathOut.ReadOnly = true;
nms.btnOk.Text = "Open"; nms.btnOk.Text = "Open";
if (DialogResult.OK == nms.ShowDialog()) if (DialogResult.OK == nms.ShowDialog())
LoadMap(nms.txtNew.Tag as string); LoadMap(nms.txtNew.Tag as string);
} }
} }
void NewClicked(object sender, EventArgs e) void NewClicked(object sender, EventArgs e)
{ {
using (var nmd = new NewMapDialog()) using (var nmd = new NewMapDialog())
{ {
nmd.theater.Items.Clear(); nmd.theater.Items.Clear();
nmd.theater.Items.AddRange(Rules.TileSets.Select(a => a.Value.Id).ToArray()); nmd.theater.Items.AddRange(Rules.TileSets.Select(a => a.Value.Id).ToArray());
nmd.theater.SelectedIndex = 0; nmd.theater.SelectedIndex = 0;
if (DialogResult.OK == nmd.ShowDialog()) if (DialogResult.OK == nmd.ShowDialog())
{ {
var map = Map.FromTileset(nmd.theater.SelectedItem as string); var map = Map.FromTileset(nmd.theater.SelectedItem as string);
map.Resize((int)nmd.width.Value, (int)nmd.height.Value); map.Resize((int)nmd.width.Value, (int)nmd.height.Value);
map.ResizeCordon((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value, map.ResizeCordon((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value,
(int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value); (int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
map.Players.Add("Neutral", new PlayerReference("Neutral", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true)); map.Players.Add("Neutral", new PlayerReference("Neutral", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
map.Players.Add("Creeps", new PlayerReference("Creeps", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true)); map.Players.Add("Creeps", new PlayerReference("Creeps", Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
NewMap(map); NewMap(map);
} }
} }
} }
void PropertiesClicked(object sender, EventArgs e) void PropertiesClicked(object sender, EventArgs e)
{ {
using (var pd = new PropertiesDialog()) using (var pd = new PropertiesDialog())
{ {
pd.title.Text = surface1.Map.Title; pd.title.Text = surface1.Map.Title;
pd.desc.Text = surface1.Map.Description; pd.desc.Text = surface1.Map.Description;
pd.author.Text = surface1.Map.Author; pd.author.Text = surface1.Map.Author;
pd.selectable.Checked = surface1.Map.Selectable; pd.selectable.Checked = surface1.Map.Selectable;
pd.useAsShellmap.Checked = surface1.Map.UseAsShellmap; pd.useAsShellmap.Checked = surface1.Map.UseAsShellmap;
if (DialogResult.OK != pd.ShowDialog()) if (DialogResult.OK != pd.ShowDialog())
return; return;
surface1.Map.Title = pd.title.Text; surface1.Map.Title = pd.title.Text;
surface1.Map.Description = pd.desc.Text; surface1.Map.Description = pd.desc.Text;
surface1.Map.Author = pd.author.Text; surface1.Map.Author = pd.author.Text;
surface1.Map.Selectable = pd.selectable.Checked; surface1.Map.Selectable = pd.selectable.Checked;
surface1.Map.UseAsShellmap = pd.useAsShellmap.Checked; surface1.Map.UseAsShellmap = pd.useAsShellmap.Checked;
} }
} }
void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = true; } void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = true; }
void Form1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = false; } void Form1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = false; }
void CloseClicked(object sender, EventArgs e) void CloseClicked(object sender, EventArgs e)
{ {
Close(); Close();
} }
void ImportLegacyMapClicked(object sender, EventArgs e) void ImportLegacyMapClicked(object sender, EventArgs e)
{ {
var currentDirectory = Directory.GetCurrentDirectory(); var currentDirectory = Directory.GetCurrentDirectory();
using (var ofd = new OpenFileDialog { Filter = "Legacy maps (*.ini;*.mpr)|*.ini;*.mpr" }) using (var ofd = new OpenFileDialog { Filter = "Legacy maps (*.ini;*.mpr)|*.ini;*.mpr" })
if (DialogResult.OK == ofd.ShowDialog()) if (DialogResult.OK == ofd.ShowDialog())
{ {
Directory.SetCurrentDirectory(currentDirectory); Directory.SetCurrentDirectory(currentDirectory);
/* massive hack: we should be able to call NewMap() with the imported Map object, /* massive hack: we should be able to call NewMap() with the imported Map object,
* but something's not right internally in it, unless loaded via the real maploader */ * but something's not right internally in it, unless loaded via the real maploader */
var savePath = Path.Combine(Path.GetTempPath(), "OpenRA.Import"); var savePath = Path.Combine(Path.GetTempPath(), "OpenRA.Import");
Directory.CreateDirectory(savePath); Directory.CreateDirectory(savePath);
var map = LegacyMapImporter.Import(ofd.FileName); var map = LegacyMapImporter.Import(ofd.FileName);
map.Players.Add("Neutral", new PlayerReference("Neutral", map.Players.Add("Neutral", new PlayerReference("Neutral",
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true)); Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
map.Players.Add("Creeps", new PlayerReference("Creeps", map.Players.Add("Creeps", new PlayerReference("Creeps",
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true)); Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
map.Save(savePath); map.Save(savePath);
LoadMap(savePath); LoadMap(savePath);
loadedMapName = null; /* editor needs to think this hasnt been saved */ loadedMapName = null; /* editor needs to think this hasnt been saved */
Directory.Delete(savePath, true); Directory.Delete(savePath, true);
MakeDirty(); MakeDirty();
} }
} }
void OnFormClosing(object sender, FormClosingEventArgs e) void OnFormClosing(object sender, FormClosingEventArgs e)
{ {
if (!dirty) return; if (!dirty) return;
switch (MessageBox.Show("The map has been modified since it was last saved. " + "\r\n" + "Save changes now?", switch (MessageBox.Show("The map has been modified since it was last saved. " + "\r\n" + "Save changes now?",
"Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation)) "Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation))
{ {
case DialogResult.Yes: SaveClicked(null, EventArgs.Empty); break; case DialogResult.Yes: SaveClicked(null, EventArgs.Empty); break;
case DialogResult.No: break; case DialogResult.No: break;
case DialogResult.Cancel: e.Cancel = true; break; case DialogResult.Cancel: e.Cancel = true; break;
} }
} }
private void layersFloaterToolStripMenuItem_Click(object sender, EventArgs e) private void layersFloaterToolStripMenuItem_Click(object sender, EventArgs e)
{ {
var pb = new PaletteBox(); var pb = new PaletteBox();
pb.Show(); pb.Show();
} }
void ExportMinimap(object sender, EventArgs e) void ExportMinimap(object sender, EventArgs e)
{ {
saveFileDialog.InitialDirectory = Path.Combine(Environment.CurrentDirectory, "maps"); saveFileDialog.InitialDirectory = Path.Combine(Environment.CurrentDirectory, "maps");
saveFileDialog.FileName = Path.ChangeExtension(loadedMapName, ".png"); saveFileDialog.FileName = Path.ChangeExtension(loadedMapName, ".png");
if (DialogResult.OK == saveFileDialog.ShowDialog()) if (DialogResult.OK == saveFileDialog.ShowDialog())
pmMiniMap.Image.Save(saveFileDialog.FileName); pmMiniMap.Image.Save(saveFileDialog.FileName);
} }
} }
} }

View File

@@ -1,20 +1,20 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using SGraphics = System.Drawing.Graphics; using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
interface ITool interface ITool
{ {
void Apply(Surface surface); void Apply(Surface surface);
void Preview(Surface surface, SGraphics g); void Preview(Surface surface, SGraphics g);
} }
} }

View File

@@ -1,472 +1,472 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
public class LegacyMapImporter public class LegacyMapImporter
{ {
// Mapping from ra overlay index to type string // Mapping from ra overlay index to type string
static string[] raOverlayNames = static string[] raOverlayNames =
{ {
"sbag", "cycl", "brik", "fenc", "wood", "sbag", "cycl", "brik", "fenc", "wood",
"gold01", "gold02", "gold03", "gold04", "gold01", "gold02", "gold03", "gold04",
"gem01", "gem02", "gem03", "gem04", "gem01", "gem02", "gem03", "gem04",
"v12", "v13", "v14", "v15", "v16", "v17", "v18", "v12", "v13", "v14", "v15", "v16", "v17", "v18",
"fpls", "wcrate", "scrate", "barb", "sbag", "fpls", "wcrate", "scrate", "barb", "sbag",
}; };
static Dictionary<string, Pair<byte, byte>> overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>() static Dictionary<string, Pair<byte, byte>> overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>()
{ {
// RA Gems, Gold // RA Gems, Gold
{ "gold01", new Pair<byte,byte>(1,0) }, { "gold01", new Pair<byte,byte>(1,0) },
{ "gold02", new Pair<byte,byte>(1,1) }, { "gold02", new Pair<byte,byte>(1,1) },
{ "gold03", new Pair<byte,byte>(1,2) }, { "gold03", new Pair<byte,byte>(1,2) },
{ "gold04", new Pair<byte,byte>(1,3) }, { "gold04", new Pair<byte,byte>(1,3) },
{ "gem01", new Pair<byte,byte>(2,0) }, { "gem01", new Pair<byte,byte>(2,0) },
{ "gem02", new Pair<byte,byte>(2,1) }, { "gem02", new Pair<byte,byte>(2,1) },
{ "gem03", new Pair<byte,byte>(2,2) }, { "gem03", new Pair<byte,byte>(2,2) },
{ "gem04", new Pair<byte,byte>(2,3) }, { "gem04", new Pair<byte,byte>(2,3) },
// cnc tiberium // cnc tiberium
{ "ti1", new Pair<byte,byte>(1,0) }, { "ti1", new Pair<byte,byte>(1,0) },
{ "ti2", new Pair<byte,byte>(1,1) }, { "ti2", new Pair<byte,byte>(1,1) },
{ "ti3", new Pair<byte,byte>(1,2) }, { "ti3", new Pair<byte,byte>(1,2) },
{ "ti4", new Pair<byte,byte>(1,3) }, { "ti4", new Pair<byte,byte>(1,3) },
{ "ti5", new Pair<byte,byte>(1,4) }, { "ti5", new Pair<byte,byte>(1,4) },
{ "ti6", new Pair<byte,byte>(1,5) }, { "ti6", new Pair<byte,byte>(1,5) },
{ "ti7", new Pair<byte,byte>(1,6) }, { "ti7", new Pair<byte,byte>(1,6) },
{ "ti8", new Pair<byte,byte>(1,7) }, { "ti8", new Pair<byte,byte>(1,7) },
{ "ti9", new Pair<byte,byte>(1,8) }, { "ti9", new Pair<byte,byte>(1,8) },
{ "ti10", new Pair<byte,byte>(1,9) }, { "ti10", new Pair<byte,byte>(1,9) },
{ "ti11", new Pair<byte,byte>(1,10) }, { "ti11", new Pair<byte,byte>(1,10) },
{ "ti12", new Pair<byte,byte>(1,11) }, { "ti12", new Pair<byte,byte>(1,11) },
}; };
static Dictionary<string, string> overlayActorMapping = new Dictionary<string, string>() { static Dictionary<string, string> overlayActorMapping = new Dictionary<string, string>() {
// Fences // Fences
{"sbag","sbag"}, {"sbag","sbag"},
{"cycl","cycl"}, {"cycl","cycl"},
{"brik","brik"}, {"brik","brik"},
{"fenc","fenc"}, {"fenc","fenc"},
{"wood","wood"}, {"wood","wood"},
// Fields // Fields
{"v12","v12"}, {"v12","v12"},
{"v13","v13"}, {"v13","v13"},
{"v14","v14"}, {"v14","v14"},
{"v15","v15"}, {"v15","v15"},
{"v16","v16"}, {"v16","v16"},
{"v17","v17"}, {"v17","v17"},
{"v18","v18"}, {"v18","v18"},
// Crates // Crates
// {"wcrate","crate"}, // {"wcrate","crate"},
// {"scrate","crate"}, // {"scrate","crate"},
}; };
// todo: fix this -- will have bitrotted pretty badly. // todo: fix this -- will have bitrotted pretty badly.
static Dictionary<string,Pair<Color,Color>> namedColorMapping = new Dictionary<string, Pair<Color, Color>>() static Dictionary<string,Pair<Color,Color>> namedColorMapping = new Dictionary<string, Pair<Color, Color>>()
{ {
{"gold",Pair.New(Color.FromArgb(246,214,121),Color.FromArgb(40,32,8))}, {"gold",Pair.New(Color.FromArgb(246,214,121),Color.FromArgb(40,32,8))},
{"blue",Pair.New(Color.FromArgb(226,230,246),Color.FromArgb(8,20,52))}, {"blue",Pair.New(Color.FromArgb(226,230,246),Color.FromArgb(8,20,52))},
{"red",Pair.New(Color.FromArgb(255,20,0),Color.FromArgb(56,0,0))}, {"red",Pair.New(Color.FromArgb(255,20,0),Color.FromArgb(56,0,0))},
{"neutral",Pair.New(Color.FromArgb(238,238,238),Color.FromArgb(44,28,24))}, {"neutral",Pair.New(Color.FromArgb(238,238,238),Color.FromArgb(44,28,24))},
{"orange",Pair.New(Color.FromArgb(255,230,149),Color.FromArgb(56,0,0))}, {"orange",Pair.New(Color.FromArgb(255,230,149),Color.FromArgb(56,0,0))},
{"teal",Pair.New(Color.FromArgb(93,194,165),Color.FromArgb(0,32,32))}, {"teal",Pair.New(Color.FromArgb(93,194,165),Color.FromArgb(0,32,32))},
{"salmon",Pair.New(Color.FromArgb(210,153,125),Color.FromArgb(56,0,0))}, {"salmon",Pair.New(Color.FromArgb(210,153,125),Color.FromArgb(56,0,0))},
{"green",Pair.New(Color.FromArgb(160,240,140),Color.FromArgb(20,20,20))}, {"green",Pair.New(Color.FromArgb(160,240,140),Color.FromArgb(20,20,20))},
{"white",Pair.New(Color.FromArgb(255,255,255),Color.FromArgb(75,75,75))}, {"white",Pair.New(Color.FromArgb(255,255,255),Color.FromArgb(75,75,75))},
{"black",Pair.New(Color.FromArgb(80,80,80),Color.FromArgb(5,5,5))}, {"black",Pair.New(Color.FromArgb(80,80,80),Color.FromArgb(5,5,5))},
}; };
int MapSize; int MapSize;
int ActorCount = 0; int ActorCount = 0;
Map Map = new Map(); Map Map = new Map();
List<string> Players = new List<string>(); List<string> Players = new List<string>();
LegacyMapImporter(string filename) LegacyMapImporter(string filename)
{ {
ConvertIniMap(filename); ConvertIniMap(filename);
} }
public static Map Import(string filename) public static Map Import(string filename)
{ {
var converter = new LegacyMapImporter(filename); var converter = new LegacyMapImporter(filename);
return converter.Map; return converter.Map;
} }
enum IniMapFormat { RedAlert = 3, /* otherwise, cnc (2 variants exist, we don't care to differentiate) */ }; enum IniMapFormat { RedAlert = 3, /* otherwise, cnc (2 variants exist, we don't care to differentiate) */ };
public void ConvertIniMap(string iniFile) public void ConvertIniMap(string iniFile)
{ {
var file = new IniFile(FileSystem.Open(iniFile)); var file = new IniFile(FileSystem.Open(iniFile));
var basic = file.GetSection("Basic"); var basic = file.GetSection("Basic");
var map = file.GetSection("Map"); var map = file.GetSection("Map");
var legacyMapFormat = (IniMapFormat)int.Parse(basic.GetValue("NewINIFormat", "0")); var legacyMapFormat = (IniMapFormat)int.Parse(basic.GetValue("NewINIFormat", "0"));
var XOffset = int.Parse(map.GetValue("X", "0")); var XOffset = int.Parse(map.GetValue("X", "0"));
var YOffset = int.Parse(map.GetValue("Y", "0")); var YOffset = int.Parse(map.GetValue("Y", "0"));
var Width = int.Parse(map.GetValue("Width", "0")); var Width = int.Parse(map.GetValue("Width", "0"));
var Height = int.Parse(map.GetValue("Height", "0")); var Height = int.Parse(map.GetValue("Height", "0"));
MapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64; MapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64;
Map.Title = basic.GetValue("Name", "(null)"); Map.Title = basic.GetValue("Name", "(null)");
Map.Author = "Westwood Studios"; Map.Author = "Westwood Studios";
Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8); Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8);
Map.MapSize.X = MapSize; Map.MapSize.X = MapSize;
Map.MapSize.Y = MapSize; Map.MapSize.Y = MapSize;
Map.Bounds = Rectangle.FromLTRB(XOffset, YOffset, XOffset + Width, YOffset + Height); Map.Bounds = Rectangle.FromLTRB(XOffset, YOffset, XOffset + Width, YOffset + Height);
Map.Selectable = true; Map.Selectable = true;
Map.Smudges = Lazy.New(() => new List<SmudgeReference>()); Map.Smudges = Lazy.New(() => new List<SmudgeReference>());
Map.Actors = Lazy.New(() => new Dictionary<string, ActorReference>()); Map.Actors = Lazy.New(() => new Dictionary<string, ActorReference>());
Map.MapResources = Lazy.New(() => new TileReference<byte, byte>[MapSize, MapSize]); Map.MapResources = Lazy.New(() => new TileReference<byte, byte>[MapSize, MapSize]);
Map.MapTiles = Lazy.New(() => new TileReference<ushort, byte>[MapSize, MapSize]); Map.MapTiles = Lazy.New(() => new TileReference<ushort, byte>[MapSize, MapSize]);
if (legacyMapFormat == IniMapFormat.RedAlert) if (legacyMapFormat == IniMapFormat.RedAlert)
{ {
UnpackRATileData(ReadPackedSection(file.GetSection("MapPack"))); UnpackRATileData(ReadPackedSection(file.GetSection("MapPack")));
UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
ReadRATrees(file); ReadRATrees(file);
} }
else // CNC else // CNC
{ {
UnpackCncTileData(FileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")); UnpackCncTileData(FileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin"));
ReadCncOverlay(file); ReadCncOverlay(file);
ReadCncTrees(file); ReadCncTrees(file);
} }
LoadActors(file, "STRUCTURES"); LoadActors(file, "STRUCTURES");
LoadActors(file, "UNITS"); LoadActors(file, "UNITS");
LoadActors(file, "INFANTRY"); LoadActors(file, "INFANTRY");
LoadSmudges(file, "SMUDGE"); LoadSmudges(file, "SMUDGE");
foreach (var p in Players) foreach (var p in Players)
LoadPlayer(file, p, (legacyMapFormat == IniMapFormat.RedAlert)); LoadPlayer(file, p, (legacyMapFormat == IniMapFormat.RedAlert));
var wps = file.GetSection("Waypoints") var wps = file.GetSection("Waypoints")
.Where(kv => int.Parse(kv.Value) > 0) .Where(kv => int.Parse(kv.Value) > 0)
.Select(kv => Pair.New(int.Parse(kv.Key), .Select(kv => Pair.New(int.Parse(kv.Key),
LocationFromMapOffset(int.Parse(kv.Value), MapSize))) LocationFromMapOffset(int.Parse(kv.Value), MapSize)))
.ToArray(); .ToArray();
// Add waypoint actors // Add waypoint actors
foreach( var kv in wps ) foreach( var kv in wps )
{ {
var a = new ActorReference("mpspawn"); var a = new ActorReference("mpspawn");
a.Add(new LocationInit(kv.Second)); a.Add(new LocationInit(kv.Second));
Map.Actors.Value.Add("spawn" + kv.First, a); Map.Actors.Value.Add("spawn" + kv.First, a);
} }
} }
static int2 LocationFromMapOffset(int offset, int mapSize) static int2 LocationFromMapOffset(int offset, int mapSize)
{ {
return new int2(offset % mapSize, offset / mapSize); return new int2(offset % mapSize, offset / mapSize);
} }
static MemoryStream ReadPackedSection(IniSection mapPackSection) static MemoryStream ReadPackedSection(IniSection mapPackSection)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 1; ; i++) for (int i = 1; ; i++)
{ {
string line = mapPackSection.GetValue(i.ToString(), null); string line = mapPackSection.GetValue(i.ToString(), null);
if (line == null) if (line == null)
break; break;
sb.Append(line.Trim()); sb.Append(line.Trim());
} }
byte[] data = Convert.FromBase64String(sb.ToString()); byte[] data = Convert.FromBase64String(sb.ToString());
List<byte[]> chunks = new List<byte[]>(); List<byte[]> chunks = new List<byte[]>();
BinaryReader reader = new BinaryReader(new MemoryStream(data)); BinaryReader reader = new BinaryReader(new MemoryStream(data));
try try
{ {
while (true) while (true)
{ {
uint length = reader.ReadUInt32() & 0xdfffffff; uint length = reader.ReadUInt32() & 0xdfffffff;
byte[] dest = new byte[8192]; byte[] dest = new byte[8192];
byte[] src = reader.ReadBytes((int)length); byte[] src = reader.ReadBytes((int)length);
/*int actualLength =*/ /*int actualLength =*/
Format80.DecodeInto(src, dest); Format80.DecodeInto(src, dest);
chunks.Add(dest); chunks.Add(dest);
} }
} }
catch (EndOfStreamException) { } catch (EndOfStreamException) { }
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
foreach (byte[] chunk in chunks) foreach (byte[] chunk in chunks)
ms.Write(chunk, 0, chunk.Length); ms.Write(chunk, 0, chunk.Length);
ms.Position = 0; ms.Position = 0;
return ms; return ms;
} }
static byte ReadByte(Stream s) static byte ReadByte(Stream s)
{ {
int ret = s.ReadByte(); int ret = s.ReadByte();
if (ret == -1) if (ret == -1)
throw new NotImplementedException(); throw new NotImplementedException();
return (byte)ret; return (byte)ret;
} }
static ushort ReadWord(Stream s) static ushort ReadWord(Stream s)
{ {
ushort ret = ReadByte(s); ushort ret = ReadByte(s);
ret |= (ushort)(ReadByte(s) << 8); ret |= (ushort)(ReadByte(s) << 8);
return ret; return ret;
} }
void UnpackRATileData(MemoryStream ms) void UnpackRATileData(MemoryStream ms)
{ {
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
Map.MapTiles.Value[i, j] = new TileReference<ushort, byte>(); Map.MapTiles.Value[i, j] = new TileReference<ushort, byte>();
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
Map.MapTiles.Value[i, j].type = ReadWord(ms); Map.MapTiles.Value[i, j].type = ReadWord(ms);
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
Map.MapTiles.Value[i, j].index = ReadByte(ms); Map.MapTiles.Value[i, j].index = ReadByte(ms);
} }
void UnpackRAOverlayData(MemoryStream ms) void UnpackRAOverlayData(MemoryStream ms)
{ {
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
{ {
byte o = ReadByte(ms); byte o = ReadByte(ms);
var res = Pair.New((byte)0, (byte)0); var res = Pair.New((byte)0, (byte)0);
if (o != 255 && overlayResourceMapping.ContainsKey(raOverlayNames[o])) if (o != 255 && overlayResourceMapping.ContainsKey(raOverlayNames[o]))
res = overlayResourceMapping[raOverlayNames[o]]; res = overlayResourceMapping[raOverlayNames[o]];
Map.MapResources.Value[i, j] = new TileReference<byte, byte>(res.First, res.Second); Map.MapResources.Value[i, j] = new TileReference<byte, byte>(res.First, res.Second);
if (o != 255 && overlayActorMapping.ContainsKey(raOverlayNames[o])) if (o != 255 && overlayActorMapping.ContainsKey(raOverlayNames[o]))
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(overlayActorMapping[raOverlayNames[o]]) new ActorReference(overlayActorMapping[raOverlayNames[o]])
{ {
new LocationInit( new int2(i, j) ), new LocationInit( new int2(i, j) ),
new OwnerInit( "Neutral" ) new OwnerInit( "Neutral" )
}); });
} }
} }
void ReadRATrees(IniFile file) void ReadRATrees(IniFile file)
{ {
IniSection terrain = file.GetSection("TERRAIN", true); IniSection terrain = file.GetSection("TERRAIN", true);
if (terrain == null) if (terrain == null)
return; return;
foreach (KeyValuePair<string, string> kv in terrain) foreach (KeyValuePair<string, string> kv in terrain)
{ {
var loc = int.Parse(kv.Key); var loc = int.Parse(kv.Key);
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.ToLowerInvariant()) new ActorReference(kv.Value.ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}); });
} }
} }
void UnpackCncTileData(Stream ms) void UnpackCncTileData(Stream ms)
{ {
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
Map.MapTiles.Value[i, j] = new TileReference<ushort, byte>(); Map.MapTiles.Value[i, j] = new TileReference<ushort, byte>();
for (int j = 0; j < MapSize; j++) for (int j = 0; j < MapSize; j++)
for (int i = 0; i < MapSize; i++) for (int i = 0; i < MapSize; i++)
{ {
Map.MapTiles.Value[i, j].type = ReadByte(ms); Map.MapTiles.Value[i, j].type = ReadByte(ms);
Map.MapTiles.Value[i, j].index = ReadByte(ms); Map.MapTiles.Value[i, j].index = ReadByte(ms);
} }
} }
void ReadCncOverlay(IniFile file) void ReadCncOverlay(IniFile file)
{ {
IniSection overlay = file.GetSection("OVERLAY", true); IniSection overlay = file.GetSection("OVERLAY", true);
if (overlay == null) if (overlay == null)
return; return;
foreach (KeyValuePair<string, string> kv in overlay) foreach (KeyValuePair<string, string> kv in overlay)
{ {
var loc = int.Parse(kv.Key); var loc = int.Parse(kv.Key);
int2 cell = new int2(loc % MapSize, loc / MapSize); int2 cell = new int2(loc % MapSize, loc / MapSize);
var res = Pair.New((byte)0, (byte)0); var res = Pair.New((byte)0, (byte)0);
if (overlayResourceMapping.ContainsKey(kv.Value.ToLower())) if (overlayResourceMapping.ContainsKey(kv.Value.ToLower()))
res = overlayResourceMapping[kv.Value.ToLower()]; res = overlayResourceMapping[kv.Value.ToLower()];
Map.MapResources.Value[cell.X, cell.Y] = new TileReference<byte, byte>(res.First, res.Second); Map.MapResources.Value[cell.X, cell.Y] = new TileReference<byte, byte>(res.First, res.Second);
if (overlayActorMapping.ContainsKey(kv.Value.ToLower())) if (overlayActorMapping.ContainsKey(kv.Value.ToLower()))
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(overlayActorMapping[kv.Value.ToLower()]) new ActorReference(overlayActorMapping[kv.Value.ToLower()])
{ {
new LocationInit(cell), new LocationInit(cell),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}); });
} }
} }
void ReadCncTrees(IniFile file) void ReadCncTrees(IniFile file)
{ {
IniSection terrain = file.GetSection("TERRAIN", true); IniSection terrain = file.GetSection("TERRAIN", true);
if (terrain == null) if (terrain == null)
return; return;
foreach (KeyValuePair<string, string> kv in terrain) foreach (KeyValuePair<string, string> kv in terrain)
{ {
var loc = int.Parse(kv.Key); var loc = int.Parse(kv.Key);
Map.Actors.Value.Add("Actor" + ActorCount++, Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant()) new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}); });
} }
} }
void LoadActors(IniFile file, string section) void LoadActors(IniFile file, string section)
{ {
foreach (var s in file.GetSection(section, true)) foreach (var s in file.GetSection(section, true))
{ {
//Structures: num=owner,type,health,location,turret-facing,trigger //Structures: num=owner,type,health,location,turret-facing,trigger
//Units: num=owner,type,health,location,facing,action,trigger //Units: num=owner,type,health,location,facing,action,trigger
//Infantry: num=owner,type,health,location,subcell,action,facing,trigger //Infantry: num=owner,type,health,location,subcell,action,facing,trigger
var parts = s.Value.Split(','); var parts = s.Value.Split(',');
var loc = int.Parse(parts[3]); var loc = int.Parse(parts[3]);
if (parts[0] == "") if (parts[0] == "")
parts[0] = "Neutral"; parts[0] = "Neutral";
if (!Players.Contains(parts[0])) if (!Players.Contains(parts[0]))
Players.Add(parts[0]); Players.Add(parts[0]);
var stance = ActorStance.Stance.None; var stance = ActorStance.Stance.None;
switch(parts[5]) switch(parts[5])
{ {
case "Area Guard": case "Area Guard":
case "Guard": case "Guard":
stance = ActorStance.Stance.Guard; stance = ActorStance.Stance.Guard;
break; break;
case "Defend Base": case "Defend Base":
stance = ActorStance.Stance.Defend; stance = ActorStance.Stance.Defend;
break; break;
case "Hunt": case "Hunt":
case "Rampage": case "Rampage":
case "Attack Base": case "Attack Base":
case "Attack Units": case "Attack Units":
case "Attack Civil.": case "Attack Civil.":
case "Attack Tarcom": case "Attack Tarcom":
stance = ActorStance.Stance.Hunt; stance = ActorStance.Stance.Hunt;
break; break;
case "Retreat": case "Retreat":
case "Return": case "Return":
stance = ActorStance.Stance.Retreat; stance = ActorStance.Stance.Retreat;
break; break;
// do we care about `Harvest' and `Sticky'? // do we care about `Harvest' and `Sticky'?
} }
var actor = new ActorReference(parts[1].ToLowerInvariant()) var actor = new ActorReference(parts[1].ToLowerInvariant())
{ {
new LocationInit(new int2(loc % MapSize, loc / MapSize)), new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new OwnerInit(parts[0]), new OwnerInit(parts[0]),
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256), new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])), new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
new ActorStanceInit(stance), new ActorStanceInit(stance),
}; };
if (section == "INFANTRY") if (section == "INFANTRY")
actor.Add(new SubCellInit(int.Parse(parts[4]))); actor.Add(new SubCellInit(int.Parse(parts[4])));
Map.Actors.Value.Add("Actor" + ActorCount++,actor); Map.Actors.Value.Add("Actor" + ActorCount++,actor);
} }
} }
void LoadSmudges(IniFile file, string section) void LoadSmudges(IniFile file, string section)
{ {
foreach (var s in file.GetSection(section, true)) foreach (var s in file.GetSection(section, true))
{ {
//loc=type,loc,depth //loc=type,loc,depth
var parts = s.Value.Split(','); var parts = s.Value.Split(',');
var loc = int.Parse(parts[1]); var loc = int.Parse(parts[1]);
Map.Smudges.Value.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), int.Parse(parts[2]))); Map.Smudges.Value.Add(new SmudgeReference(parts[0].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), int.Parse(parts[2])));
} }
} }
void LoadPlayer(IniFile file, string section, bool isRA) void LoadPlayer(IniFile file, string section, bool isRA)
{ {
var c = (section == "BadGuy") ? "red" : var c = (section == "BadGuy") ? "red" :
(isRA) ? "blue" : "gold"; (isRA) ? "blue" : "gold";
var color = namedColorMapping[c]; var color = namedColorMapping[c];
var pr = new PlayerReference var pr = new PlayerReference
{ {
Name = section, Name = section,
OwnsWorld = (section == "Neutral"), OwnsWorld = (section == "Neutral"),
NonCombatant = (section == "Neutral"), NonCombatant = (section == "Neutral"),
Race = (isRA) ? ((section == "BadGuy") ? "soviet" : "allies") : ((section == "BadGuy") ? "nod" : "gdi"), Race = (isRA) ? ((section == "BadGuy") ? "soviet" : "allies") : ((section == "BadGuy") ? "nod" : "gdi"),
ColorRamp = new ColorRamp( ColorRamp = new ColorRamp(
(byte)((color.First.GetHue() / 360.0f) * 255), (byte)((color.First.GetHue() / 360.0f) * 255),
(byte)(color.First.GetSaturation() * 255), (byte)(color.First.GetSaturation() * 255),
(byte)(color.First.GetBrightness() * 255), (byte)(color.First.GetBrightness() * 255),
(byte)(color.Second.GetBrightness() * 255)) (byte)(color.Second.GetBrightness() * 255))
}; };
var Neutral = new List<string>(){"Neutral"}; var Neutral = new List<string>(){"Neutral"};
foreach (var s in file.GetSection(section, true)) foreach (var s in file.GetSection(section, true))
{ {
Console.WriteLine(s.Key); Console.WriteLine(s.Key);
switch(s.Key) switch(s.Key)
{ {
case "Credits": case "Credits":
pr.InitialCash = int.Parse(s.Value); pr.InitialCash = int.Parse(s.Value);
break; break;
case "Allies": case "Allies":
pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray(); pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray();
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray(); pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray();
break; break;
} }
} }
Map.Players.Add(section, pr); Map.Players.Add(section, pr);
} }
static string Truncate(string s, int maxLength) static string Truncate(string s, int maxLength)
{ {
return s.Length <= maxLength ? s : s.Substring(0, maxLength); return s.Length <= maxLength ? s : s.Substring(0, maxLength);
} }
} }
} }

View File

@@ -1,27 +1,27 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Windows.Forms; using System.Windows.Forms;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
public partial class NewMapDialog : Form public partial class NewMapDialog : Form
{ {
public NewMapDialog() public NewMapDialog()
{ {
InitializeComponent(); InitializeComponent();
} }
private void SelectText(object sender, System.EventArgs e) private void SelectText(object sender, System.EventArgs e)
{ {
(sender as NumericUpDown).Select(0, (sender as NumericUpDown).ToString().Length); (sender as NumericUpDown).Select(0, (sender as NumericUpDown).ToString().Length);
} }
} }
} }

View File

@@ -1,54 +1,54 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows.Forms; using System.Windows.Forms;
using System.Linq; using System.Linq;
using System.IO; using System.IO;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
static class Program static class Program
{ {
[STAThread] [STAThread]
static void Main( string[] args ) static void Main( string[] args )
{ {
if (args.Length >= 2 && args[0] == "--convert") if (args.Length >= 2 && args[0] == "--convert")
{ {
Game.modData = new ModData(args[1]); Game.modData = new ModData(args[1]);
FileSystem.LoadFromManifest(Game.modData.Manifest); FileSystem.LoadFromManifest(Game.modData.Manifest);
Rules.LoadRules(Game.modData.Manifest, new Map()); Rules.LoadRules(Game.modData.Manifest, new Map());
UpgradeMaps(args[1]); UpgradeMaps(args[1]);
return; return;
} }
Application.CurrentCulture = CultureInfo.InvariantCulture; Application.CurrentCulture = CultureInfo.InvariantCulture;
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args)); Application.Run(new Form1(args));
} }
static void UpgradeMaps(string mod) static void UpgradeMaps(string mod)
{ {
var MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", mod, "maps" } var MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", mod, "maps" }
.Aggregate(Path.Combine); .Aggregate(Path.Combine);
foreach (var path in ModData.FindMapsIn(MapFolderPath)) foreach (var path in ModData.FindMapsIn(MapFolderPath))
{ {
var map = new Map(path); var map = new Map(path);
map.Save(path); map.Save(path);
} }
} }
} }
} }

View File

@@ -1,22 +1,22 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Windows.Forms; using System.Windows.Forms;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
public partial class PropertiesDialog : Form public partial class PropertiesDialog : Form
{ {
public PropertiesDialog() public PropertiesDialog()
{ {
InitializeComponent(); InitializeComponent();
} }
} }
} }

View File

@@ -1,156 +1,156 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
static class RenderUtils static class RenderUtils
{ {
public static ColorPalette MakeSystemPalette(Palette p) public static ColorPalette MakeSystemPalette(Palette p)
{ {
ColorPalette pal; ColorPalette pal;
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
pal = b.Palette; pal = b.Palette;
for (var i = 0; i < 256; i++) for (var i = 0; i < 256; i++)
pal.Entries[i] = p.GetColor(i); pal.Entries[i] = p.GetColor(i);
return pal; return pal;
} }
public static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p) public static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
{ {
var template = ts.Templates[n]; var template = ts.Templates[n];
var tile = ts.Tiles[n]; var tile = ts.Tiles[n];
var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y, var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y,
PixelFormat.Format8bppIndexed); PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p); bitmap.Palette = MakeSystemPalette(p);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe unsafe
{ {
byte* q = (byte*)data.Scan0.ToPointer(); byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride; var stride = data.Stride;
for (var u = 0; u < template.Size.X; u++) for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++) for (var v = 0; v < template.Size.Y; v++)
if (tile.TileBitmapBytes[u + v * template.Size.X] != null) if (tile.TileBitmapBytes[u + v * template.Size.X] != null)
{ {
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X]; var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
for (var i = 0; i < ts.TileSize; i++) for (var i = 0; i < ts.TileSize; i++)
for (var j = 0; j < ts.TileSize; j++) for (var j = 0; j < ts.TileSize; j++)
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = rawImage[i + ts.TileSize * j]; q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = rawImage[i + ts.TileSize * j];
} }
else else
{ {
for (var i = 0; i < ts.TileSize; i++) for (var i = 0; i < ts.TileSize; i++)
for (var j = 0; j < ts.TileSize; j++) for (var j = 0; j < ts.TileSize; j++)
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = 0; q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = 0;
} }
} }
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
return bitmap; return bitmap;
} }
static Bitmap RenderShp(ShpReader shp, Palette p) static Bitmap RenderShp(ShpReader shp, Palette p)
{ {
var frame = shp[0]; var frame = shp[0];
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed); var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p); bitmap.Palette = MakeSystemPalette(p);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe unsafe
{ {
byte* q = (byte*)data.Scan0.ToPointer(); byte* q = (byte*)data.Scan0.ToPointer();
var stride2 = data.Stride; var stride2 = data.Stride;
for (var i = 0; i < shp.Width; i++) for (var i = 0; i < shp.Width; i++)
for (var j = 0; j < shp.Height; j++) for (var j = 0; j < shp.Height; j++)
q[j * stride2 + i] = frame.Image[i + shp.Width * j]; q[j * stride2 + i] = frame.Image[i + shp.Width * j];
} }
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
return bitmap; return bitmap;
} }
public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p) public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p)
{ {
var ri = info.Traits.Get<RenderSimpleInfo>(); var ri = info.Traits.Get<RenderSimpleInfo>();
var image = RenderSimple.GetImage(info, tileset.Id); var image = RenderSimple.GetImage(info, tileset.Id);
using (var s = FileSystem.OpenWithExts(image, tileset.Extensions)) using (var s = FileSystem.OpenWithExts(image, tileset.Extensions))
{ {
var shp = new ShpReader(s); var shp = new ShpReader(s);
var bitmap = RenderShp(shp, p); var bitmap = RenderShp(shp, p);
try try
{ {
using (var s2 = FileSystem.OpenWithExts(image + "2", tileset.Extensions)) using (var s2 = FileSystem.OpenWithExts(image + "2", tileset.Extensions))
{ {
var shp2 = new ShpReader(s2); var shp2 = new ShpReader(s2);
var roofBitmap = RenderShp(shp2, p); var roofBitmap = RenderShp(shp2, p);
using (var g = System.Drawing.Graphics.FromImage(bitmap)) using (var g = System.Drawing.Graphics.FromImage(bitmap))
g.DrawImage(roofBitmap, 0, 0); g.DrawImage(roofBitmap, 0, 0);
} }
} }
catch { } catch { }
return new ActorTemplate return new ActorTemplate
{ {
Bitmap = bitmap, Bitmap = bitmap,
Info = info, Info = info,
Appearance = info.Traits.GetOrDefault<EditorAppearanceInfo>() Appearance = info.Traits.GetOrDefault<EditorAppearanceInfo>()
}; };
} }
} }
public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p) public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p)
{ {
var image = info.SpriteNames[0]; var image = info.SpriteNames[0];
using (var s = FileSystem.OpenWithExts(image, exts)) using (var s = FileSystem.OpenWithExts(image, exts))
{ {
var shp = new ShpReader(s); var shp = new ShpReader(s);
var frame = shp[shp.ImageCount - 1]; var frame = shp[shp.ImageCount - 1];
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed); var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p); bitmap.Palette = MakeSystemPalette(p);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe unsafe
{ {
byte* q = (byte*)data.Scan0.ToPointer(); byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride; var stride = data.Stride;
for (var i = 0; i < shp.Width; i++) for (var i = 0; i < shp.Width; i++)
for (var j = 0; j < shp.Height; j++) for (var j = 0; j < shp.Height; j++)
q[j * stride + i] = frame.Image[i + shp.Width * j]; q[j * stride + i] = frame.Image[i + shp.Width * j];
} }
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 }; return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.ImageCount - 1 };
} }
} }
} }
} }

View File

@@ -1,22 +1,22 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Windows.Forms; using System.Windows.Forms;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
public partial class ResizeDialog : Form public partial class ResizeDialog : Form
{ {
public ResizeDialog() public ResizeDialog()
{ {
InitializeComponent(); InitializeComponent();
} }
} }
} }

View File

@@ -1,50 +1,50 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using SGraphics = System.Drawing.Graphics; using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
class ResourceTool : ITool class ResourceTool : ITool
{ {
ResourceTemplate Resource; ResourceTemplate Resource;
public ResourceTool(ResourceTemplate resource) { Resource = resource; } public ResourceTool(ResourceTemplate resource) { Resource = resource; }
public void Apply(Surface surface) public void Apply(Surface surface)
{ {
surface.Map.MapResources.Value[surface.GetBrushLocation().X, surface.GetBrushLocation().Y] surface.Map.MapResources.Value[surface.GetBrushLocation().X, surface.GetBrushLocation().Y]
= new TileReference<byte, byte> = new TileReference<byte, byte>
{ {
type = (byte)Resource.Info.ResourceType, type = (byte)Resource.Info.ResourceType,
index = (byte)random.Next(Resource.Info.SpriteNames.Length) index = (byte)random.Next(Resource.Info.SpriteNames.Length)
}; };
var ch = new int2((surface.GetBrushLocation().X) / Surface.ChunkSize, var ch = new int2((surface.GetBrushLocation().X) / Surface.ChunkSize,
(surface.GetBrushLocation().Y) / Surface.ChunkSize); (surface.GetBrushLocation().Y) / Surface.ChunkSize);
if (surface.Chunks.ContainsKey(ch)) if (surface.Chunks.ContainsKey(ch))
{ {
surface.Chunks[ch].Dispose(); surface.Chunks[ch].Dispose();
surface.Chunks.Remove(ch); surface.Chunks.Remove(ch);
} }
} }
public void Preview(Surface surface, SGraphics g) public void Preview(Surface surface, SGraphics g)
{ {
surface.DrawImage(g, Resource.Bitmap, surface.GetBrushLocation(), false, null); surface.DrawImage(g, Resource.Bitmap, surface.GetBrushLocation(), false, null);
} }
Random random = new Random(); Random random = new Random();
} }
} }

View File

@@ -1,364 +1,364 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
using SGraphics = System.Drawing.Graphics; using SGraphics = System.Drawing.Graphics;
namespace OpenRA.Editor namespace OpenRA.Editor
{ {
class Surface : Control class Surface : Control
{ {
public Map Map { get; private set; } public Map Map { get; private set; }
public TileSet TileSet { get; private set; } public TileSet TileSet { get; private set; }
public Palette Palette { get; private set; } public Palette Palette { get; private set; }
public int2 Offset; public int2 Offset;
public int2 GetOffset() { return Offset; } public int2 GetOffset() { return Offset; }
public float Zoom = 1.0f; public float Zoom = 1.0f;
ITool Tool; ITool Tool;
public bool IsPanning; public bool IsPanning;
public event Action AfterChange = () => { }; public event Action AfterChange = () => { };
public event Action<string> MousePositionChanged = _ => { }; public event Action<string> MousePositionChanged = _ => { };
Dictionary<string, ActorTemplate> ActorTemplates = new Dictionary<string, ActorTemplate>(); Dictionary<string, ActorTemplate> ActorTemplates = new Dictionary<string, ActorTemplate>();
Dictionary<int, ResourceTemplate> ResourceTemplates = new Dictionary<int, ResourceTemplate>(); Dictionary<int, ResourceTemplate> ResourceTemplates = new Dictionary<int, ResourceTemplate>();
public Keys GetModifiers() { return ModifierKeys; } public Keys GetModifiers() { return ModifierKeys; }
public void Bind(Map m, TileSet ts, Palette p) public void Bind(Map m, TileSet ts, Palette p)
{ {
Map = m; Map = m;
TileSet = ts; TileSet = ts;
Palette = p; Palette = p;
PlayerPalettes = null; PlayerPalettes = null;
Chunks.Clear(); Chunks.Clear();
Tool = null; Tool = null;
} }
public void SetTool(ITool tool) { Tool = tool; } public void SetTool(ITool tool) { Tool = tool; }
public void BindActorTemplates(IEnumerable<ActorTemplate> templates) public void BindActorTemplates(IEnumerable<ActorTemplate> templates)
{ {
ActorTemplates = templates.ToDictionary(a => a.Info.Name.ToLowerInvariant()); ActorTemplates = templates.ToDictionary(a => a.Info.Name.ToLowerInvariant());
} }
public void BindResourceTemplates(IEnumerable<ResourceTemplate> templates) public void BindResourceTemplates(IEnumerable<ResourceTemplate> templates)
{ {
ResourceTemplates = templates.ToDictionary(a => a.Info.ResourceType); ResourceTemplates = templates.ToDictionary(a => a.Info.ResourceType);
} }
public Dictionary<int2, Bitmap> Chunks = new Dictionary<int2, Bitmap>(); public Dictionary<int2, Bitmap> Chunks = new Dictionary<int2, Bitmap>();
public Surface() public Surface()
: base() : base()
{ {
BackColor = Color.Black; BackColor = Color.Black;
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.ResizeRedraw, true);
UpdateStyles(); UpdateStyles();
} }
static readonly Pen CordonPen = new Pen(Color.Red); static readonly Pen CordonPen = new Pen(Color.Red);
int2 MousePos; int2 MousePos;
public void Scroll(int2 dx) public void Scroll(int2 dx)
{ {
Offset -= dx; Offset -= dx;
Invalidate(); Invalidate();
} }
protected override void OnMouseWheel(MouseEventArgs e) protected override void OnMouseWheel(MouseEventArgs e)
{ {
base.OnMouseWheel(e); base.OnMouseWheel(e);
if (Map == null) return; if (Map == null) return;
Zoom *= e.Delta > 0 ? 4.0f / 3.0f : .75f; Zoom *= e.Delta > 0 ? 4.0f / 3.0f : .75f;
Invalidate(); Invalidate();
} }
protected override void OnMouseLeave(EventArgs e) protected override void OnMouseLeave(EventArgs e)
{ {
base.OnMouseLeave(e); base.OnMouseLeave(e);
this.Parent.Focus(); this.Parent.Focus();
Invalidate(); Invalidate();
} }
protected override void OnMouseEnter(EventArgs e) protected override void OnMouseEnter(EventArgs e)
{ {
base.OnMouseLeave(e); base.OnMouseLeave(e);
this.Focus(); this.Focus();
Invalidate(); Invalidate();
} }
protected override void OnMouseMove(MouseEventArgs e) protected override void OnMouseMove(MouseEventArgs e)
{ {
base.OnMouseMove(e); base.OnMouseMove(e);
if (Map == null) return; if (Map == null) return;
var oldMousePos = MousePos; var oldMousePos = MousePos;
MousePos = new int2(e.Location); MousePos = new int2(e.Location);
MousePositionChanged(GetBrushLocation().ToString()); MousePositionChanged(GetBrushLocation().ToString());
if (e.Button == MouseButtons.Middle || (e.Button != MouseButtons.None && IsPanning)) if (e.Button == MouseButtons.Middle || (e.Button != MouseButtons.None && IsPanning))
Scroll(oldMousePos - MousePos); Scroll(oldMousePos - MousePos);
else else
{ {
if (e.Button == MouseButtons.Right) if (e.Button == MouseButtons.Right)
Erase(); Erase();
if (e.Button == MouseButtons.Left) if (e.Button == MouseButtons.Left)
Draw(); Draw();
Invalidate(); Invalidate();
} }
} }
void Erase() void Erase()
{ {
// Crash preventing // Crash preventing
var BrushLocation = GetBrushLocation(); var BrushLocation = GetBrushLocation();
if (Map == null || BrushLocation.X >= Map.MapSize.X || if (Map == null || BrushLocation.X >= Map.MapSize.X ||
BrushLocation.Y >= Map.MapSize.Y || BrushLocation.Y >= Map.MapSize.Y ||
BrushLocation.X < 0 || BrushLocation.X < 0 ||
BrushLocation.Y < 0) BrushLocation.Y < 0)
return; return;
Tool = null; Tool = null;
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == BrushLocation); var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == BrushLocation);
if (key.Key != null) Map.Actors.Value.Remove(key.Key); if (key.Key != null) Map.Actors.Value.Remove(key.Key);
if (Map.MapResources.Value[BrushLocation.X, BrushLocation.Y].type != 0) if (Map.MapResources.Value[BrushLocation.X, BrushLocation.Y].type != 0)
{ {
Map.MapResources.Value[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>(); Map.MapResources.Value[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>();
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize); var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize);
if (Chunks.ContainsKey(ch)) if (Chunks.ContainsKey(ch))
{ {
Chunks[ch].Dispose(); Chunks[ch].Dispose();
Chunks.Remove(ch); Chunks.Remove(ch);
} }
} }
AfterChange(); AfterChange();
} }
void Draw() void Draw()
{ {
if (Tool != null) Tool.Apply(this); if (Tool != null) Tool.Apply(this);
AfterChange(); AfterChange();
} }
protected override void OnMouseDown(MouseEventArgs e) protected override void OnMouseDown(MouseEventArgs e)
{ {
base.OnMouseDown(e); base.OnMouseDown(e);
if (Map == null) return; if (Map == null) return;
if (!IsPanning) if (!IsPanning)
{ {
if (e.Button == MouseButtons.Right) Erase(); if (e.Button == MouseButtons.Right) Erase();
if (e.Button == MouseButtons.Left) Draw(); if (e.Button == MouseButtons.Left) Draw();
} }
Invalidate(); Invalidate();
} }
public const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps. public const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps.
Bitmap RenderChunk(int u, int v) Bitmap RenderChunk(int u, int v)
{ {
var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize); var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize);
bitmap.SetPixel(0, 0, Color.Green); bitmap.SetPixel(0, 0, Color.Green);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe unsafe
{ {
int* p = (int*)data.Scan0.ToPointer(); int* p = (int*)data.Scan0.ToPointer();
var stride = data.Stride >> 2; var stride = data.Stride >> 2;
for (var i = 0; i < ChunkSize; i++) for (var i = 0; i < ChunkSize; i++)
for (var j = 0; j < ChunkSize; j++) for (var j = 0; j < ChunkSize; j++)
{ {
var tr = Map.MapTiles.Value[u * ChunkSize + i, v * ChunkSize + j]; var tr = Map.MapTiles.Value[u * ChunkSize + i, v * ChunkSize + j];
var tile = TileSet.Tiles[tr.type]; var tile = TileSet.Tiles[tr.type];
var index = (tr.index < tile.TileBitmapBytes.Count) ? tr.index : (byte)0; var index = (tr.index < tile.TileBitmapBytes.Count) ? tr.index : (byte)0;
var rawImage = tile.TileBitmapBytes[index]; var rawImage = tile.TileBitmapBytes[index];
for (var x = 0; x < TileSet.TileSize; x++) for (var x = 0; x < TileSet.TileSize; x++)
for (var y = 0; y < TileSet.TileSize; y++) for (var y = 0; y < TileSet.TileSize; y++)
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = Palette.GetColor(rawImage[x + TileSet.TileSize * y]).ToArgb(); p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = Palette.GetColor(rawImage[x + TileSet.TileSize * y]).ToArgb();
if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type != 0) if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type != 0)
{ {
var resourceImage = ResourceTemplates[Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type].Bitmap; var resourceImage = ResourceTemplates[Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type].Bitmap;
var srcdata = resourceImage.LockBits(new Rectangle(0, 0, resourceImage.Width, resourceImage.Height), var srcdata = resourceImage.LockBits(new Rectangle(0, 0, resourceImage.Width, resourceImage.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int* q = (int*)srcdata.Scan0.ToPointer(); int* q = (int*)srcdata.Scan0.ToPointer();
var srcstride = srcdata.Stride >> 2; var srcstride = srcdata.Stride >> 2;
for (var x = 0; x < TileSet.TileSize; x++) for (var x = 0; x < TileSet.TileSize; x++)
for (var y = 0; y < TileSet.TileSize; y++) for (var y = 0; y < TileSet.TileSize; y++)
{ {
var c = q[y * srcstride + x]; var c = q[y * srcstride + x];
if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */ if ((c & 0xff000000) != 0) /* quick & dirty, i cbf doing real alpha */
p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = c; p[(j * TileSet.TileSize + y) * stride + i * TileSet.TileSize + x] = c;
} }
resourceImage.UnlockBits(srcdata); resourceImage.UnlockBits(srcdata);
} }
} }
} }
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
return bitmap; return bitmap;
} }
public int2 GetBrushLocation() public int2 GetBrushLocation()
{ {
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom); var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom); var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize); return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
} }
public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp) public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp)
{ {
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
DrawImage(g, t.Bitmap, p, centered, cp); DrawImage(g, t.Bitmap, p, centered, cp);
} }
float2 GetDrawPosition(int2 location, Bitmap bmp, bool centered) float2 GetDrawPosition(int2 location, Bitmap bmp, bool centered)
{ {
float OffsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0; float OffsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0;
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX; float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX;
float OffsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0; float OffsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0;
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY; float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY;
return new float2(DrawX, DrawY); return new float2(DrawX, DrawY);
} }
public void DrawImage(SGraphics g, Bitmap bmp, int2 location, bool centered, ColorPalette cp) public void DrawImage(SGraphics g, Bitmap bmp, int2 location, bool centered, ColorPalette cp)
{ {
var drawPos = GetDrawPosition(location, bmp, centered); var drawPos = GetDrawPosition(location, bmp, centered);
var sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height); var sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
var destRect = new RectangleF(drawPos.X, drawPos.Y, bmp.Width * Zoom, bmp.Height * Zoom); var destRect = new RectangleF(drawPos.X, drawPos.Y, bmp.Width * Zoom, bmp.Height * Zoom);
var restorePalette = bmp.Palette; var restorePalette = bmp.Palette;
if (cp != null) bmp.Palette = cp; if (cp != null) bmp.Palette = cp;
g.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel); g.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
if (cp != null) bmp.Palette = restorePalette; if (cp != null) bmp.Palette = restorePalette;
} }
void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t) void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t)
{ {
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
var drawPos = GetDrawPosition(p, t.Bitmap, centered); var drawPos = GetDrawPosition(p, t.Bitmap, centered);
g.DrawRectangle(CordonPen, g.DrawRectangle(CordonPen,
drawPos.X, drawPos.Y, drawPos.X, drawPos.Y,
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom); t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);
} }
ColorPalette GetPaletteForPlayer(string name) ColorPalette GetPaletteForPlayer(string name)
{ {
var pr = Map.Players[name]; var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>(); var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pr.ColorRamp, pcpi.PaletteFormat); var remap = new PlayerColorRemap(pr.ColorRamp, pcpi.PaletteFormat);
return RenderUtils.MakeSystemPalette(new Palette(Palette, remap)); return RenderUtils.MakeSystemPalette(new Palette(Palette, remap));
} }
Cache<string, ColorPalette> PlayerPalettes; Cache<string, ColorPalette> PlayerPalettes;
ColorPalette GetPaletteForActor(ActorReference ar) ColorPalette GetPaletteForActor(ActorReference ar)
{ {
if (PlayerPalettes == null) if (PlayerPalettes == null)
PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer); PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer);
var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>(); var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>();
if (ownerInit == null) if (ownerInit == null)
return null; return null;
return PlayerPalettes[ownerInit.PlayerName]; return PlayerPalettes[ownerInit.PlayerName];
} }
protected override void OnPaint(PaintEventArgs e) protected override void OnPaint(PaintEventArgs e)
{ {
if (Map == null) return; if (Map == null) return;
if (TileSet == null) return; if (TileSet == null) return;
for (var u = 0; u < Map.MapSize.X; u += ChunkSize) for (var u = 0; u < Map.MapSize.X; u += ChunkSize)
for (var v = 0; v < Map.MapSize.Y; v += ChunkSize) for (var v = 0; v < Map.MapSize.Y; v += ChunkSize)
{ {
var x = new int2(u / ChunkSize, v / ChunkSize); var x = new int2(u / ChunkSize, v / ChunkSize);
if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize); if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize);
Bitmap bmp = Chunks[x]; Bitmap bmp = Chunks[x];
float DrawX = TileSet.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X; float DrawX = TileSet.TileSize * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
float DrawY = TileSet.TileSize * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y; float DrawY = TileSet.TileSize * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height); RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
RectangleF destRect = new RectangleF(DrawX, DrawY, bmp.Width * Zoom, bmp.Height * Zoom); RectangleF destRect = new RectangleF(DrawX, DrawY, bmp.Width * Zoom, bmp.Height * Zoom);
e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel); e.Graphics.DrawImage(bmp, destRect, sourceRect, GraphicsUnit.Pixel);
} }
e.Graphics.DrawRectangle(CordonPen, e.Graphics.DrawRectangle(CordonPen,
Map.Bounds.Left * TileSet.TileSize * Zoom + Offset.X, Map.Bounds.Left * TileSet.TileSize * Zoom + Offset.X,
Map.Bounds.Top * TileSet.TileSize * Zoom + Offset.Y, Map.Bounds.Top * TileSet.TileSize * Zoom + Offset.Y,
Map.Bounds.Width * TileSet.TileSize * Zoom, Map.Bounds.Width * TileSet.TileSize * Zoom,
Map.Bounds.Height * TileSet.TileSize * Zoom); Map.Bounds.Height * TileSet.TileSize * Zoom);
foreach (var ar in Map.Actors.Value) foreach (var ar in Map.Actors.Value)
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type], DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type],
GetPaletteForActor(ar.Value)); GetPaletteForActor(ar.Value));
if (Tool != null) if (Tool != null)
Tool.Preview(this, e.Graphics); Tool.Preview(this, e.Graphics);
if (Tool == null) if (Tool == null)
{ {
var x = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == GetBrushLocation()); var x = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == GetBrushLocation());
if (x.Key != null) if (x.Key != null)
DrawActorBorder(e.Graphics, x.Value.Location(), ActorTemplates[x.Value.Type]); DrawActorBorder(e.Graphics, x.Value.Location(), ActorTemplates[x.Value.Type]);
} }
} }
} }
static class ActorReferenceExts static class ActorReferenceExts
{ {
public static int2 Location(this ActorReference ar) public static int2 Location(this ActorReference ar)
{ {
return ar.InitDict.Get<LocationInit>().value; return ar.InitDict.Get<LocationInit>().value;
} }
} }
} }

View File

@@ -1,64 +1,64 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public struct ColorRamp public struct ColorRamp
{ {
public byte H,S,L,R; public byte H,S,L,R;
public ColorRamp(byte h, byte s, byte l, byte r) public ColorRamp(byte h, byte s, byte l, byte r)
{ {
H = h; S = s; L = l; R = r; H = h; S = s; L = l; R = r;
} }
/* returns a color along the Lum ramp */ /* returns a color along the Lum ramp */
public Color GetColor( float t ) public Color GetColor( float t )
{ {
return ColorFromHSL( H / 255f, S / 255f, float2.Lerp( L / 255f, L*R / (255f * 255f), t ) ); return ColorFromHSL( H / 255f, S / 255f, float2.Lerp( L / 255f, L*R / (255f * 255f), t ) );
} }
public override string ToString() public override string ToString()
{ {
return "{0},{1},{2},{3}".F(H, S, L, R); return "{0},{1},{2},{3}".F(H, S, L, R);
} }
// hk is hue in the range [0,1] instead of [0,360] // hk is hue in the range [0,1] instead of [0,360]
public static Color ColorFromHSL(float hk, float s, float l) public static Color ColorFromHSL(float hk, float s, float l)
{ {
// Convert from HSL to RGB // Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s); var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q; var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f, float[] trgb = { hk + 1 / 3.0f,
hk, hk,
hk - 1/3.0f }; hk - 1/3.0f };
float[] rgb = { 0, 0, 0 }; float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++) for (int k = 0; k < 3; k++)
{ {
while (trgb[k] < 0) trgb[k] += 1.0f; while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f; while (trgb[k] > 1) trgb[k] -= 1.0f;
} }
for (int k = 0; k < 3; k++) for (int k = 0; k < 3; k++)
{ {
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); } if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; } else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); } else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; } else { rgb[k] = p; }
} }
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255)); return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
} }
} }
} }

View File

@@ -1,107 +1,107 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class Evaluator public static class Evaluator
{ {
public static int Evaluate(string expr) public static int Evaluate(string expr)
{ {
return Evaluate(expr, new Dictionary<string, int>()); return Evaluate(expr, new Dictionary<string, int>());
} }
public static int Evaluate(string expr, Dictionary<string, int> syms) public static int Evaluate(string expr, Dictionary<string, int> syms)
{ {
var toks = Tokens(expr, "+-*/()"); var toks = Tokens(expr, "+-*/()");
var postfix = ToPostfix(toks, syms); var postfix = ToPostfix(toks, syms);
var s = new Stack<int>(); var s = new Stack<int>();
foreach (var t in postfix) foreach (var t in postfix)
{ {
switch (t[0]) switch (t[0])
{ {
case '+': ApplyBinop(s, (x, y) => y + x); break; case '+': ApplyBinop(s, (x, y) => y + x); break;
case '-': ApplyBinop(s, (x, y) => y - x); break; case '-': ApplyBinop(s, (x, y) => y - x); break;
case '*': ApplyBinop(s, (x, y) => y * x); break; case '*': ApplyBinop(s, (x, y) => y * x); break;
case '/': ApplyBinop(s, (x, y) => y / x); break; case '/': ApplyBinop(s, (x, y) => y / x); break;
default: s.Push(int.Parse(t)); break; default: s.Push(int.Parse(t)); break;
} }
} }
return s.Pop(); return s.Pop();
} }
static void ApplyBinop( Stack<int> s, Func<int,int,int> f ) static void ApplyBinop( Stack<int> s, Func<int,int,int> f )
{ {
var x = s.Pop(); var x = s.Pop();
var y = s.Pop(); var y = s.Pop();
s.Push( f(x,y) ); s.Push( f(x,y) );
} }
static IEnumerable<string> ToPostfix(IEnumerable<string> toks, Dictionary<string, int> syms) static IEnumerable<string> ToPostfix(IEnumerable<string> toks, Dictionary<string, int> syms)
{ {
var s = new Stack<string>(); var s = new Stack<string>();
foreach (var t in toks) foreach (var t in toks)
{ {
if (t[0] == '(') s.Push(t); if (t[0] == '(') s.Push(t);
else if (t[0] == ')') else if (t[0] == ')')
{ {
var temp = ""; var temp = "";
while ((temp = s.Pop()) != "(") yield return temp; while ((temp = s.Pop()) != "(") yield return temp;
} }
else if (char.IsNumber(t[0])) yield return t; else if (char.IsNumber(t[0])) yield return t;
else if (char.IsLetter(t[0])) else if (char.IsLetter(t[0]))
{ {
if (!syms.ContainsKey(t)) if (!syms.ContainsKey(t))
throw new InvalidOperationException("Substitution `{0}` undefined".F(t)); throw new InvalidOperationException("Substitution `{0}` undefined".F(t));
yield return syms[t].ToString();; yield return syms[t].ToString();;
} }
else else
{ {
while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop(); while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop();
s.Push(t); s.Push(t);
} }
} }
while (s.Count > 0) yield return s.Pop(); while (s.Count > 0) yield return s.Pop();
} }
static readonly Dictionary<string, int> Prec static readonly Dictionary<string, int> Prec
= new Dictionary<string, int> { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 }, { "(", -1 } }; = new Dictionary<string, int> { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 }, { "(", -1 } };
static IEnumerable<string> Tokens(string expr, string ops) static IEnumerable<string> Tokens(string expr, string ops)
{ {
var s = ""; var s = "";
foreach (var c in expr) foreach (var c in expr)
{ {
if (char.IsWhiteSpace(c)) if (char.IsWhiteSpace(c))
{ {
if (s != "") yield return s; if (s != "") yield return s;
s = ""; s = "";
} }
else if (ops.Contains(c)) else if (ops.Contains(c))
{ {
if (s != "") yield return s; if (s != "") yield return s;
s = ""; s = "";
yield return "" + c; yield return "" + c;
} }
else else
s += c; s += c;
} }
if (s != "") yield return s; if (s != "") yield return s;
} }
} }
} }

View File

@@ -1,110 +1,110 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
namespace OpenRA namespace OpenRA
{ {
public static class Exts public static class Exts
{ {
public static string F(this string fmt, params object[] args) public static string F(this string fmt, params object[] args)
{ {
return string.Format(fmt, args); return string.Format(fmt, args);
} }
public static void Do<T>(this IEnumerable<T> e, Action<T> fn) public static void Do<T>(this IEnumerable<T> e, Action<T> fn)
{ {
foreach (var ee in e) foreach (var ee in e)
fn(ee); fn(ee);
} }
public static IEnumerable<string> GetNamespaces(this Assembly a) public static IEnumerable<string> GetNamespaces(this Assembly a)
{ {
return a.GetTypes().Select(t => t.Namespace).Distinct().Where(n => n != null); return a.GetTypes().Select(t => t.Namespace).Distinct().Where(n => n != null);
} }
public static string ReadAllText(this Stream s) public static string ReadAllText(this Stream s)
{ {
using (s) using (s)
using (var sr = new StreamReader(s)) using (var sr = new StreamReader(s))
return sr.ReadToEnd(); return sr.ReadToEnd();
} }
public static byte[] ReadAllBytes(this Stream s) public static byte[] ReadAllBytes(this Stream s)
{ {
using (s) using (s)
{ {
var data = new byte[s.Length - s.Position]; var data = new byte[s.Length - s.Position];
s.Read(data, 0, data.Length); s.Read(data, 0, data.Length);
return data; return data;
} }
} }
public static void Write(this Stream s, byte[] data) public static void Write(this Stream s, byte[] data)
{ {
s.Write(data, 0, data.Length); s.Write(data, 0, data.Length);
} }
public static IEnumerable<string> ReadAllLines(this Stream s) public static IEnumerable<string> ReadAllLines(this Stream s)
{ {
using (var sr = new StreamReader(s)) using (var sr = new StreamReader(s))
for (; ; ) for (; ; )
{ {
var line = sr.ReadLine(); var line = sr.ReadLine();
if (line == null) if (line == null)
yield break; yield break;
else else
yield return line; yield return line;
} }
} }
public static bool HasAttribute<T>(this MemberInfo mi) public static bool HasAttribute<T>(this MemberInfo mi)
{ {
return mi.GetCustomAttributes(typeof(T), true).Length != 0; return mi.GetCustomAttributes(typeof(T), true).Length != 0;
} }
public static T[] GetCustomAttributes<T>(this MemberInfo mi, bool inherit) public static T[] GetCustomAttributes<T>(this MemberInfo mi, bool inherit)
where T : class where T : class
{ {
return (T[])mi.GetCustomAttributes(typeof(T), inherit); return (T[])mi.GetCustomAttributes(typeof(T), inherit);
} }
public static T[] GetCustomAttributes<T>(this ParameterInfo mi) public static T[] GetCustomAttributes<T>(this ParameterInfo mi)
where T : class where T : class
{ {
return (T[])mi.GetCustomAttributes(typeof(T), true); return (T[])mi.GetCustomAttributes(typeof(T), true);
} }
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T> public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{ {
if (val.CompareTo(min) < 0) if (val.CompareTo(min) < 0)
return min; return min;
else if (val.CompareTo(max) > 0) else if (val.CompareTo(max) > 0)
return max; return max;
else else
return val; return val;
} }
public static bool Contains(this Rectangle r, int2 p) public static bool Contains(this Rectangle r, int2 p)
{ {
return r.Contains(p.ToPoint()); return r.Contains(p.ToPoint());
} }
public static bool Contains(this RectangleF r, int2 p) public static bool Contains(this RectangleF r, int2 p)
{ {
return r.Contains(p.ToPointF()); return r.Contains(p.ToPointF());
} }
} }
} }

View File

@@ -1,316 +1,316 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Globalization; using System.Globalization;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class FieldLoader public static class FieldLoader
{ {
public static Func<string,Type,string,object> InvalidValueAction = (s,t,f) => public static Func<string,Type,string,object> InvalidValueAction = (s,t,f) =>
{ {
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) ); throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) );
}; };
public static Action<string,Type> UnknownFieldAction = (s,f) => public static Action<string,Type> UnknownFieldAction = (s,f) =>
{ {
throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) ); throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) );
}; };
public static void Load( object self, MiniYaml my ) public static void Load( object self, MiniYaml my )
{ {
var loadDict = typeLoadInfo[ self.GetType() ]; var loadDict = typeLoadInfo[ self.GetType() ];
foreach( var kv in loadDict ) foreach( var kv in loadDict )
{ {
object val; object val;
if( kv.Value != null ) if( kv.Value != null )
val = kv.Value( kv.Key.Name, kv.Key.FieldType, my ); val = kv.Value( kv.Key.Name, kv.Key.FieldType, my );
else if( !TryGetValueFromYaml( kv.Key.Name, kv.Key.FieldType, my, out val ) ) else if( !TryGetValueFromYaml( kv.Key.Name, kv.Key.FieldType, my, out val ) )
continue; continue;
kv.Key.SetValue( self, val ); kv.Key.SetValue( self, val );
} }
} }
static bool TryGetValueFromYaml( string fieldName, Type fieldType, MiniYaml yaml, out object ret ) static bool TryGetValueFromYaml( string fieldName, Type fieldType, MiniYaml yaml, out object ret )
{ {
ret = null; ret = null;
var n = yaml.Nodes.Where( x=>x.Key == fieldName ).ToList(); var n = yaml.Nodes.Where( x=>x.Key == fieldName ).ToList();
if( n.Count == 0 ) if( n.Count == 0 )
return false; return false;
if( n.Count == 1 && n[ 0 ].Value.Nodes.Count == 0 ) if( n.Count == 1 && n[ 0 ].Value.Nodes.Count == 0 )
{ {
ret = GetValue( fieldName, fieldType, n[ 0 ].Value.Value ); ret = GetValue( fieldName, fieldType, n[ 0 ].Value.Value );
return true; return true;
} }
throw new InvalidOperationException( "TryGetValueFromYaml: unable to load field {0} (of type {1})".F( fieldName, fieldType ) ); throw new InvalidOperationException( "TryGetValueFromYaml: unable to load field {0} (of type {1})".F( fieldName, fieldType ) );
} }
public static T Load<T>(MiniYaml y) where T : new() public static T Load<T>(MiniYaml y) where T : new()
{ {
var t = new T(); var t = new T();
Load(t, y); Load(t, y);
return t; return t;
} }
public static void LoadField( object self, string key, string value ) public static void LoadField( object self, string key, string value )
{ {
var field = self.GetType().GetField( key.Trim() ); var field = self.GetType().GetField( key.Trim() );
if( field == null ) if( field == null )
UnknownFieldAction( key.Trim(), self.GetType() ); UnknownFieldAction( key.Trim(), self.GetType() );
else if( field.HasAttribute<FieldFromYamlKeyAttribute>() ) else if( field.HasAttribute<FieldFromYamlKeyAttribute>() )
return; return;
else else
field.SetValue( self, GetValue( field.Name, field.FieldType, value ) ); field.SetValue( self, GetValue( field.Name, field.FieldType, value ) );
} }
public static object GetValue( string field, Type fieldType, string x ) public static object GetValue( string field, Type fieldType, string x )
{ {
if (x != null) x = x.Trim(); if (x != null) x = x.Trim();
if( fieldType == typeof( int ) ) if( fieldType == typeof( int ) )
{ {
int res; int res;
if (int.TryParse(x,out res)) if (int.TryParse(x,out res))
return res; return res;
return InvalidValueAction(x,fieldType, field); return InvalidValueAction(x,fieldType, field);
} }
else if( fieldType == typeof( ushort ) ) else if( fieldType == typeof( ushort ) )
{ {
ushort res; ushort res;
if (ushort.TryParse(x,out res)) if (ushort.TryParse(x,out res))
return res; return res;
return InvalidValueAction(x,fieldType, field); return InvalidValueAction(x,fieldType, field);
} }
else if (fieldType == typeof(float)) else if (fieldType == typeof(float))
{ {
float res; float res;
if (float.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res)) if (float.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
return res * (x.Contains( '%' ) ? 0.01f : 1f); return res * (x.Contains( '%' ) ? 0.01f : 1f);
return InvalidValueAction(x,fieldType, field); return InvalidValueAction(x,fieldType, field);
} }
else if (fieldType == typeof(decimal)) else if (fieldType == typeof(decimal))
{ {
decimal res; decimal res;
if (decimal.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res)) if (decimal.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
return res * (x.Contains( '%' ) ? 0.01m : 1m); return res * (x.Contains( '%' ) ? 0.01m : 1m);
return InvalidValueAction(x,fieldType, field); return InvalidValueAction(x,fieldType, field);
} }
else if (fieldType == typeof(string)) else if (fieldType == typeof(string))
return x; return x;
else if (fieldType == typeof(Color)) else if (fieldType == typeof(Color))
{ {
var parts = x.Split(','); var parts = x.Split(',');
if (parts.Length == 3) if (parts.Length == 3)
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255)); return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255));
if (parts.Length == 4) if (parts.Length == 4)
return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255)); return Color.FromArgb(int.Parse(parts[0]).Clamp(0, 255), int.Parse(parts[1]).Clamp(0, 255), int.Parse(parts[2]).Clamp(0, 255), int.Parse(parts[3]).Clamp(0, 255));
return InvalidValueAction(x,fieldType, field); return InvalidValueAction(x,fieldType, field);
} }
else if (fieldType == typeof(ColorRamp)) else if (fieldType == typeof(ColorRamp))
{ {
var parts = x.Split(','); var parts = x.Split(',');
if (parts.Length == 4) if (parts.Length == 4)
return new ColorRamp( return new ColorRamp(
(byte)int.Parse(parts[0]).Clamp(0, 255), (byte)int.Parse(parts[0]).Clamp(0, 255),
(byte)int.Parse(parts[1]).Clamp(0, 255), (byte)int.Parse(parts[1]).Clamp(0, 255),
(byte)int.Parse(parts[2]).Clamp(0, 255), (byte)int.Parse(parts[2]).Clamp(0, 255),
(byte)int.Parse(parts[3]).Clamp(0, 255)); (byte)int.Parse(parts[3]).Clamp(0, 255));
return InvalidValueAction(x, fieldType, field); return InvalidValueAction(x, fieldType, field);
} }
else if (fieldType.IsEnum) else if (fieldType.IsEnum)
{ {
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower())) if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
return InvalidValueAction(x, fieldType, field); return InvalidValueAction(x, fieldType, field);
return Enum.Parse(fieldType, x, true); return Enum.Parse(fieldType, x, true);
} }
else if (fieldType == typeof(bool)) else if (fieldType == typeof(bool))
return ParseYesNo(x, fieldType, field); return ParseYesNo(x, fieldType, field);
else if (fieldType.IsArray) else if (fieldType.IsArray)
{ {
if (x == null) if (x == null)
return Array.CreateInstance(fieldType.GetElementType(), 0); return Array.CreateInstance(fieldType.GetElementType(), 0);
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length); var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
ret.SetValue(GetValue(field, fieldType.GetElementType(), parts[i].Trim()), i); ret.SetValue(GetValue(field, fieldType.GetElementType(), parts[i].Trim()), i);
return ret; return ret;
} }
else if (fieldType == typeof(int2)) else if (fieldType == typeof(int2))
{ {
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new int2(int.Parse(parts[0]), int.Parse(parts[1])); return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
} }
else if (fieldType == typeof(float2)) else if (fieldType == typeof(float2))
{ {
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
float xx = 0; float xx = 0;
float yy = 0; float yy = 0;
float res; float res;
if (float.TryParse(parts[0].Replace("%", ""), out res)) if (float.TryParse(parts[0].Replace("%", ""), out res))
xx = res * (parts[0].Contains('%') ? 0.01f : 1f); xx = res * (parts[0].Contains('%') ? 0.01f : 1f);
if (float.TryParse(parts[1].Replace("%", ""), out res)) if (float.TryParse(parts[1].Replace("%", ""), out res))
yy = res * (parts[1].Contains('%') ? 0.01f : 1f); yy = res * (parts[1].Contains('%') ? 0.01f : 1f);
return new float2(xx, yy); return new float2(xx, yy);
} }
else if (fieldType == typeof(Rectangle)) else if (fieldType == typeof(Rectangle))
{ {
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new Rectangle(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3])); return new Rectangle(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]));
} }
UnknownFieldAction("[Type] {0}".F(x),fieldType); UnknownFieldAction("[Type] {0}".F(x),fieldType);
return null; return null;
} }
static object ParseYesNo( string p, System.Type fieldType, string field ) static object ParseYesNo( string p, System.Type fieldType, string field )
{ {
p = p.ToLowerInvariant(); p = p.ToLowerInvariant();
if( p == "yes" ) return true; if( p == "yes" ) return true;
if( p == "true" ) return true; if( p == "true" ) return true;
if( p == "no" ) return false; if( p == "no" ) return false;
if( p == "false" ) return false; if( p == "false" ) return false;
return InvalidValueAction(p,fieldType, field); return InvalidValueAction(p,fieldType, field);
} }
static Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>> typeLoadInfo = new Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>>( GetTypeLoadInfo ); static Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>> typeLoadInfo = new Cache<Type, Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>>( GetTypeLoadInfo );
static Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>> GetTypeLoadInfo( Type type ) static Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>> GetTypeLoadInfo( Type type )
{ {
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>(); var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
foreach( var ff in type.GetFields() ) foreach( var ff in type.GetFields() )
{ {
var field = ff; var field = ff;
var load = field.GetCustomAttributes<LoadAttribute>( false ); var load = field.GetCustomAttributes<LoadAttribute>( false );
var loadUsing = field.GetCustomAttributes<LoadUsingAttribute>( false ); var loadUsing = field.GetCustomAttributes<LoadUsingAttribute>( false );
var fromYamlKey = field.GetCustomAttributes<FieldFromYamlKeyAttribute>( false ); var fromYamlKey = field.GetCustomAttributes<FieldFromYamlKeyAttribute>( false );
if( loadUsing.Length != 0 ) if( loadUsing.Length != 0 )
ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml ); ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
else if( fromYamlKey.Length != 0 ) else if( fromYamlKey.Length != 0 )
ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value ); ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value );
else if( load.Length != 0 ) else if( load.Length != 0 )
ret[ field ] = null; ret[ field ] = null;
} }
if( ret.Count == 0 ) if( ret.Count == 0 )
foreach( var f in type.GetFields() ) foreach( var f in type.GetFields() )
ret.Add( f, null ); ret.Add( f, null );
return ret; return ret;
} }
[AttributeUsage( AttributeTargets.Field )] [AttributeUsage( AttributeTargets.Field )]
public class LoadAttribute : Attribute { } public class LoadAttribute : Attribute { }
[AttributeUsage( AttributeTargets.Field )] [AttributeUsage( AttributeTargets.Field )]
public class LoadUsingAttribute : Attribute public class LoadUsingAttribute : Attribute
{ {
Func<MiniYaml, object> loaderFuncCache; Func<MiniYaml, object> loaderFuncCache;
public readonly string Loader; public readonly string Loader;
public LoadUsingAttribute( string loader ) public LoadUsingAttribute( string loader )
{ {
Loader = loader; Loader = loader;
} }
internal Func<MiniYaml, object> LoaderFunc( FieldInfo field ) internal Func<MiniYaml, object> LoaderFunc( FieldInfo field )
{ {
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
if( loaderFuncCache == null ) if( loaderFuncCache == null )
loaderFuncCache = (Func<MiniYaml, object>)Delegate.CreateDelegate( typeof( Func<MiniYaml, object> ), field.DeclaringType.GetMethod( Loader, bf ) ); loaderFuncCache = (Func<MiniYaml, object>)Delegate.CreateDelegate( typeof( Func<MiniYaml, object> ), field.DeclaringType.GetMethod( Loader, bf ) );
return loaderFuncCache; return loaderFuncCache;
} }
} }
} }
public static class FieldSaver public static class FieldSaver
{ {
public static MiniYaml Save(object o) public static MiniYaml Save(object o)
{ {
var nodes = new List<MiniYamlNode>(); var nodes = new List<MiniYamlNode>();
string root = null; string root = null;
foreach( var f in o.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance ) ) foreach( var f in o.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance ) )
{ {
if( f.HasAttribute<FieldFromYamlKeyAttribute>() ) if( f.HasAttribute<FieldFromYamlKeyAttribute>() )
root = FormatValue( o, f ); root = FormatValue( o, f );
else else
nodes.Add( new MiniYamlNode( f.Name, FormatValue( o, f ) ) ); nodes.Add( new MiniYamlNode( f.Name, FormatValue( o, f ) ) );
} }
return new MiniYaml( root, nodes ); return new MiniYaml( root, nodes );
} }
public static MiniYaml SaveDifferences(object o, object from) public static MiniYaml SaveDifferences(object o, object from)
{ {
if (o.GetType() != from.GetType()) if (o.GetType() != from.GetType())
throw new InvalidOperationException("FieldLoader: can't diff objects of different types"); throw new InvalidOperationException("FieldLoader: can't diff objects of different types");
var fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance) var fields = o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(f => FormatValue(o,f) != FormatValue(from,f)); .Where(f => FormatValue(o,f) != FormatValue(from,f));
return new MiniYaml( null, fields.Select( f => new MiniYamlNode( return new MiniYaml( null, fields.Select( f => new MiniYamlNode(
f.Name, f.Name,
FormatValue( o, f ) ) ).ToList() ); FormatValue( o, f ) ) ).ToList() );
} }
public static MiniYamlNode SaveField(object o, string field) public static MiniYamlNode SaveField(object o, string field)
{ {
return new MiniYamlNode(field, FieldSaver.FormatValue( o, o.GetType().GetField(field) )); return new MiniYamlNode(field, FieldSaver.FormatValue( o, o.GetType().GetField(field) ));
} }
public static string FormatValue(object o, FieldInfo f) public static string FormatValue(object o, FieldInfo f)
{ {
var v = f.GetValue(o); var v = f.GetValue(o);
if (v == null) if (v == null)
return ""; return "";
// Color.ToString() does the wrong thing; force it to format as an array // Color.ToString() does the wrong thing; force it to format as an array
if (f.FieldType == typeof(Color)) if (f.FieldType == typeof(Color))
{ {
var c = (Color)v; var c = (Color)v;
return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255), return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255),
((int)c.R).Clamp(0, 255), ((int)c.R).Clamp(0, 255),
((int)c.G).Clamp(0, 255), ((int)c.G).Clamp(0, 255),
((int)c.B).Clamp(0, 255)); ((int)c.B).Clamp(0, 255));
} }
else if (f.FieldType == typeof(Rectangle)) else if (f.FieldType == typeof(Rectangle))
{ {
var r = (Rectangle)v; var r = (Rectangle)v;
return "{0},{1},{2},{3}".F(r.X, r.Y, r.Width, r.Height); return "{0},{1},{2},{3}".F(r.X, r.Y, r.Width, r.Height);
} }
return f.FieldType.IsArray return f.FieldType.IsArray
? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray()) ? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray())
: v.ToString(); : v.ToString();
} }
} }
public class FieldFromYamlKeyAttribute : Attribute { } public class FieldFromYamlKeyAttribute : Attribute { }
} }

View File

@@ -1,155 +1,155 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
[Flags] [Flags]
enum SoundFlags enum SoundFlags
{ {
Stereo = 0x1, Stereo = 0x1,
_16Bit = 0x2, _16Bit = 0x2,
} }
enum SoundFormat enum SoundFormat
{ {
WestwoodCompressed = 1, WestwoodCompressed = 1,
ImaAdpcm = 99, ImaAdpcm = 99,
} }
struct Chunk struct Chunk
{ {
public int CompressedSize; public int CompressedSize;
public int OutputSize; public int OutputSize;
public static Chunk Read(BinaryReader r) public static Chunk Read(BinaryReader r)
{ {
Chunk c; Chunk c;
c.CompressedSize = r.ReadUInt16(); c.CompressedSize = r.ReadUInt16();
c.OutputSize = r.ReadUInt16(); c.OutputSize = r.ReadUInt16();
if (0xdeaf != r.ReadUInt32()) if (0xdeaf != r.ReadUInt32())
throw new InvalidDataException("Chunk header is bogus"); throw new InvalidDataException("Chunk header is bogus");
return c; return c;
} }
} }
public static class AudLoader public static class AudLoader
{ {
static int[] IndexAdjust = { -1, -1, -1, -1, 2, 4, 6, 8 }; static int[] IndexAdjust = { -1, -1, -1, -1, 2, 4, 6, 8 };
static int[] StepTable = { static int[] StepTable = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 7, 8, 9, 10, 11, 12, 13, 14, 16,
17, 19, 21, 23, 25, 28, 31, 34, 37, 17, 19, 21, 23, 25, 28, 31, 34, 37,
41, 45, 50, 55, 60, 66, 73, 80, 88, 41, 45, 50, 55, 60, 66, 73, 80, 88,
97, 107, 118, 130, 143, 157, 173, 190, 209, 97, 107, 118, 130, 143, 157, 173, 190, 209,
230, 253, 279, 307, 337, 371, 408, 449, 494, 230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166, 544, 598, 658, 724, 796, 876, 963, 1060, 1166,
1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749,
3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };
static short DecodeSample(byte b, ref int index, ref int current) static short DecodeSample(byte b, ref int index, ref int current)
{ {
var sb = (b & 8) != 0; var sb = (b & 8) != 0;
b &= 7; b &= 7;
var delta = (StepTable[index] * b) / 4 + StepTable[index] / 8; var delta = (StepTable[index] * b) / 4 + StepTable[index] / 8;
if (sb) delta = -delta; if (sb) delta = -delta;
current += delta; current += delta;
if (current > short.MaxValue) current = short.MaxValue; if (current > short.MaxValue) current = short.MaxValue;
if (current < short.MinValue) current = short.MinValue; if (current < short.MinValue) current = short.MinValue;
index += IndexAdjust[b]; index += IndexAdjust[b];
if (index < 0) index = 0; if (index < 0) index = 0;
if (index > 88) index = 88; if (index > 88) index = 88;
return (short)current; return (short)current;
} }
public static byte[] LoadSound(byte[] raw, ref int index) public static byte[] LoadSound(byte[] raw, ref int index)
{ {
var br = new BinaryReader(new MemoryStream(raw)); var br = new BinaryReader(new MemoryStream(raw));
var dataSize = raw.Length; var dataSize = raw.Length;
var outputSize = raw.Length * 4; var outputSize = raw.Length * 4;
var output = new byte[outputSize]; var output = new byte[outputSize];
var offset = 0; var offset = 0;
var currentSample = 0; var currentSample = 0;
while (dataSize-- > 0) while (dataSize-- > 0)
{ {
var b = br.ReadByte(); var b = br.ReadByte();
var t = DecodeSample(b, ref index, ref currentSample); var t = DecodeSample(b, ref index, ref currentSample);
output[offset++] = (byte)t; output[offset++] = (byte)t;
output[offset++] = (byte)(t >> 8); output[offset++] = (byte)(t >> 8);
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample); t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
output[offset++] = (byte)t; output[offset++] = (byte)t;
output[offset++] = (byte)(t >> 8); output[offset++] = (byte)(t >> 8);
} }
return output; return output;
} }
public static float SoundLength(Stream s) public static float SoundLength(Stream s)
{ {
var br = new BinaryReader(s); var br = new BinaryReader(s);
var sampleRate = br.ReadUInt16(); var sampleRate = br.ReadUInt16();
/*var dataSize = */ br.ReadInt32(); /*var dataSize = */ br.ReadInt32();
var outputSize = br.ReadInt32(); var outputSize = br.ReadInt32();
var flags = (SoundFlags) br.ReadByte(); var flags = (SoundFlags) br.ReadByte();
var samples = outputSize; var samples = outputSize;
if (0 != (flags & SoundFlags.Stereo)) samples /= 2; if (0 != (flags & SoundFlags.Stereo)) samples /= 2;
if (0 != (flags & SoundFlags._16Bit)) samples /= 2; if (0 != (flags & SoundFlags._16Bit)) samples /= 2;
return samples / sampleRate; return samples / sampleRate;
} }
public static byte[] LoadSound(Stream s) public static byte[] LoadSound(Stream s)
{ {
var br = new BinaryReader(s); var br = new BinaryReader(s);
/*var sampleRate =*/ br.ReadUInt16(); /*var sampleRate =*/ br.ReadUInt16();
var dataSize = br.ReadInt32(); var dataSize = br.ReadInt32();
var outputSize = br.ReadInt32(); var outputSize = br.ReadInt32();
/*var flags = (SoundFlags)*/ br.ReadByte(); /*var flags = (SoundFlags)*/ br.ReadByte();
/*var format = (SoundFormat)*/ br.ReadByte(); /*var format = (SoundFormat)*/ br.ReadByte();
var output = new byte[outputSize]; var output = new byte[outputSize];
var offset = 0; var offset = 0;
var index = 0; var index = 0;
var currentSample = 0; var currentSample = 0;
while (dataSize > 0) while (dataSize > 0)
{ {
var chunk = Chunk.Read(br); var chunk = Chunk.Read(br);
for (int n = 0; n < chunk.CompressedSize; n++) for (int n = 0; n < chunk.CompressedSize; n++)
{ {
var b = br.ReadByte(); var b = br.ReadByte();
var t = DecodeSample(b, ref index, ref currentSample); var t = DecodeSample(b, ref index, ref currentSample);
output[offset++] = (byte)t; output[offset++] = (byte)t;
output[offset++] = (byte)(t >> 8); output[offset++] = (byte)(t >> 8);
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample); t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
output[offset++] = (byte)t; output[offset++] = (byte)t;
output[offset++] = (byte)(t >> 8); output[offset++] = (byte)(t >> 8);
} }
dataSize -= 8 + chunk.CompressedSize; dataSize -= 8 + chunk.CompressedSize;
} }
return output; return output;
} }
} }
} }

View File

@@ -1,274 +1,274 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
* *
* This file is based on the blast routines (version 1.1 by Mark Adler) * This file is based on the blast routines (version 1.1 by Mark Adler)
* included in zlib/contrib * included in zlib/contrib
*/ */
#endregion #endregion
using System; using System;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class Blast public static class Blast
{ {
public static readonly int MAXBITS = 13; // maximum code length public static readonly int MAXBITS = 13; // maximum code length
public static readonly int MAXWIN = 4096; // maximum window size public static readonly int MAXWIN = 4096; // maximum window size
static byte[] litlen = new byte[] { static byte[] litlen = new byte[] {
11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
10, 8, 12, 10, 12, 10, 8, 23, 8, 9, 10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24,
12, 11, 7, 9, 11, 12, 6, 7, 22, 5, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 7, 24, 6, 11, 9, 6, 7, 22, 7, 11,
38, 7, 9, 8, 25, 11, 8, 11, 9, 12, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 8, 12, 5, 38, 5, 38, 5, 11, 7, 5,
6, 21, 6, 10, 53, 8, 7, 24, 10, 27, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 44, 253, 253, 253, 252, 252, 252, 13, 12, 45,
12, 45, 12, 61, 12, 45, 44, 173 12, 45, 12, 61, 12, 45, 44, 173
}; };
// bit lengths of length codes 0..15 // bit lengths of length codes 0..15
static byte[] lenlen = new byte[] { 2, 35, 36, 53, 38, 23 }; static byte[] lenlen = new byte[] { 2, 35, 36, 53, 38, 23 };
// bit lengths of distance codes 0..63 // bit lengths of distance codes 0..63
static byte[] distlen = new byte[] { 2, 20, 53, 230, 247, 151, 248 }; static byte[] distlen = new byte[] { 2, 20, 53, 230, 247, 151, 248 };
// base for length codes // base for length codes
static short[] lengthbase = new short[] { static short[] lengthbase = new short[] {
3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 3, 2, 4, 5, 6, 7, 8, 9, 10, 12,
16, 24, 40, 72, 136, 264 16, 24, 40, 72, 136, 264
}; };
// extra bits for length codes // extra bits for length codes
static byte[] extra = new byte[] { static byte[] extra = new byte[] {
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
3, 4, 5, 6, 7, 8 3, 4, 5, 6, 7, 8
}; };
static Huffman litcode = new Huffman(litlen, litlen.Length, 256); static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16); static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
static Huffman distcode = new Huffman(distlen, distlen.Length, 64); static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
// Decode PKWare Compression Library stream. // Decode PKWare Compression Library stream.
public static byte[] Decompress(byte[] src) public static byte[] Decompress(byte[] src)
{ {
BitReader br = new BitReader(src); BitReader br = new BitReader(src);
// Are literals coded? // Are literals coded?
int coded = br.ReadBits(8); int coded = br.ReadBits(8);
if (coded < 0 || coded > 1) if (coded < 0 || coded > 1)
throw new NotImplementedException("Invalid datastream"); throw new NotImplementedException("Invalid datastream");
bool EncodedLiterals = (coded == 1); bool EncodedLiterals = (coded == 1);
// log2(dictionary size) - 6 // log2(dictionary size) - 6
int dict = br.ReadBits(8); int dict = br.ReadBits(8);
if (dict < 4 || dict > 6) if (dict < 4 || dict > 6)
throw new InvalidDataException("Invalid dictionary size"); throw new InvalidDataException("Invalid dictionary size");
// output state // output state
ushort next = 0; // index of next write location in out[] ushort next = 0; // index of next write location in out[]
bool first = true; // true to check distances (for first 4K) bool first = true; // true to check distances (for first 4K)
byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window
var ms = new MemoryStream(); var ms = new MemoryStream();
// decode literals and length/distance pairs // decode literals and length/distance pairs
do do
{ {
// length/distance pair // length/distance pair
if (br.ReadBits(1) == 1) if (br.ReadBits(1) == 1)
{ {
// Length // Length
int symbol = Decode(lencode, br); int symbol = Decode(lencode, br);
int len = lengthbase[symbol] + br.ReadBits(extra[symbol]); int len = lengthbase[symbol] + br.ReadBits(extra[symbol]);
if (len == 519) // Magic number for "done" if (len == 519) // Magic number for "done"
{ {
for (int i = 0; i < next; i++) for (int i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]); ms.WriteByte(outBuffer[i]);
break; break;
} }
// Distance // Distance
symbol = len == 2 ? 2 : dict; symbol = len == 2 ? 2 : dict;
int dist = Decode(distcode, br) << symbol; int dist = Decode(distcode, br) << symbol;
dist += br.ReadBits(symbol); dist += br.ReadBits(symbol);
dist++; dist++;
if (first && dist > next) if (first && dist > next)
throw new InvalidDataException("Attempt to jump before data"); throw new InvalidDataException("Attempt to jump before data");
// copy length bytes from distance bytes back // copy length bytes from distance bytes back
do do
{ {
int dest = next; int dest = next;
int source = dest - dist; int source = dest - dist;
int copy = MAXWIN; int copy = MAXWIN;
if (next < dist) if (next < dist)
{ {
source += copy; source += copy;
copy = dist; copy = dist;
} }
copy -= next; copy -= next;
if (copy > len) if (copy > len)
copy = len; copy = len;
len -= copy; len -= copy;
next += (ushort)copy; next += (ushort)copy;
Array.Copy(outBuffer, source, outBuffer, dest, copy); Array.Copy(outBuffer, source, outBuffer, dest, copy);
// Flush window to outstream // Flush window to outstream
if (next == MAXWIN) if (next == MAXWIN)
{ {
for (int i = 0; i < next; i++) for (int i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]); ms.WriteByte(outBuffer[i]);
next = 0; next = 0;
first = false; first = false;
} }
} while (len != 0); } while (len != 0);
} }
else // literal value else // literal value
{ {
int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8); int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
outBuffer[next++] = (byte)symbol; outBuffer[next++] = (byte)symbol;
if (next == MAXWIN) if (next == MAXWIN)
{ {
for (int i = 0; i < next; i++) for (int i = 0; i < next; i++)
ms.WriteByte(outBuffer[i]); ms.WriteByte(outBuffer[i]);
next = 0; next = 0;
first = false; first = false;
} }
} }
} while (true); } while (true);
return ms.ToArray(); return ms.ToArray();
} }
// Decode a code using huffman table h. // Decode a code using huffman table h.
private static int Decode(Huffman h, BitReader br) private static int Decode(Huffman h, BitReader br)
{ {
int code = 0; // len bits being decoded int code = 0; // len bits being decoded
int first = 0; // first code of length len int first = 0; // first code of length len
int index = 0; // index of first code of length len in symbol table int index = 0; // index of first code of length len in symbol table
short next = 1; short next = 1;
while (true) while (true)
{ {
code |= br.ReadBits(1) ^ 1; // invert code code |= br.ReadBits(1) ^ 1; // invert code
int count = h.Count[next++]; int count = h.Count[next++];
if (code < first + count) if (code < first + count)
return h.Symbol[index + (code - first)]; return h.Symbol[index + (code - first)];
index += count; index += count;
first += count; first += count;
first <<= 1; first <<= 1;
code <<= 1; code <<= 1;
} }
} }
} }
class BitReader class BitReader
{ {
readonly byte[] src; readonly byte[] src;
int offset = 0; int offset = 0;
int bitBuffer = 0; int bitBuffer = 0;
int bitCount = 0; int bitCount = 0;
public BitReader(byte[] src) public BitReader(byte[] src)
{ {
this.src = src; this.src = src;
} }
public int ReadBits(int count) public int ReadBits(int count)
{ {
int ret = 0; int ret = 0;
int filled = 0; int filled = 0;
while (filled < count) while (filled < count)
{ {
if (bitCount == 0) if (bitCount == 0)
{ {
bitBuffer = src[offset++]; bitBuffer = src[offset++];
bitCount = 8; bitCount = 8;
} }
ret |= (bitBuffer & 1) << filled; ret |= (bitBuffer & 1) << filled;
bitBuffer >>= 1; bitBuffer >>= 1;
bitCount--; bitCount--;
filled++; filled++;
} }
return ret; return ret;
} }
} }
/* /*
* Given a list of repeated code lengths rep[0..n-1], where each byte is a * Given a list of repeated code lengths rep[0..n-1], where each byte is a
* count (high four bits + 1) and a code length (low four bits), generate the * count (high four bits + 1) and a code length (low four bits), generate the
* list of code lengths. This compaction reduces the size of the object code. * list of code lengths. This compaction reduces the size of the object code.
* Then given the list of code lengths length[0..n-1] representing a canonical * Then given the list of code lengths length[0..n-1] representing a canonical
* Huffman code for n symbols, construct the tables required to decode those * Huffman code for n symbols, construct the tables required to decode those
* codes. Those tables are the number of codes of each length, and the symbols * codes. Those tables are the number of codes of each length, and the symbols
* sorted by length, retaining their original order within each length. * sorted by length, retaining their original order within each length.
*/ */
class Huffman class Huffman
{ {
public short[] Count; // number of symbols of each length public short[] Count; // number of symbols of each length
public short[] Symbol; // canonically ordered symbols public short[] Symbol; // canonically ordered symbols
public Huffman(byte[] rep, int n, short SymbolCount) public Huffman(byte[] rep, int n, short SymbolCount)
{ {
short[] length = new short[256]; // code lengths short[] length = new short[256]; // code lengths
int s = 0; // current symbol int s = 0; // current symbol
// convert compact repeat counts into symbol bit length list // convert compact repeat counts into symbol bit length list
foreach (byte code in rep) foreach (byte code in rep)
{ {
int num = (code >> 4) + 1; // Number of codes (top four bits plus 1) int num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
byte len = (byte)(code & 15); // Code length (low four bits) byte len = (byte)(code & 15); // Code length (low four bits)
do do
{ {
length[s++] = len; length[s++] = len;
} while (--num > 0); } while (--num > 0);
} }
n = s; n = s;
// count number of codes of each length // count number of codes of each length
Count = new short[Blast.MAXBITS + 1]; Count = new short[Blast.MAXBITS + 1];
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
Count[length[i]]++; Count[length[i]]++;
// no codes! // no codes!
if (Count[0] == n) if (Count[0] == n)
return; return;
// check for an over-subscribed or incomplete set of lengths // check for an over-subscribed or incomplete set of lengths
int left = 1; // one possible code of zero length int left = 1; // one possible code of zero length
for (int len = 1; len <= Blast.MAXBITS; len++) for (int len = 1; len <= Blast.MAXBITS; len++)
{ {
left <<= 1; left <<= 1;
// one more bit, double codes left // one more bit, double codes left
left -= Count[len]; left -= Count[len];
// deduct count from possible codes // deduct count from possible codes
if (left < 0) if (left < 0)
throw new InvalidDataException ("over subscribed code set"); throw new InvalidDataException ("over subscribed code set");
} }
// generate offsets into symbol table for each length for sorting // generate offsets into symbol table for each length for sorting
short[] offs = new short[Blast.MAXBITS + 1]; short[] offs = new short[Blast.MAXBITS + 1];
for (int len = 1; len < Blast.MAXBITS; len++) for (int len = 1; len < Blast.MAXBITS; len++)
offs[len + 1] = (short)(offs[len] + Count[len]); offs[len + 1] = (short)(offs[len] + Count[len]);
// put symbols in table sorted by length, by symbol order within each length // put symbols in table sorted by length, by symbol order within each length
Symbol = new short[SymbolCount]; Symbol = new short[SymbolCount];
for (short i = 0; i < n; i++) for (short i = 0; i < n; i++)
if (length[i] != 0) if (length[i] != 0)
Symbol[offs[length[i]]++] = i; Symbol[offs[length[i]]++] = i;
} }
} }
} }

View File

@@ -1,406 +1,406 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
class Blowfish class Blowfish
{ {
public Blowfish(byte[] key) public Blowfish(byte[] key)
{ {
for (int i = 0, j = 0; i < 18; ++i) for (int i = 0, j = 0; i < 18; ++i)
{ {
uint a = key[j++ % key.Length]; uint a = key[j++ % key.Length];
uint b = key[j++ % key.Length]; uint b = key[j++ % key.Length];
uint c = key[j++ % key.Length]; uint c = key[j++ % key.Length];
uint d = key[j++ % key.Length]; uint d = key[j++ % key.Length];
m_p[i] ^= a << 24 | b << 16 | c << 8 | d; m_p[i] ^= a << 24 | b << 16 | c << 8 | d;
} }
uint l = 0, r = 0; uint l = 0, r = 0;
for (int i = 0; i < 18; ) for (int i = 0; i < 18; )
{ {
Encrypt(ref l, ref r); Encrypt(ref l, ref r);
m_p[i++] = l; m_p[i++] = l;
m_p[i++] = r; m_p[i++] = r;
} }
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
for (int j = 0; j < 256; ) for (int j = 0; j < 256; )
{ {
Encrypt(ref l, ref r); Encrypt(ref l, ref r);
m_s[i, j++] = l; m_s[i, j++] = l;
m_s[i, j++] = r; m_s[i, j++] = r;
} }
} }
public uint[] Encrypt(uint[] data) { return RunCipher(data, Encrypt); } public uint[] Encrypt(uint[] data) { return RunCipher(data, Encrypt); }
public uint[] Decrypt(uint[] data) { return RunCipher(data, Decrypt); } public uint[] Decrypt(uint[] data) { return RunCipher(data, Decrypt); }
delegate void CipherFunc( ref uint a, ref uint b ); delegate void CipherFunc( ref uint a, ref uint b );
uint[] RunCipher(uint[] data, CipherFunc f) uint[] RunCipher(uint[] data, CipherFunc f)
{ {
uint[] result = new uint[data.Length]; uint[] result = new uint[data.Length];
int size = data.Length / 2; int size = data.Length / 2;
int i = 0; int i = 0;
while (size-- > 0) while (size-- > 0)
{ {
uint a = SwapBytes(data[i]); uint a = SwapBytes(data[i]);
uint b = SwapBytes(data[i+1]); uint b = SwapBytes(data[i+1]);
f(ref a, ref b); f(ref a, ref b);
result[i++] = SwapBytes(a); result[i++] = SwapBytes(a);
result[i++] = SwapBytes(b); result[i++] = SwapBytes(b);
} }
return result; return result;
} }
void Encrypt(ref uint a, ref uint b) void Encrypt(ref uint a, ref uint b)
{ {
uint _a = a, _b = b; uint _a = a, _b = b;
_a ^= m_p[0]; _a ^= m_p[0];
bool x = false; bool x = false;
for( int i = 1; i <= 16; i++, x ^= true) for( int i = 1; i <= 16; i++, x ^= true)
{ {
if (x) if (x)
Round(ref _a, _b, i); Round(ref _a, _b, i);
else else
Round(ref _b, _a, i); Round(ref _b, _a, i);
} }
_b ^= m_p[17]; _b ^= m_p[17];
a = _b; a = _b;
b = _a; b = _a;
} }
void Decrypt(ref uint a, ref uint b) void Decrypt(ref uint a, ref uint b)
{ {
uint _a = a, _b = b; uint _a = a, _b = b;
_a ^= m_p[17]; _a ^= m_p[17];
bool x = false; bool x = false;
for (int i = 16; i >= 1; i--, x ^= true) for (int i = 16; i >= 1; i--, x ^= true)
{ {
if (x) if (x)
Round(ref _a, _b, i); Round(ref _a, _b, i);
else else
Round(ref _b, _a, i); Round(ref _b, _a, i);
} }
_b ^= m_p[0]; _b ^= m_p[0];
a = _b; a = _b;
b = _a; b = _a;
} }
uint S(uint x, int i) uint S(uint x, int i)
{ {
return m_s[i, (x >> ((3 - i) << 3)) & 0xff]; return m_s[i, (x >> ((3 - i) << 3)) & 0xff];
} }
uint bf_f(uint x) uint bf_f(uint x)
{ {
return ((S(x, 0) + S(x, 1)) ^ S(x, 2)) + S(x, 3); return ((S(x, 0) + S(x, 1)) ^ S(x, 2)) + S(x, 3);
} }
void Round(ref uint a, uint b, int n) void Round(ref uint a, uint b, int n)
{ {
a ^= bf_f(b) ^ m_p[n]; a ^= bf_f(b) ^ m_p[n];
} }
uint SwapBytes(uint i) uint SwapBytes(uint i)
{ {
i = (i << 16) | (i >> 16); i = (i << 16) | (i >> 16);
i = ((i << 8) & 0xff00ff00) | ((i >> 8) & 0x00ff00ff); i = ((i << 8) & 0xff00ff00) | ((i >> 8) & 0x00ff00ff);
return i; return i;
} }
uint[] m_p = new uint[] { uint[] m_p = new uint[] {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b 0x9216d5d9, 0x8979fb1b
}; };
uint[,] m_s = new uint[,] { uint[,] m_s = new uint[,] {
{ {
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
}, },
{ {
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
}, },
{ {
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
}, },
{ {
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
} }
}; };
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,36 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class Format2 public static class Format2
{ {
public static int DecodeInto(byte[] src, byte[] dest) public static int DecodeInto(byte[] src, byte[] dest)
{ {
FastByteReader r = new FastByteReader(src); FastByteReader r = new FastByteReader(src);
int i = 0; int i = 0;
while (!r.Done()) while (!r.Done())
{ {
byte cmd = r.ReadByte(); byte cmd = r.ReadByte();
if (cmd == 0) if (cmd == 0)
{ {
byte count = r.ReadByte(); byte count = r.ReadByte();
while (count-- > 0) while (count-- > 0)
dest[i++] = 0; dest[i++] = 0;
} }
else else
dest[i++] = cmd; dest[i++] = cmd;
} }
return i; return i;
} }
} }
} }

View File

@@ -1,78 +1,78 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class Format40 public static class Format40
{ {
public static int DecodeInto( byte[] src, byte[] dest ) public static int DecodeInto( byte[] src, byte[] dest )
{ {
var ctx = new FastByteReader(src); var ctx = new FastByteReader(src);
int destIndex = 0; int destIndex = 0;
while( true ) while( true )
{ {
byte i = ctx.ReadByte(); byte i = ctx.ReadByte();
if( ( i & 0x80 ) == 0 ) if( ( i & 0x80 ) == 0 )
{ {
int count = i & 0x7F; int count = i & 0x7F;
if( count == 0 ) if( count == 0 )
{ {
// case 6 // case 6
count = ctx.ReadByte(); count = ctx.ReadByte();
byte value = ctx.ReadByte(); byte value = ctx.ReadByte();
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] ^= value; dest[ destIndex ] ^= value;
} }
else else
{ {
// case 5 // case 5
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[destIndex] ^= ctx.ReadByte(); dest[destIndex] ^= ctx.ReadByte();
} }
} }
else else
{ {
int count = i & 0x7F; int count = i & 0x7F;
if( count == 0 ) if( count == 0 )
{ {
count = ctx.ReadWord(); count = ctx.ReadWord();
if( count == 0 ) if( count == 0 )
return destIndex; return destIndex;
if( ( count & 0x8000 ) == 0 ) if( ( count & 0x8000 ) == 0 )
{ {
// case 2 // case 2
destIndex += ( count & 0x7FFF ); destIndex += ( count & 0x7FFF );
} }
else if( ( count & 0x4000 ) == 0 ) else if( ( count & 0x4000 ) == 0 )
{ {
// case 3 // case 3
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ ) for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
dest[destIndex] ^= ctx.ReadByte(); dest[destIndex] ^= ctx.ReadByte();
} }
else else
{ {
// case 4 // case 4
byte value = ctx.ReadByte(); byte value = ctx.ReadByte();
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ ) for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
dest[ destIndex ] ^= value; dest[ destIndex ] ^= value;
} }
} }
else else
{ {
// case 1 // case 1
destIndex += count; destIndex += count;
} }
} }
} }
} }
} }
} }

View File

@@ -1,150 +1,150 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
class FastByteReader class FastByteReader
{ {
readonly byte[] src; readonly byte[] src;
int offset = 0; int offset = 0;
public FastByteReader(byte[] src) public FastByteReader(byte[] src)
{ {
this.src = src; this.src = src;
} }
public bool Done() { return offset >= src.Length; } public bool Done() { return offset >= src.Length; }
public byte ReadByte() { return src[offset++]; } public byte ReadByte() { return src[offset++]; }
public int ReadWord() public int ReadWord()
{ {
int x = ReadByte(); int x = ReadByte();
return x | (ReadByte() << 8); return x | (ReadByte() << 8);
} }
public void CopyTo(byte[] dest, int offset, int count) public void CopyTo(byte[] dest, int offset, int count)
{ {
Array.Copy(src, this.offset, dest, offset, count); Array.Copy(src, this.offset, dest, offset, count);
this.offset += count; this.offset += count;
} }
public int Remaining() { return src.Length - offset; } public int Remaining() { return src.Length - offset; }
} }
public static class Format80 public static class Format80
{ {
static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count ) static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count )
{ {
if( srcIndex > destIndex ) if( srcIndex > destIndex )
throw new NotImplementedException( string.Format( "srcIndex > destIndex {0} {1}", srcIndex, destIndex ) ); throw new NotImplementedException( string.Format( "srcIndex > destIndex {0} {1}", srcIndex, destIndex ) );
if( destIndex - srcIndex == 1 ) if( destIndex - srcIndex == 1 )
{ {
for( int i = 0 ; i < count ; i++ ) for( int i = 0 ; i < count ; i++ )
dest[ destIndex + i ] = dest[ destIndex - 1 ]; dest[ destIndex + i ] = dest[ destIndex - 1 ];
} }
else else
{ {
for( int i = 0 ; i < count ; i++ ) for( int i = 0 ; i < count ; i++ )
dest[ destIndex + i ] = dest[ srcIndex + i ]; dest[ destIndex + i ] = dest[ srcIndex + i ];
} }
} }
public static int DecodeInto( byte[] src, byte[] dest ) public static int DecodeInto( byte[] src, byte[] dest )
{ {
var ctx = new FastByteReader(src); var ctx = new FastByteReader(src);
int destIndex = 0; int destIndex = 0;
while( true ) while( true )
{ {
byte i = ctx.ReadByte(); byte i = ctx.ReadByte();
if( ( i & 0x80 ) == 0 ) if( ( i & 0x80 ) == 0 )
{ {
// case 2 // case 2
byte secondByte = ctx.ReadByte(); byte secondByte = ctx.ReadByte();
int count = ( ( i & 0x70 ) >> 4 ) + 3; int count = ( ( i & 0x70 ) >> 4 ) + 3;
int rpos = ( ( i & 0xf ) << 8 ) + secondByte; int rpos = ( ( i & 0xf ) << 8 ) + secondByte;
ReplicatePrevious( dest, destIndex, destIndex - rpos, count ); ReplicatePrevious( dest, destIndex, destIndex - rpos, count );
destIndex += count; destIndex += count;
} }
else if( ( i & 0x40 ) == 0 ) else if( ( i & 0x40 ) == 0 )
{ {
// case 1 // case 1
int count = i & 0x3F; int count = i & 0x3F;
if( count == 0 ) if( count == 0 )
return destIndex; return destIndex;
ctx.CopyTo( dest, destIndex, count ); ctx.CopyTo( dest, destIndex, count );
destIndex += count; destIndex += count;
} }
else else
{ {
int count3 = i & 0x3F; int count3 = i & 0x3F;
if( count3 == 0x3E ) if( count3 == 0x3E )
{ {
// case 4 // case 4
int count = ctx.ReadWord(); int count = ctx.ReadWord();
byte color = ctx.ReadByte(); byte color = ctx.ReadByte();
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] = color; dest[ destIndex ] = color;
} }
else if( count3 == 0x3F ) else if( count3 == 0x3F )
{ {
// case 5 // case 5
int count = ctx.ReadWord(); int count = ctx.ReadWord();
int srcIndex = ctx.ReadWord(); int srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex ) if( srcIndex >= destIndex )
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) ); throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] = dest[ srcIndex++ ]; dest[ destIndex ] = dest[ srcIndex++ ];
} }
else else
{ {
// case 3 // case 3
int count = count3 + 3; int count = count3 + 3;
int srcIndex = ctx.ReadWord(); int srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex ) if( srcIndex >= destIndex )
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) ); throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
for( int end = destIndex + count ; destIndex < end ; destIndex++ ) for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] = dest[ srcIndex++ ]; dest[ destIndex ] = dest[ srcIndex++ ];
} }
} }
} }
} }
public static byte[] Encode(byte[] src) public static byte[] Encode(byte[] src)
{ {
/* quick & dirty format80 encoder -- only uses raw copy operator, terminated with a zero-run. */ /* quick & dirty format80 encoder -- only uses raw copy operator, terminated with a zero-run. */
/* this does not produce good compression, but it's valid format80 */ /* this does not produce good compression, but it's valid format80 */
var ctx = new FastByteReader(src); var ctx = new FastByteReader(src);
var ms = new MemoryStream(); var ms = new MemoryStream();
do do
{ {
var len = Math.Min(ctx.Remaining(), 0x3F); var len = Math.Min(ctx.Remaining(), 0x3F);
ms.WriteByte((byte)(0x80 | len)); ms.WriteByte((byte)(0x80 | len));
while (len-- > 0) while (len-- > 0)
ms.WriteByte(ctx.ReadByte()); ms.WriteByte(ctx.ReadByte());
} }
while (!ctx.Done()); while (!ctx.Done());
ms.WriteByte(0x80); // terminator -- 0-length run. ms.WriteByte(0x80); // terminator -- 0-length run.
return ms.ToArray(); return ms.ToArray();
} }
} }
} }

View File

@@ -1,151 +1,151 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class IniFile public class IniFile
{ {
Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>(); Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>();
public IniFile( Stream s ) public IniFile( Stream s )
{ {
Load( s ); Load( s );
} }
public IniFile( params Stream[] streams ) public IniFile( params Stream[] streams )
{ {
foreach( var s in streams ) foreach( var s in streams )
Load( s ); Load( s );
} }
public void Load( Stream s ) public void Load( Stream s )
{ {
StreamReader reader = new StreamReader( s ); StreamReader reader = new StreamReader( s );
IniSection currentSection = null; IniSection currentSection = null;
while( !reader.EndOfStream ) while( !reader.EndOfStream )
{ {
string line = reader.ReadLine(); string line = reader.ReadLine();
if( line.Length == 0 ) continue; if( line.Length == 0 ) continue;
switch( line[ 0 ] ) switch( line[ 0 ] )
{ {
case ';': break; case ';': break;
case '[': currentSection = ProcessSection( line ); break; case '[': currentSection = ProcessSection( line ); break;
default: ProcessEntry( line, currentSection ); break; default: ProcessEntry( line, currentSection ); break;
} }
} }
} }
Regex sectionPattern = new Regex( @"^\[([^]]*)\]" ); Regex sectionPattern = new Regex( @"^\[([^]]*)\]" );
IniSection ProcessSection( string line ) IniSection ProcessSection( string line )
{ {
Match m = sectionPattern.Match( line ); Match m = sectionPattern.Match( line );
if( m == null || !m.Success ) if( m == null || !m.Success )
return null; return null;
string sectionName = m.Groups[ 1 ].Value.ToLowerInvariant(); string sectionName = m.Groups[ 1 ].Value.ToLowerInvariant();
IniSection ret; IniSection ret;
if( !sections.TryGetValue( sectionName, out ret ) ) if( !sections.TryGetValue( sectionName, out ret ) )
sections.Add( sectionName, ret = new IniSection( sectionName ) ); sections.Add( sectionName, ret = new IniSection( sectionName ) );
return ret; return ret;
} }
bool ProcessEntry( string line, IniSection currentSection ) bool ProcessEntry( string line, IniSection currentSection )
{ {
int comment = line.IndexOf( ';' ); int comment = line.IndexOf( ';' );
if( comment >= 0 ) if( comment >= 0 )
line = line.Substring( 0, comment ); line = line.Substring( 0, comment );
line = line.Trim(); line = line.Trim();
if( line.Length == 0 ) if( line.Length == 0 )
return false; return false;
var key = line; var key = line;
var value = ""; var value = "";
int eq = line.IndexOf( '=' ); int eq = line.IndexOf( '=' );
if( eq >= 0 ) if( eq >= 0 )
{ {
key = line.Substring( 0, eq ); key = line.Substring( 0, eq );
value = line.Substring( eq + 1, line.Length - eq - 1 ); value = line.Substring( eq + 1, line.Length - eq - 1 );
} }
if( currentSection == null ) if( currentSection == null )
throw new InvalidOperationException( "No current INI section" ); throw new InvalidOperationException( "No current INI section" );
if( !currentSection.Contains( key ) ) if( !currentSection.Contains( key ) )
currentSection.Add( key, value ); currentSection.Add( key, value );
return true; return true;
} }
public IniSection GetSection( string s ) public IniSection GetSection( string s )
{ {
return GetSection( s, false ); return GetSection( s, false );
} }
public IniSection GetSection( string s, bool allowFail ) public IniSection GetSection( string s, bool allowFail )
{ {
IniSection section; IniSection section;
if( sections.TryGetValue( s.ToLowerInvariant(), out section ) ) if( sections.TryGetValue( s.ToLowerInvariant(), out section ) )
return section; return section;
if( allowFail ) if( allowFail )
return new IniSection( s ); return new IniSection( s );
throw new InvalidOperationException( "Section does not exist in map or rules: " + s ); throw new InvalidOperationException( "Section does not exist in map or rules: " + s );
} }
public IEnumerable<IniSection> Sections { get { return sections.Values; } } public IEnumerable<IniSection> Sections { get { return sections.Values; } }
} }
public class IniSection : IEnumerable<KeyValuePair<string, string>> public class IniSection : IEnumerable<KeyValuePair<string, string>>
{ {
public string Name { get; private set; } public string Name { get; private set; }
Dictionary<string, string> values = new Dictionary<string, string>(); Dictionary<string, string> values = new Dictionary<string, string>();
public IniSection( string name ) public IniSection( string name )
{ {
Name = name; Name = name;
} }
public void Add( string key, string value ) public void Add( string key, string value )
{ {
values[key] = value; values[key] = value;
} }
public bool Contains( string key ) public bool Contains( string key )
{ {
return values.ContainsKey( key ); return values.ContainsKey( key );
} }
public string GetValue( string key, string defaultValue ) public string GetValue( string key, string defaultValue )
{ {
string s; string s;
return values.TryGetValue( key, out s ) ? s : defaultValue; return values.TryGetValue( key, out s ) ? s : defaultValue;
} }
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{ {
return values.GetEnumerator(); return values.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
} }
} }

View File

@@ -1,206 +1,206 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class FileSystem public static class FileSystem
{ {
static List<IFolder> mountedFolders = new List<IFolder>(); static List<IFolder> mountedFolders = new List<IFolder>();
public static string SpecialPackageRoot = ""; public static string SpecialPackageRoot = "";
static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() ); static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
static void MountInner(IFolder folder) 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]; var l = allFiles[hash];
if( !l.Contains( folder ) ) if( !l.Contains( folder ) )
l.Add( folder ); l.Add( folder );
} }
} }
static int order = 0; static int order = 0;
static IFolder OpenPackage(string filename) static IFolder OpenPackage(string filename)
{ {
return OpenPackage(filename, order++); return OpenPackage(filename, order++);
} }
public static IFolder CreatePackage(string filename, int order, Dictionary<string, byte[]> content) public static IFolder CreatePackage(string filename, int order, Dictionary<string, byte[]> content)
{ {
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
return new MixFile(filename, order, content); return new MixFile(filename, order, content);
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(filename, order, content); return new ZipFile(filename, order, content);
else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(filename, order, content); return new ZipFile(filename, order, content);
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
throw new NotImplementedException("Creating .Z archives is unsupported"); throw new NotImplementedException("Creating .Z archives is unsupported");
else else
return new Folder(filename, order, content); return new Folder(filename, order, content);
} }
public static IFolder OpenPackage(string filename, int order) public static IFolder OpenPackage(string filename, int order)
{ {
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
return new MixFile(filename, order); return new MixFile(filename, order);
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(filename, order); return new ZipFile(filename, order);
else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(filename, order); return new ZipFile(filename, order);
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
return new InstallShieldPackage(filename, order); return new InstallShieldPackage(filename, order);
else else
return new Folder(filename, order); return new Folder(filename, order);
} }
public static void Mount(string name) public static void Mount(string name)
{ {
var optional = name.StartsWith("~"); var optional = name.StartsWith("~");
if (optional) name = name.Substring(1); if (optional) name = name.Substring(1);
// paths starting with $ are relative to SpecialPackageRoot // paths starting with $ are relative to SpecialPackageRoot
if (name.StartsWith("$")) if (name.StartsWith("$"))
name = SpecialPackageRoot+name.Substring(1); name = SpecialPackageRoot+name.Substring(1);
var a = (Action)(() => FileSystem.MountInner(OpenPackage(name))); var a = (Action)(() => FileSystem.MountInner(OpenPackage(name)));
if (optional) if (optional)
try { a(); } try { a(); }
catch { } catch { }
else else
a(); a();
} }
public static void UnmountAll() public static void UnmountAll()
{ {
mountedFolders.Clear(); mountedFolders.Clear();
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() ); allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
} }
public static bool Unmount(IFolder mount) 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) 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(); UnmountAll();
foreach (var dir in manifest.Folders) Mount(dir); foreach (var dir in manifest.Folders) Mount(dir);
foreach (var pkg in manifest.Packages) Mount(pkg); foreach (var pkg in manifest.Packages) Mount(pkg);
} }
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename ) static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
{ {
var folder = index[PackageEntry.HashFilename(filename)] var folder = index[PackageEntry.HashFilename(filename)]
.Where(x => x.Exists(filename)) .Where(x => x.Exists(filename))
.OrderBy(x => x.Priority) .OrderBy(x => x.Priority)
.FirstOrDefault(); .FirstOrDefault();
if (folder != null) if (folder != null)
return folder.GetContent(filename); return folder.GetContent(filename);
return null; return null;
} }
public static Stream Open(string filename) public static Stream Open(string filename)
{ {
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 ) if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
{ {
var ret = GetFromCache( allFiles, filename ); var ret = GetFromCache( allFiles, filename );
if( ret != null ) if( ret != null )
return ret; return ret;
} }
var folder = mountedFolders var folder = mountedFolders
.Where(x => x.Exists(filename)) .Where(x => x.Exists(filename))
.OrderByDescending(x => x.Priority) .OrderByDescending(x => x.Priority)
.FirstOrDefault(); .FirstOrDefault();
if (folder != null) if (folder != null)
return folder.GetContent(filename); return folder.GetContent(filename);
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename ); throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), 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 ) if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
{ {
foreach( var ext in exts ) foreach( var ext in exts )
{ {
var s = GetFromCache( allFiles, filename + ext ); var s = GetFromCache( allFiles, filename + ext );
if( s != null ) if( s != null )
return s; return s;
} }
} }
foreach( var ext in exts ) foreach( var ext in exts )
{ {
foreach( IFolder folder in mountedFolders ) foreach( IFolder folder in mountedFolders )
if (folder.Exists(filename + ext)) if (folder.Exists(filename + ext))
return folder.GetContent( filename + ext ); return folder.GetContent( filename + ext );
} }
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename ); throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
} }
public static bool Exists(string filename) public static bool Exists(string filename)
{ {
foreach (var folder in mountedFolders) foreach (var folder in mountedFolders)
if (folder.Exists(filename)) if (folder.Exists(filename))
return true; return true;
return false; return false;
} }
static Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>(); static Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>();
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e) public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)
{ {
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{ {
if (assembly.FullName == e.Name) if (assembly.FullName == e.Name)
return assembly; return assembly;
} }
string[] frags = e.Name.Split(','); string[] frags = e.Name.Split(',');
var filename = frags[0] + ".dll"; var filename = frags[0] + ".dll";
Assembly a; Assembly a;
if (assemblyCache.TryGetValue(filename, out a)) if (assemblyCache.TryGetValue(filename, out a))
return a; return a;
if (FileSystem.Exists(filename)) if (FileSystem.Exists(filename))
using (Stream s = FileSystem.Open(filename)) using (Stream s = FileSystem.Open(filename))
{ {
byte[] buf = new byte[s.Length]; byte[] buf = new byte[s.Length];
s.Read(buf, 0, buf.Length); s.Read(buf, 0, buf.Length);
a = Assembly.Load(buf); a = Assembly.Load(buf);
assemblyCache.Add(filename, a); assemblyCache.Add(filename, a);
return a; return a;
} }
return null; return null;
} }
} }
} }

View File

@@ -1,73 +1,73 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System; using System;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class Folder : IFolder public class Folder : IFolder
{ {
readonly string path; readonly string path;
int priority; int priority;
// Create a new folder package // Create a new folder package
public Folder(string path, int priority, Dictionary<string, byte[]> contents) public Folder(string path, int priority, Dictionary<string, byte[]> contents)
{ {
this.path = path; this.path = path;
this.priority = priority; this.priority = priority;
if (Directory.Exists(path)) if (Directory.Exists(path))
Directory.Delete(path); Directory.Delete(path);
Write(contents); Write(contents);
} }
public Folder(string path, int priority) public Folder(string path, int priority)
{ {
this.path = path; this.path = path;
this.priority = priority; this.priority = priority;
if (!Directory.Exists(path)) if (!Directory.Exists(path))
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
} }
public Stream GetContent(string filename) public Stream GetContent(string filename)
{ {
try { return File.OpenRead( Path.Combine( path, filename ) ); } try { return File.OpenRead( Path.Combine( path, filename ) ); }
catch { return null; } catch { return null; }
} }
public IEnumerable<uint> AllFileHashes() public IEnumerable<uint> AllFileHashes()
{ {
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) ) foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
yield return PackageEntry.HashFilename( Path.GetFileName(filename) ); yield return PackageEntry.HashFilename( Path.GetFileName(filename) );
} }
public bool Exists(string filename) public bool Exists(string filename)
{ {
return File.Exists(Path.Combine(path,filename)); return File.Exists(Path.Combine(path,filename));
} }
public int Priority public int Priority
{ {
get { return priority; } get { return priority; }
} }
public void Write(Dictionary<string, byte[]> contents) public void Write(Dictionary<string, byte[]> contents)
{ {
foreach (var file in contents) foreach (var file in contents)
using (var dataStream = File.Create(Path.Combine(path, file.Key))) using (var dataStream = File.Create(Path.Combine(path, file.Key)))
using (var writer = new BinaryWriter(dataStream)) using (var writer = new BinaryWriter(dataStream))
writer.Write(file.Value); writer.Write(file.Value);
} }
} }
} }

View File

@@ -1,126 +1,126 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class InstallShieldPackage : IFolder public class InstallShieldPackage : IFolder
{ {
readonly Dictionary<uint, PackageEntry> index = new Dictionary<uint, PackageEntry>(); readonly Dictionary<uint, PackageEntry> index = new Dictionary<uint, PackageEntry>();
readonly Stream s; readonly Stream s;
readonly long dataStart = 255; readonly long dataStart = 255;
int priority; int priority;
public InstallShieldPackage(string filename, int priority) public InstallShieldPackage(string filename, int priority)
{ {
this.priority = priority; this.priority = priority;
s = FileSystem.Open(filename); s = FileSystem.Open(filename);
// Parse package header // Parse package header
BinaryReader reader = new BinaryReader(s); BinaryReader reader = new BinaryReader(s);
uint signature = reader.ReadUInt32(); uint signature = reader.ReadUInt32();
if (signature != 0x8C655D13) if (signature != 0x8C655D13)
throw new InvalidDataException("Not an Installshield package"); throw new InvalidDataException("Not an Installshield package");
reader.ReadBytes(8); reader.ReadBytes(8);
/*var FileCount = */reader.ReadUInt16(); /*var FileCount = */reader.ReadUInt16();
reader.ReadBytes(4); reader.ReadBytes(4);
/*var ArchiveSize = */reader.ReadUInt32(); /*var ArchiveSize = */reader.ReadUInt32();
reader.ReadBytes(19); reader.ReadBytes(19);
var TOCAddress = reader.ReadInt32(); var TOCAddress = reader.ReadInt32();
reader.ReadBytes(4); reader.ReadBytes(4);
var DirCount = reader.ReadUInt16(); var DirCount = reader.ReadUInt16();
// Parse the directory list // Parse the directory list
s.Seek(TOCAddress, SeekOrigin.Begin); s.Seek(TOCAddress, SeekOrigin.Begin);
BinaryReader TOCreader = new BinaryReader(s); BinaryReader TOCreader = new BinaryReader(s);
for (var i = 0; i < DirCount; i++) for (var i = 0; i < DirCount; i++)
ParseDirectory(TOCreader); ParseDirectory(TOCreader);
} }
void ParseDirectory(BinaryReader reader) void ParseDirectory(BinaryReader reader)
{ {
// Parse directory header // Parse directory header
var FileCount = reader.ReadUInt16(); var FileCount = reader.ReadUInt16();
var ChunkSize = reader.ReadUInt16(); var ChunkSize = reader.ReadUInt16();
var NameLength = reader.ReadUInt16(); var NameLength = reader.ReadUInt16();
reader.ReadChars(NameLength); //var DirName = new String(reader.ReadChars(NameLength)); reader.ReadChars(NameLength); //var DirName = new String(reader.ReadChars(NameLength));
// Skip to the end of the chunk // Skip to the end of the chunk
reader.ReadBytes(ChunkSize - NameLength - 6); reader.ReadBytes(ChunkSize - NameLength - 6);
// Parse files // Parse files
for (var i = 0; i < FileCount; i++) for (var i = 0; i < FileCount; i++)
ParseFile(reader); ParseFile(reader);
} }
uint AccumulatedData = 0; uint AccumulatedData = 0;
void ParseFile(BinaryReader reader) void ParseFile(BinaryReader reader)
{ {
reader.ReadBytes(7); reader.ReadBytes(7);
var CompressedSize = reader.ReadUInt32(); var CompressedSize = reader.ReadUInt32();
reader.ReadBytes(12); reader.ReadBytes(12);
var ChunkSize = reader.ReadUInt16(); var ChunkSize = reader.ReadUInt16();
reader.ReadBytes(4); reader.ReadBytes(4);
var NameLength = reader.ReadByte(); var NameLength = reader.ReadByte();
var FileName = new String(reader.ReadChars(NameLength)); var FileName = new String(reader.ReadChars(NameLength));
var hash = PackageEntry.HashFilename(FileName); var hash = PackageEntry.HashFilename(FileName);
index.Add(hash, new PackageEntry(hash,AccumulatedData, CompressedSize)); index.Add(hash, new PackageEntry(hash,AccumulatedData, CompressedSize));
AccumulatedData += CompressedSize; AccumulatedData += CompressedSize;
// Skip to the end of the chunk // Skip to the end of the chunk
reader.ReadBytes(ChunkSize - NameLength - 30); reader.ReadBytes(ChunkSize - NameLength - 30);
} }
public Stream GetContent(uint hash) public Stream GetContent(uint hash)
{ {
PackageEntry e; PackageEntry e;
if (!index.TryGetValue(hash, out e)) if (!index.TryGetValue(hash, out e))
return null; return null;
s.Seek( dataStart + e.Offset, SeekOrigin.Begin ); s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
byte[] data = new byte[ e.Length ]; byte[] data = new byte[ e.Length ];
s.Read( data, 0, (int)e.Length ); s.Read( data, 0, (int)e.Length );
return new MemoryStream(Blast.Decompress(data)); return new MemoryStream(Blast.Decompress(data));
} }
public Stream GetContent(string filename) public Stream GetContent(string filename)
{ {
return GetContent(PackageEntry.HashFilename(filename)); return GetContent(PackageEntry.HashFilename(filename));
} }
public IEnumerable<uint> AllFileHashes() public IEnumerable<uint> AllFileHashes()
{ {
return index.Keys; return index.Keys;
} }
public bool Exists(string filename) public bool Exists(string filename)
{ {
return index.ContainsKey(PackageEntry.HashFilename(filename)); return index.ContainsKey(PackageEntry.HashFilename(filename));
} }
public int Priority public int Priority
{ {
get { return 2000 + priority; } get { return 2000 + priority; }
} }
public void Write(Dictionary<string, byte[]> contents) public void Write(Dictionary<string, byte[]> contents)
{ {
throw new NotImplementedException("Cannot save InstallShieldPackages."); throw new NotImplementedException("Cannot save InstallShieldPackages.");
} }
} }
} }

View File

@@ -1,220 +1,220 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public interface IFolder public interface IFolder
{ {
Stream GetContent(string filename); Stream GetContent(string filename);
bool Exists(string filename); bool Exists(string filename);
IEnumerable<uint> AllFileHashes(); IEnumerable<uint> AllFileHashes();
void Write(Dictionary<string, byte[]> contents); void Write(Dictionary<string, byte[]> contents);
int Priority { get; } int Priority { get; }
} }
public class MixFile : IFolder public class MixFile : IFolder
{ {
readonly Dictionary<uint, PackageEntry> index; readonly Dictionary<uint, PackageEntry> index;
readonly bool isRmix, isEncrypted; readonly bool isRmix, isEncrypted;
readonly long dataStart; readonly long dataStart;
readonly Stream s; readonly Stream s;
int priority; int priority;
// Create a new MixFile // Create a new MixFile
public MixFile(string filename, int priority, Dictionary<string, byte[]> contents) public MixFile(string filename, int priority, Dictionary<string, byte[]> contents)
{ {
this.priority = priority; this.priority = priority;
if (File.Exists(filename)) if (File.Exists(filename))
File.Delete(filename); File.Delete(filename);
s = File.Create(filename); s = File.Create(filename);
Write(contents); Write(contents);
} }
public MixFile(string filename, int priority) public MixFile(string filename, int priority)
{ {
this.priority = priority; this.priority = priority;
s = FileSystem.Open(filename); s = FileSystem.Open(filename);
BinaryReader reader = new BinaryReader(s); BinaryReader reader = new BinaryReader(s);
uint signature = reader.ReadUInt32(); uint signature = reader.ReadUInt32();
isRmix = 0 == (signature & ~(uint)(MixFileFlags.Checksum | MixFileFlags.Encrypted)); isRmix = 0 == (signature & ~(uint)(MixFileFlags.Checksum | MixFileFlags.Encrypted));
if (isRmix) if (isRmix)
{ {
isEncrypted = 0 != (signature & (uint)MixFileFlags.Encrypted); isEncrypted = 0 != (signature & (uint)MixFileFlags.Encrypted);
if( isEncrypted ) if( isEncrypted )
{ {
index = ParseRaHeader( s, out dataStart ).ToDictionary(x => x.Hash); index = ParseRaHeader( s, out dataStart ).ToDictionary(x => x.Hash);
return; return;
} }
} }
else else
s.Seek( 0, SeekOrigin.Begin ); s.Seek( 0, SeekOrigin.Begin );
isEncrypted = false; isEncrypted = false;
index = ParseTdHeader(s, out dataStart).ToDictionary(x => x.Hash); index = ParseTdHeader(s, out dataStart).ToDictionary(x => x.Hash);
} }
const long headerStart = 84; const long headerStart = 84;
List<PackageEntry> ParseRaHeader(Stream s, out long dataStart) List<PackageEntry> ParseRaHeader(Stream s, out long dataStart)
{ {
BinaryReader reader = new BinaryReader(s); BinaryReader reader = new BinaryReader(s);
byte[] keyblock = reader.ReadBytes(80); byte[] keyblock = reader.ReadBytes(80);
byte[] blowfishKey = new BlowfishKeyProvider().DecryptKey(keyblock); byte[] blowfishKey = new BlowfishKeyProvider().DecryptKey(keyblock);
uint[] h = ReadUints(reader, 2); uint[] h = ReadUints(reader, 2);
Blowfish fish = new Blowfish(blowfishKey); Blowfish fish = new Blowfish(blowfishKey);
MemoryStream ms = Decrypt( h, fish ); MemoryStream ms = Decrypt( h, fish );
BinaryReader reader2 = new BinaryReader(ms); BinaryReader reader2 = new BinaryReader(ms);
ushort numFiles = reader2.ReadUInt16(); ushort numFiles = reader2.ReadUInt16();
reader2.ReadUInt32(); /*datasize*/ reader2.ReadUInt32(); /*datasize*/
s.Position = headerStart; s.Position = headerStart;
reader = new BinaryReader(s); reader = new BinaryReader(s);
int byteCount = 6 + numFiles * PackageEntry.Size; int byteCount = 6 + numFiles * PackageEntry.Size;
h = ReadUints( reader, ( byteCount + 3 ) / 4 ); h = ReadUints( reader, ( byteCount + 3 ) / 4 );
ms = Decrypt( h, fish ); ms = Decrypt( h, fish );
dataStart = headerStart + byteCount + ( ( ~byteCount + 1 ) & 7 ); dataStart = headerStart + byteCount + ( ( ~byteCount + 1 ) & 7 );
long ds; long ds;
return ParseTdHeader( ms, out ds ); return ParseTdHeader( ms, out ds );
} }
static MemoryStream Decrypt( uint[] h, Blowfish fish ) static MemoryStream Decrypt( uint[] h, Blowfish fish )
{ {
uint[] decrypted = fish.Decrypt( h ); uint[] decrypted = fish.Decrypt( h );
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter( ms ); BinaryWriter writer = new BinaryWriter( ms );
foreach( uint t in decrypted ) foreach( uint t in decrypted )
writer.Write( t ); writer.Write( t );
writer.Flush(); writer.Flush();
ms.Position = 0; ms.Position = 0;
return ms; return ms;
} }
uint[] ReadUints(BinaryReader r, int count) uint[] ReadUints(BinaryReader r, int count)
{ {
uint[] ret = new uint[count]; uint[] ret = new uint[count];
for (int i = 0; i < ret.Length; i++) for (int i = 0; i < ret.Length; i++)
ret[i] = r.ReadUInt32(); ret[i] = r.ReadUInt32();
return ret; return ret;
} }
List<PackageEntry> ParseTdHeader(Stream s, out long dataStart) List<PackageEntry> ParseTdHeader(Stream s, out long dataStart)
{ {
List<PackageEntry> items = new List<PackageEntry>(); List<PackageEntry> items = new List<PackageEntry>();
BinaryReader reader = new BinaryReader(s); BinaryReader reader = new BinaryReader(s);
ushort numFiles = reader.ReadUInt16(); ushort numFiles = reader.ReadUInt16();
/*uint dataSize = */reader.ReadUInt32(); /*uint dataSize = */reader.ReadUInt32();
for (int i = 0; i < numFiles; i++) for (int i = 0; i < numFiles; i++)
items.Add(new PackageEntry(reader)); items.Add(new PackageEntry(reader));
dataStart = s.Position; dataStart = s.Position;
return items; return items;
} }
public Stream GetContent(uint hash) public Stream GetContent(uint hash)
{ {
PackageEntry e; PackageEntry e;
if (!index.TryGetValue(hash, out e)) if (!index.TryGetValue(hash, out e))
return null; return null;
s.Seek( dataStart + e.Offset, SeekOrigin.Begin ); s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
byte[] data = new byte[ e.Length ]; byte[] data = new byte[ e.Length ];
s.Read( data, 0, (int)e.Length ); s.Read( data, 0, (int)e.Length );
return new MemoryStream(data); return new MemoryStream(data);
} }
public Stream GetContent(string filename) public Stream GetContent(string filename)
{ {
return GetContent(PackageEntry.HashFilename(filename)); return GetContent(PackageEntry.HashFilename(filename));
} }
public IEnumerable<uint> AllFileHashes() public IEnumerable<uint> AllFileHashes()
{ {
return index.Keys; return index.Keys;
} }
public bool Exists(string filename) public bool Exists(string filename)
{ {
return index.ContainsKey(PackageEntry.HashFilename(filename)); return index.ContainsKey(PackageEntry.HashFilename(filename));
} }
public int Priority public int Priority
{ {
get { return 1000 + priority; } get { return 1000 + priority; }
} }
public void Write(Dictionary<string, byte[]> contents) public void Write(Dictionary<string, byte[]> contents)
{ {
// Cannot modify existing mixfile - rename existing file and // Cannot modify existing mixfile - rename existing file and
// create a new one with original content plus modifications // create a new one with original content plus modifications
FileSystem.Unmount(this); FileSystem.Unmount(this);
// TODO: Add existing data to the contents list // TODO: Add existing data to the contents list
if (index.Count > 0) if (index.Count > 0)
throw new NotImplementedException("Updating mix files unfinished"); throw new NotImplementedException("Updating mix files unfinished");
// Construct a list of entries for the file header // Construct a list of entries for the file header
uint dataSize = 0; uint dataSize = 0;
var items = new List<PackageEntry>(); var items = new List<PackageEntry>();
foreach (var kv in contents) foreach (var kv in contents)
{ {
uint length = (uint)kv.Value.Length; uint length = (uint)kv.Value.Length;
uint hash = PackageEntry.HashFilename(Path.GetFileName(kv.Key)); uint hash = PackageEntry.HashFilename(Path.GetFileName(kv.Key));
items.Add(new PackageEntry(hash, dataSize, length)); items.Add(new PackageEntry(hash, dataSize, length));
dataSize += length; dataSize += length;
} }
// Write the new file // Write the new file
s.Seek(0,SeekOrigin.Begin); s.Seek(0,SeekOrigin.Begin);
using (var writer = new BinaryWriter(s)) using (var writer = new BinaryWriter(s))
{ {
// Write file header // Write file header
writer.Write((ushort)items.Count); writer.Write((ushort)items.Count);
writer.Write(dataSize); writer.Write(dataSize);
foreach (var item in items) foreach (var item in items)
item.Write(writer); item.Write(writer);
writer.Flush(); writer.Flush();
// Copy file data // Copy file data
foreach (var file in contents) foreach (var file in contents)
s.Write(file.Value); s.Write(file.Value);
} }
} }
} }
[Flags] [Flags]
enum MixFileFlags : uint enum MixFileFlags : uint
{ {
Checksum = 0x10000, Checksum = 0x10000,
Encrypted = 0x20000, Encrypted = 0x20000,
} }
} }

View File

@@ -1,117 +1,117 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile; using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class ZipFile : IFolder public class ZipFile : IFolder
{ {
string filename; string filename;
SZipFile pkg; SZipFile pkg;
int priority; int priority;
public ZipFile(string filename, int priority) public ZipFile(string filename, int priority)
{ {
this.filename = filename; this.filename = filename;
this.priority = priority; this.priority = priority;
try try
{ {
// pull the file into memory, dont keep it open. // pull the file into memory, dont keep it open.
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename))); pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
} }
catch (ZipException e) catch (ZipException e)
{ {
Log.Write("debug", "Couldn't load zip file: {0}", e.Message); Log.Write("debug", "Couldn't load zip file: {0}", e.Message);
} }
} }
// Create a new zip with the specified contents // Create a new zip with the specified contents
public ZipFile(string filename, int priority, Dictionary<string, byte[]> contents) public ZipFile(string filename, int priority, Dictionary<string, byte[]> contents)
{ {
this.priority = priority; this.priority = priority;
this.filename = filename; this.filename = filename;
if (File.Exists(filename)) if (File.Exists(filename))
File.Delete(filename); File.Delete(filename);
pkg = SZipFile.Create(filename); pkg = SZipFile.Create(filename);
Write(contents); Write(contents);
} }
public Stream GetContent(string filename) public Stream GetContent(string filename)
{ {
using (var z = pkg.GetInputStream(pkg.GetEntry(filename))) using (var z = pkg.GetInputStream(pkg.GetEntry(filename)))
{ {
var ms = new MemoryStream(); var ms = new MemoryStream();
int bufSize = 2048; int bufSize = 2048;
byte[] buf = new byte[bufSize]; byte[] buf = new byte[bufSize];
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0) while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
ms.Write(buf, 0, bufSize); ms.Write(buf, 0, bufSize);
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
return ms; return ms;
} }
} }
public IEnumerable<uint> AllFileHashes() public IEnumerable<uint> AllFileHashes()
{ {
foreach(ZipEntry entry in pkg) foreach(ZipEntry entry in pkg)
yield return PackageEntry.HashFilename(entry.Name); yield return PackageEntry.HashFilename(entry.Name);
} }
public bool Exists(string filename) public bool Exists(string filename)
{ {
return pkg.GetEntry(filename) != null; return pkg.GetEntry(filename) != null;
} }
public int Priority public int Priority
{ {
get { return 500 + priority; } get { return 500 + priority; }
} }
public void Write(Dictionary<string, byte[]> contents) public void Write(Dictionary<string, byte[]> contents)
{ {
pkg.Close(); pkg.Close();
pkg = SZipFile.Create(filename); pkg = SZipFile.Create(filename);
pkg.BeginUpdate(); pkg.BeginUpdate();
// TODO: Clear existing content? // TODO: Clear existing content?
foreach (var kvp in contents) foreach (var kvp in contents)
pkg.Add(new StaticMemoryDataSource(kvp.Value), kvp.Key); pkg.Add(new StaticMemoryDataSource(kvp.Value), kvp.Key);
pkg.CommitUpdate(); pkg.CommitUpdate();
pkg.Close(); pkg.Close();
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename))); pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
} }
} }
class StaticMemoryDataSource : IStaticDataSource class StaticMemoryDataSource : IStaticDataSource
{ {
byte[] data; byte[] data;
public StaticMemoryDataSource (byte[] data) public StaticMemoryDataSource (byte[] data)
{ {
this.data = data; this.data = data;
} }
public Stream GetSource() public Stream GetSource()
{ {
return new MemoryStream(data); return new MemoryStream(data);
} }
} }
} }

View File

@@ -1,146 +1,146 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public enum Dune2ImageFlags : int public enum Dune2ImageFlags : int
{ {
F80_F2 = 0, F80_F2 = 0,
F2 = 2, F2 = 2,
L16_F80_F2_1 = 1, L16_F80_F2_1 = 1,
L16_F80_F2_2 = 3, L16_F80_F2_2 = 3,
Ln_F80_F2 = 5 Ln_F80_F2 = 5
} }
public class Dune2ImageHeader public class Dune2ImageHeader
{ {
public readonly Dune2ImageFlags Flags; public readonly Dune2ImageFlags Flags;
public readonly int Width; public readonly int Width;
public readonly int Height; public readonly int Height;
public readonly int Slices; public readonly int Slices;
public readonly int FileSize; public readonly int FileSize;
public readonly int DataSize; public readonly int DataSize;
public readonly byte[] LookupTable; public readonly byte[] LookupTable;
public byte[] Image; public byte[] Image;
public Dune2ImageHeader(BinaryReader reader) public Dune2ImageHeader(BinaryReader reader)
{ {
Flags = (Dune2ImageFlags)reader.ReadUInt16(); Flags = (Dune2ImageFlags)reader.ReadUInt16();
Slices = reader.ReadByte(); Slices = reader.ReadByte();
Width = reader.ReadUInt16(); Width = reader.ReadUInt16();
Height = reader.ReadByte(); Height = reader.ReadByte();
FileSize = reader.ReadUInt16(); FileSize = reader.ReadUInt16();
DataSize = reader.ReadUInt16(); DataSize = reader.ReadUInt16();
if (Flags == Dune2ImageFlags.L16_F80_F2_1 || if (Flags == Dune2ImageFlags.L16_F80_F2_1 ||
Flags == Dune2ImageFlags.L16_F80_F2_2 || Flags == Dune2ImageFlags.L16_F80_F2_2 ||
Flags == Dune2ImageFlags.Ln_F80_F2) Flags == Dune2ImageFlags.Ln_F80_F2)
{ {
int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? reader.ReadByte() : (byte)16; int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? reader.ReadByte() : (byte)16;
LookupTable = new byte[n]; LookupTable = new byte[n];
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
LookupTable[i] = reader.ReadByte(); LookupTable[i] = reader.ReadByte();
} }
else else
{ {
LookupTable = new byte[256]; LookupTable = new byte[256];
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
LookupTable[i] = (byte)i; LookupTable[i] = (byte)i;
LookupTable[1] = 0x7f; LookupTable[1] = 0x7f;
LookupTable[2] = 0x7e; LookupTable[2] = 0x7e;
LookupTable[3] = 0x7d; LookupTable[3] = 0x7d;
LookupTable[4] = 0x7c; LookupTable[4] = 0x7c;
} }
} }
public Size Size public Size Size
{ {
get { return new Size(Width, Height); } get { return new Size(Width, Height); }
} }
} }
public class Dune2ShpReader : IEnumerable<Dune2ImageHeader> public class Dune2ShpReader : IEnumerable<Dune2ImageHeader>
{ {
public readonly int ImageCount; public readonly int ImageCount;
List<Dune2ImageHeader> headers = new List<Dune2ImageHeader>(); List<Dune2ImageHeader> headers = new List<Dune2ImageHeader>();
public Dune2ShpReader(Stream stream) public Dune2ShpReader(Stream stream)
{ {
BinaryReader reader = new BinaryReader(stream); BinaryReader reader = new BinaryReader(stream);
ImageCount = reader.ReadUInt16(); ImageCount = reader.ReadUInt16();
//Last offset is pointer to end of file. //Last offset is pointer to end of file.
uint[] offsets = new uint[ImageCount + 1]; uint[] offsets = new uint[ImageCount + 1];
uint temp = reader.ReadUInt32(); uint temp = reader.ReadUInt32();
//If fourth byte in file is non-zero, the offsets are two bytes each. //If fourth byte in file is non-zero, the offsets are two bytes each.
bool twoByteOffsets = (temp & 0xFF0000) > 0; bool twoByteOffsets = (temp & 0xFF0000) > 0;
if (twoByteOffsets) if (twoByteOffsets)
{ {
offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes
offsets[1] = (temp & 0xFFFF) + 2; offsets[1] = (temp & 0xFFFF) + 2;
} }
else else
offsets[0] = temp + 2; offsets[0] = temp + 2;
for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++) for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++)
offsets[i] = (twoByteOffsets ? reader.ReadUInt16() : reader.ReadUInt32()) + 2; offsets[i] = (twoByteOffsets ? reader.ReadUInt16() : reader.ReadUInt32()) + 2;
for (int i = 0; i < ImageCount; i++) for (int i = 0; i < ImageCount; i++)
{ {
reader.BaseStream.Seek(offsets[i], SeekOrigin.Begin); reader.BaseStream.Seek(offsets[i], SeekOrigin.Begin);
Dune2ImageHeader header = new Dune2ImageHeader(reader); Dune2ImageHeader header = new Dune2ImageHeader(reader);
byte[] imgData = reader.ReadBytes(header.FileSize); byte[] imgData = reader.ReadBytes(header.FileSize);
header.Image = new byte[header.Height * header.Width]; header.Image = new byte[header.Height * header.Width];
//Decode image data //Decode image data
if (header.Flags != Dune2ImageFlags.F2) if (header.Flags != Dune2ImageFlags.F2)
{ {
byte[] tempData = new byte[header.DataSize]; byte[] tempData = new byte[header.DataSize];
Format80.DecodeInto(imgData, tempData); Format80.DecodeInto(imgData, tempData);
Format2.DecodeInto(tempData, header.Image); Format2.DecodeInto(tempData, header.Image);
} }
else else
Format2.DecodeInto(imgData, header.Image); Format2.DecodeInto(imgData, header.Image);
//Lookup values in lookup table //Lookup values in lookup table
if (header.LookupTable != null) if (header.LookupTable != null)
for (int j = 0; j < header.Image.Length; j++) for (int j = 0; j < header.Image.Length; j++)
header.Image[j] = header.LookupTable[header.Image[j]]; header.Image[j] = header.LookupTable[header.Image[j]];
headers.Add(header); headers.Add(header);
} }
} }
public Dune2ImageHeader this[int index] public Dune2ImageHeader this[int index]
{ {
get { return headers[index]; } get { return headers[index]; }
} }
public IEnumerator<Dune2ImageHeader> GetEnumerator() public IEnumerator<Dune2ImageHeader> GetEnumerator()
{ {
return headers.GetEnumerator(); return headers.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
} }
} }

View File

@@ -1,96 +1,96 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
namespace OpenRA.FileFormats.Graphics namespace OpenRA.FileFormats.Graphics
{ {
[AttributeUsage( AttributeTargets.Assembly )] [AttributeUsage( AttributeTargets.Assembly )]
public class RendererAttribute : Attribute public class RendererAttribute : Attribute
{ {
public readonly Type Type; public readonly Type Type;
public RendererAttribute( Type graphicsDeviceType ) public RendererAttribute( Type graphicsDeviceType )
{ {
if( !typeof( IGraphicsDevice ).IsAssignableFrom( graphicsDeviceType ) ) if( !typeof( IGraphicsDevice ).IsAssignableFrom( graphicsDeviceType ) )
throw new InvalidOperationException( "Incorrect type in RendererAttribute" ); throw new InvalidOperationException( "Incorrect type in RendererAttribute" );
Type = graphicsDeviceType; Type = graphicsDeviceType;
} }
} }
public interface IGraphicsDevice public interface IGraphicsDevice
{ {
IVertexBuffer<Vertex> CreateVertexBuffer( int length ); IVertexBuffer<Vertex> CreateVertexBuffer( int length );
IIndexBuffer CreateIndexBuffer( int length ); IIndexBuffer CreateIndexBuffer( int length );
ITexture CreateTexture( Bitmap bitmap ); ITexture CreateTexture( Bitmap bitmap );
ITexture CreateTexture(); ITexture CreateTexture();
IShader CreateShader( string name ); IShader CreateShader( string name );
Size WindowSize { get; } Size WindowSize { get; }
void Clear( Color color ); void Clear( Color color );
void Present( IInputHandler inputHandler ); void Present( IInputHandler inputHandler );
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange ); void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives ); void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );
void EnableScissor( int left, int top, int width, int height ); void EnableScissor( int left, int top, int width, int height );
void DisableScissor(); void DisableScissor();
} }
public interface IVertexBuffer<T> public interface IVertexBuffer<T>
{ {
void Bind(); void Bind();
void SetData( T[] vertices, int length ); void SetData( T[] vertices, int length );
} }
public interface IIndexBuffer public interface IIndexBuffer
{ {
void Bind(); void Bind();
void SetData( ushort[] indices, int length ); void SetData( ushort[] indices, int length );
} }
public interface IShader public interface IShader
{ {
void SetValue( string name, float x, float y ); void SetValue( string name, float x, float y );
void SetValue( string param, ITexture texture ); void SetValue( string param, ITexture texture );
void Commit(); void Commit();
void Render( Action a ); void Render( Action a );
} }
public interface ITexture public interface ITexture
{ {
void SetData(Bitmap bitmap); void SetData(Bitmap bitmap);
void SetData(uint[,] colors); void SetData(uint[,] colors);
void SetData(byte[] colors, int width, int height); void SetData(byte[] colors, int width, int height);
} }
public enum PrimitiveType public enum PrimitiveType
{ {
PointList, PointList,
LineList, LineList,
TriangleList, TriangleList,
} }
public struct Range<T> public struct Range<T>
{ {
public readonly T Start, End; public readonly T Start, End;
public Range( T start, T end ) { Start = start; End = end; } public Range( T start, T end ) { Start = start; End = end; }
} }
public enum WindowMode public enum WindowMode
{ {
Windowed, Windowed,
Fullscreen, Fullscreen,
PseudoFullscreen, PseudoFullscreen,
} }
} }

View File

@@ -1,71 +1,71 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace OpenRA namespace OpenRA
{ {
public interface IInputHandler public interface IInputHandler
{ {
void ModifierKeys( Modifiers mods ); void ModifierKeys( Modifiers mods );
void OnKeyInput( KeyInput input ); void OnKeyInput( KeyInput input );
void OnMouseInput( MouseInput input ); void OnMouseInput( MouseInput input );
} }
public struct MouseInput public struct MouseInput
{ {
public MouseInputEvent Event; public MouseInputEvent Event;
public MouseButton Button; public MouseButton Button;
public int2 Location; public int2 Location;
public Modifiers Modifiers; public Modifiers Modifiers;
public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods ) public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods )
{ {
this.Event = ev; this.Event = ev;
this.Button = button; this.Button = button;
this.Location = location; this.Location = location;
this.Modifiers = mods; this.Modifiers = mods;
} }
} }
public enum MouseInputEvent { Down, Move, Up }; public enum MouseInputEvent { Down, Move, Up };
[Flags] [Flags]
public enum MouseButton public enum MouseButton
{ {
None = 0, None = 0,
Left = 1, Left = 1,
Right = 2, Right = 2,
Middle = 4, Middle = 4,
WheelDown = 8, WheelDown = 8,
WheelUp = 16 WheelUp = 16
} }
[Flags] [Flags]
public enum Modifiers public enum Modifiers
{ {
None = 0, None = 0,
Shift = 1, Shift = 1,
Alt = 2, Alt = 2,
Ctrl = 4, Ctrl = 4,
} }
public enum KeyInputEvent { Down, Up }; public enum KeyInputEvent { Down, Up };
public struct KeyInput public struct KeyInput
{ {
public KeyInputEvent Event; public KeyInputEvent Event;
public char KeyChar; public char KeyChar;
public string KeyName; public string KeyName;
public Modifiers Modifiers; public Modifiers Modifiers;
public int VirtKey; public int VirtKey;
} }
} }

View File

@@ -1,178 +1,178 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class ImageHeader public class ImageHeader
{ {
public uint Offset; public uint Offset;
public Format Format; public Format Format;
public uint RefOffset; public uint RefOffset;
public Format RefFormat; public Format RefFormat;
public ImageHeader RefImage; public ImageHeader RefImage;
public byte[] Image; public byte[] Image;
public ImageHeader() { } public ImageHeader() { }
public ImageHeader( BinaryReader reader ) public ImageHeader( BinaryReader reader )
{ {
Offset = reader.ReadUInt32(); Offset = reader.ReadUInt32();
Format = (Format)( Offset >> 24 ); Format = (Format)( Offset >> 24 );
Offset &= 0xFFFFFF; Offset &= 0xFFFFFF;
RefOffset = reader.ReadUInt16(); RefOffset = reader.ReadUInt16();
RefFormat = (Format)reader.ReadUInt16(); RefFormat = (Format)reader.ReadUInt16();
} }
public static readonly int SizeOnDisk = 8; public static readonly int SizeOnDisk = 8;
public void WriteTo(BinaryWriter writer) public void WriteTo(BinaryWriter writer)
{ {
writer.Write(Offset | ((uint)Format << 24)); writer.Write(Offset | ((uint)Format << 24));
writer.Write((ushort)RefOffset); writer.Write((ushort)RefOffset);
writer.Write((ushort)RefFormat); writer.Write((ushort)RefFormat);
} }
} }
public enum Format public enum Format
{ {
Format20 = 0x20, Format20 = 0x20,
Format40 = 0x40, Format40 = 0x40,
Format80 = 0x80, Format80 = 0x80,
} }
public class ShpReader : IEnumerable<ImageHeader> public class ShpReader : IEnumerable<ImageHeader>
{ {
public readonly int ImageCount; public readonly int ImageCount;
public readonly ushort Width; public readonly ushort Width;
public readonly ushort Height; public readonly ushort Height;
public Size Size { get { return new Size(Width, Height); } } public Size Size { get { return new Size(Width, Height); } }
private readonly List<ImageHeader> headers = new List<ImageHeader>(); private readonly List<ImageHeader> headers = new List<ImageHeader>();
int recurseDepth = 0; int recurseDepth = 0;
public ShpReader( Stream stream ) public ShpReader( Stream stream )
{ {
BinaryReader reader = new BinaryReader( stream ); BinaryReader reader = new BinaryReader( stream );
ImageCount = reader.ReadUInt16(); ImageCount = reader.ReadUInt16();
reader.ReadUInt16(); reader.ReadUInt16();
reader.ReadUInt16(); reader.ReadUInt16();
Width = reader.ReadUInt16(); Width = reader.ReadUInt16();
Height = reader.ReadUInt16(); Height = reader.ReadUInt16();
reader.ReadUInt32(); reader.ReadUInt32();
for( int i = 0 ; i < ImageCount ; i++ ) for( int i = 0 ; i < ImageCount ; i++ )
headers.Add( new ImageHeader( reader ) ); headers.Add( new ImageHeader( reader ) );
new ImageHeader( reader ); // end-of-file header new ImageHeader( reader ); // end-of-file header
new ImageHeader( reader ); // all-zeroes header new ImageHeader( reader ); // all-zeroes header
Dictionary<uint, ImageHeader> offsets = new Dictionary<uint, ImageHeader>(); Dictionary<uint, ImageHeader> offsets = new Dictionary<uint, ImageHeader>();
foreach( ImageHeader h in headers ) foreach( ImageHeader h in headers )
offsets.Add( h.Offset, h ); offsets.Add( h.Offset, h );
for( int i = 0 ; i < ImageCount ; i++ ) for( int i = 0 ; i < ImageCount ; i++ )
{ {
ImageHeader h = headers[ i ]; ImageHeader h = headers[ i ];
if( h.Format == Format.Format20 ) if( h.Format == Format.Format20 )
h.RefImage = headers[ i - 1 ]; h.RefImage = headers[ i - 1 ];
else if( h.Format == Format.Format40 ) else if( h.Format == Format.Format40 )
{ {
if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) ) if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) ); throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) );
} }
} }
foreach( ImageHeader h in headers ) foreach( ImageHeader h in headers )
Decompress( stream, h ); 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 ) if( recurseDepth > ImageCount )
throw new InvalidDataException( "Format20/40 headers contain infinite loop" ); throw new InvalidDataException( "Format20/40 headers contain infinite loop" );
switch( h.Format ) switch( h.Format )
{ {
case Format.Format20: case Format.Format20:
case Format.Format40: case Format.Format40:
{ {
if( h.RefImage.Image == null ) if( h.RefImage.Image == null )
{ {
++recurseDepth; ++recurseDepth;
Decompress( stream, h.RefImage ); Decompress( stream, h.RefImage );
--recurseDepth; --recurseDepth;
} }
h.Image = CopyImageData( h.RefImage.Image ); h.Image = CopyImageData( h.RefImage.Image );
Format40.DecodeInto(ReadCompressedData(stream, h), h.Image); Format40.DecodeInto(ReadCompressedData(stream, h), h.Image);
break; break;
} }
case Format.Format80: case Format.Format80:
{ {
byte[] imageBytes = new byte[ Width * Height ]; byte[] imageBytes = new byte[ Width * Height ];
Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes ); Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes );
h.Image = imageBytes; h.Image = imageBytes;
break; break;
} }
default: default:
throw new InvalidDataException(); throw new InvalidDataException();
} }
} }
static byte[] ReadCompressedData( Stream stream, ImageHeader h ) static byte[] ReadCompressedData( Stream stream, ImageHeader h )
{ {
stream.Position = h.Offset; stream.Position = h.Offset;
// Actually, far too big. There's no length field with the correct length though :( // Actually, far too big. There's no length field with the correct length though :(
int compressedLength = (int)( stream.Length - stream.Position ); int compressedLength = (int)( stream.Length - stream.Position );
byte[] compressedBytes = new byte[ compressedLength ]; byte[] compressedBytes = new byte[ compressedLength ];
stream.Read( compressedBytes, 0, compressedLength ); stream.Read( compressedBytes, 0, compressedLength );
//MemoryStream ms = new MemoryStream( compressedBytes ); //MemoryStream ms = new MemoryStream( compressedBytes );
return compressedBytes; return compressedBytes;
} }
private byte[] CopyImageData( byte[] baseImage ) private byte[] CopyImageData( byte[] baseImage )
{ {
byte[] imageData = new byte[ Width * Height ]; byte[] imageData = new byte[ Width * Height ];
for( int i = 0 ; i < Width * Height ; i++ ) for( int i = 0 ; i < Width * Height ; i++ )
imageData[ i ] = baseImage[ i ]; imageData[ i ] = baseImage[ i ];
return imageData; return imageData;
} }
public IEnumerator<ImageHeader> GetEnumerator() public IEnumerator<ImageHeader> GetEnumerator()
{ {
return headers.GetEnumerator(); return headers.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
} }
} }

View File

@@ -1,28 +1,28 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace OpenRA.FileFormats.Graphics namespace OpenRA.FileFormats.Graphics
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Vertex public struct Vertex
{ {
public float x, y, z, u, v; public float x, y, z, u, v;
public float p, c; public float p, c;
public Vertex(float2 xy, float2 uv, float2 pc) public Vertex(float2 xy, float2 uv, float2 pc)
{ {
this.x = xy.X; this.y = xy.Y; this.z = 0; this.x = xy.X; this.y = xy.Y; this.z = 0;
this.u = uv.X; this.v = uv.Y; this.u = uv.X; this.v = uv.Y;
this.p = pc.X; this.c = pc.Y; this.p = pc.X; this.c = pc.Y;
} }
} }
} }

View File

@@ -1,16 +1,16 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class VqaReader public class VqaReader
@@ -40,10 +40,10 @@ namespace OpenRA.FileFormats
byte[] origData; byte[] origData;
// Final frame output // Final frame output
uint[,] frameData; uint[,] frameData;
byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed. byte[] audioData; // audio for this frame: 22050Hz 16bit mono pcm, uncompressed.
public byte[] AudioData { get { return audioData; } } public byte[] AudioData { get { return audioData; } }
public int CurrentFrame { get { return currentFrame; } } public int CurrentFrame { get { return currentFrame; } }
public VqaReader( Stream stream ) public VqaReader( Stream stream )
@@ -108,62 +108,62 @@ namespace OpenRA.FileFormats
offsets[i] = reader.ReadUInt32(); offsets[i] = reader.ReadUInt32();
if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000; if (offsets[i] > 0x40000000) offsets[i] -= 0x40000000;
offsets[i] <<= 1; offsets[i] <<= 1;
} }
CollectAudioData(); CollectAudioData();
Reset(); Reset();
} }
public void Reset() public void Reset()
{ {
currentFrame = cbOffset = cbChunk = 0; currentFrame = cbOffset = cbChunk = 0;
LoadFrame(); LoadFrame();
} }
void CollectAudioData() void CollectAudioData()
{ {
var ms = new MemoryStream(); var ms = new MemoryStream();
var adpcmIndex = 0; var adpcmIndex = 0;
bool compressed = false; bool compressed = false;
for (var i = 0; i < Frames; i++) for (var i = 0; i < Frames; i++)
{ {
stream.Seek(offsets[i], SeekOrigin.Begin); stream.Seek(offsets[i], SeekOrigin.Begin);
BinaryReader reader = new BinaryReader(stream); BinaryReader reader = new BinaryReader(stream);
var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length; var end = (i < Frames - 1) ? offsets[i + 1] : stream.Length;
while (reader.BaseStream.Position < end) while (reader.BaseStream.Position < end)
{ {
var type = new String(reader.ReadChars(4)); var type = new String(reader.ReadChars(4));
var length = int2.Swap(reader.ReadUInt32()); var length = int2.Swap(reader.ReadUInt32());
switch (type) switch (type)
{ {
case "SND0": case "SND0":
case "SND2": case "SND2":
var rawAudio = reader.ReadBytes((int)length); var rawAudio = reader.ReadBytes((int)length);
ms.Write(rawAudio); ms.Write(rawAudio);
compressed = (type == "SND2"); compressed = (type == "SND2");
break; break;
default: default:
reader.ReadBytes((int)length); reader.ReadBytes((int)length);
break; break;
} }
if (reader.PeekChar() == 0) reader.ReadByte(); if (reader.PeekChar() == 0) reader.ReadByte();
} }
} }
audioData = (compressed) ? AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex) : ms.ToArray(); audioData = (compressed) ? AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex) : ms.ToArray();
} }
public void AdvanceFrame() public void AdvanceFrame()
{ {
currentFrame++; currentFrame++;
LoadFrame(); LoadFrame();
} }
void LoadFrame() void LoadFrame()
{ {
if (currentFrame >= Frames) if (currentFrame >= Frames)
@@ -180,7 +180,7 @@ namespace OpenRA.FileFormats
var length = int2.Swap(reader.ReadUInt32()); var length = int2.Swap(reader.ReadUInt32());
switch(type) switch(type)
{ {
case "VQFR": case "VQFR":
DecodeVQFR(reader); DecodeVQFR(reader);
break; break;

View File

@@ -1,97 +1,97 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public static class HttpUtil public static class HttpUtil
{ {
public static byte[] DownloadData(string url, Action<int, int> f, int chunkSize) public static byte[] DownloadData(string url, Action<int, int> f, int chunkSize)
{ {
var uri = new Uri(url); var uri = new Uri(url);
var ip = Dns.GetHostEntry(uri.DnsSafeHost).AddressList[0]; var ip = Dns.GetHostEntry(uri.DnsSafeHost).AddressList[0];
using (var s = new TcpClient()) using (var s = new TcpClient())
{ {
s.Connect(new IPEndPoint(ip, uri.Port)); s.Connect(new IPEndPoint(ip, uri.Port));
var ns = s.GetStream(); var ns = s.GetStream();
var sw = new StreamWriter(ns); var sw = new StreamWriter(ns);
sw.Write("GET {0} HTTP/1.0\r\nHost:{1}\r\n\r\n", uri.PathAndQuery, uri.Host); sw.Write("GET {0} HTTP/1.0\r\nHost:{1}\r\n\r\n", uri.PathAndQuery, uri.Host);
sw.Flush(); sw.Flush();
var br = new BinaryReader(ns); var br = new BinaryReader(ns);
var contentLength = 0; var contentLength = 0;
var offset = 0; var offset = 0;
for (; ; ) for (; ; )
{ {
var result = br.ReadLine(); var result = br.ReadLine();
var kv = result.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries); var kv = result.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
if (result == "") if (result == "")
{ {
/* data follows the blank line */ /* data follows the blank line */
if (contentLength > 0) if (contentLength > 0)
{ {
if (f != null) if (f != null)
f(offset, contentLength); f(offset, contentLength);
var data = new byte[contentLength]; var data = new byte[contentLength];
while (offset < contentLength) while (offset < contentLength)
{ {
var thisChunk = Math.Min(contentLength - offset, chunkSize); var thisChunk = Math.Min(contentLength - offset, chunkSize);
br.Read(data, offset, thisChunk); br.Read(data, offset, thisChunk);
offset += thisChunk; offset += thisChunk;
if (f != null) if (f != null)
f(offset, contentLength); f(offset, contentLength);
} }
s.Close(); s.Close();
return data; return data;
} }
else else
{ {
s.Close(); s.Close();
return new byte[] { }; return new byte[] { };
} }
} }
else if (kv[0] == "Content-Length") else if (kv[0] == "Content-Length")
contentLength = int.Parse(kv[1]); contentLength = int.Parse(kv[1]);
} }
} }
} }
public static byte[] DownloadData(string url, Action<int, int> f) public static byte[] DownloadData(string url, Action<int, int> f)
{ {
return DownloadData(url, f, 4096); return DownloadData(url, f, 4096);
} }
public static byte[] DownloadData(string url) public static byte[] DownloadData(string url)
{ {
return DownloadData(url, null); return DownloadData(url, null);
} }
static string ReadLine(this BinaryReader br) static string ReadLine(this BinaryReader br)
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
char c; char c;
while ((c = br.ReadChar()) != '\n') while ((c = br.ReadChar()) != '\n')
if (c != '\r' && c != '\n') if (c != '\r' && c != '\n')
sb.Append(c); sb.Append(c);
return sb.ToString(); return sb.ToString();
} }
} }
} }

View File

@@ -1,65 +1,65 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
/* describes what is to be loaded in order to run a set of mods */ /* describes what is to be loaded in order to run a set of mods */
public class Manifest public class Manifest
{ {
public readonly string[] public readonly string[]
Mods, Folders, Packages, Rules, ServerTraits, Mods, Folders, Packages, Rules, ServerTraits,
Sequences, Cursors, Chrome, Assemblies, ChromeLayout, Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Music, Movies, TileSets; Weapons, Voices, Music, Movies, TileSets;
public readonly string LoadScreen; public readonly string LoadScreen;
public readonly int TileSize = 24; public readonly int TileSize = 24;
public Manifest(string[] mods) public Manifest(string[] mods)
{ {
Mods = mods; Mods = mods;
var yaml = mods var yaml = mods
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml")) .Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
.Aggregate(MiniYaml.Merge); .Aggregate(MiniYaml.Merge);
// Todo: Use fieldloader // Todo: Use fieldloader
Folders = YamlList(yaml, "Folders"); Folders = YamlList(yaml, "Folders");
Packages = YamlList(yaml, "Packages"); Packages = YamlList(yaml, "Packages");
Rules = YamlList(yaml, "Rules"); Rules = YamlList(yaml, "Rules");
ServerTraits = YamlList(yaml, "ServerTraits"); ServerTraits = YamlList(yaml, "ServerTraits");
Sequences = YamlList(yaml, "Sequences"); Sequences = YamlList(yaml, "Sequences");
Cursors = YamlList(yaml, "Cursors"); Cursors = YamlList(yaml, "Cursors");
Chrome = YamlList(yaml, "Chrome"); Chrome = YamlList(yaml, "Chrome");
Assemblies = YamlList(yaml, "Assemblies"); Assemblies = YamlList(yaml, "Assemblies");
ChromeLayout = YamlList(yaml, "ChromeLayout"); ChromeLayout = YamlList(yaml, "ChromeLayout");
Weapons = YamlList(yaml, "Weapons"); Weapons = YamlList(yaml, "Weapons");
Voices = YamlList(yaml, "Voices"); Voices = YamlList(yaml, "Voices");
Music = YamlList(yaml, "Music"); Music = YamlList(yaml, "Music");
Movies = YamlList(yaml, "Movies"); Movies = YamlList(yaml, "Movies");
TileSets = YamlList(yaml, "TileSets"); TileSets = YamlList(yaml, "TileSets");
LoadScreen = yaml.First( x => x.Key == "LoadScreen" ).Value.Value; LoadScreen = yaml.First( x => x.Key == "LoadScreen" ).Value.Value;
if (yaml.FirstOrDefault( x => x.Key == "TileSize" ) != null) if (yaml.FirstOrDefault( x => x.Key == "TileSize" ) != null)
TileSize = int.Parse(yaml.First( x => x.Key == "TileSize" ).Value.Value); TileSize = int.Parse(yaml.First( x => x.Key == "TileSize" ).Value.Value);
} }
static string[] YamlList(List<MiniYamlNode> ys, string key) static string[] YamlList(List<MiniYamlNode> ys, string key)
{ {
var y = ys.FirstOrDefault( x => x.Key == key ); var y = ys.FirstOrDefault( x => x.Key == key );
if( y == null ) if( y == null )
return new string[ 0 ]; return new string[ 0 ];
return y.Value.NodesDict.Keys.ToArray(); return y.Value.NodesDict.Keys.ToArray();
} }
} }
} }

View File

@@ -1,14 +1,14 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using System; using System;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
@@ -18,21 +18,21 @@ namespace OpenRA.FileFormats
public string Name; public string Name;
public string Palette; public string Palette;
public bool OwnsWorld = false; public bool OwnsWorld = false;
public bool NonCombatant = false; public bool NonCombatant = false;
public bool Playable = false; public bool Playable = false;
public bool DefaultStartingUnits = false; public bool DefaultStartingUnits = false;
public bool AllowBots = true; public bool AllowBots = true;
public bool LockRace = false; public bool LockRace = false;
public string Race; public string Race;
public bool LockColor = false; public bool LockColor = false;
public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25); public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25);
public int InitialCash = 0; public int InitialCash = 0;
public string[] Allies = {}; public string[] Allies = {};
public string[] Enemies = {}; public string[] Enemies = {};
public PlayerReference() {} public PlayerReference() {}
public PlayerReference(MiniYaml my) public PlayerReference(MiniYaml my)
{ {

View File

@@ -1,11 +1,11 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.FileFormats namespace OpenRA.FileFormats

View File

@@ -1,76 +1,76 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class Terrain public class Terrain
{ {
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>(); public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
public Terrain( Stream stream, int size ) public Terrain( Stream stream, int size )
{ {
// Try loading as a cnc .tem // Try loading as a cnc .tem
BinaryReader reader = new BinaryReader( stream ); BinaryReader reader = new BinaryReader( stream );
int Width = reader.ReadUInt16(); int Width = reader.ReadUInt16();
int Height = reader.ReadUInt16(); int Height = reader.ReadUInt16();
if( Width != size || Height != size ) if( Width != size || Height != size )
throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) ); throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) );
/*NumTiles = */reader.ReadUInt16(); /*NumTiles = */reader.ReadUInt16();
/*Zero1 = */reader.ReadUInt16(); /*Zero1 = */reader.ReadUInt16();
/*uint Size = */reader.ReadUInt32(); /*uint Size = */reader.ReadUInt32();
uint ImgStart = reader.ReadUInt32(); uint ImgStart = reader.ReadUInt32();
/*Zero2 = */reader.ReadUInt32(); /*Zero2 = */reader.ReadUInt32();
int IndexEnd, IndexStart; int IndexEnd, IndexStart;
if (reader.ReadUInt16() == 65535) // ID1 = FFFFh for cnc if (reader.ReadUInt16() == 65535) // ID1 = FFFFh for cnc
{ {
/*ID2 = */reader.ReadUInt16(); /*ID2 = */reader.ReadUInt16();
IndexEnd = reader.ReadInt32(); IndexEnd = reader.ReadInt32();
IndexStart = reader.ReadInt32(); IndexStart = reader.ReadInt32();
} }
else // Load as a ra .tem else // Load as a ra .tem
{ {
stream.Position = 0; stream.Position = 0;
reader = new BinaryReader( stream ); reader = new BinaryReader( stream );
Width = reader.ReadUInt16(); Width = reader.ReadUInt16();
Height = reader.ReadUInt16(); Height = reader.ReadUInt16();
/*NumTiles = */reader.ReadUInt16(); /*NumTiles = */reader.ReadUInt16();
reader.ReadUInt16(); reader.ReadUInt16();
/*XDim = */reader.ReadUInt16(); /*XDim = */reader.ReadUInt16();
/*YDim = */reader.ReadUInt16(); /*YDim = */reader.ReadUInt16();
/*uint FileSize = */reader.ReadUInt32(); /*uint FileSize = */reader.ReadUInt32();
ImgStart = reader.ReadUInt32(); ImgStart = reader.ReadUInt32();
reader.ReadUInt32(); reader.ReadUInt32();
reader.ReadUInt32(); reader.ReadUInt32();
IndexEnd = reader.ReadInt32(); IndexEnd = reader.ReadInt32();
reader.ReadUInt32(); reader.ReadUInt32();
IndexStart = reader.ReadInt32(); IndexStart = reader.ReadInt32();
} }
stream.Position = IndexStart; stream.Position = IndexStart;
foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) ) foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) )
{ {
if (b != 255) if (b != 255)
{ {
stream.Position = ImgStart + b * size * size; stream.Position = ImgStart + b * size * size;
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size)); TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size));
} }
else else
TileBitmapBytes.Add(null); TileBitmapBytes.Add(null);
} }
} }
} }
} }

View File

@@ -1,11 +1,11 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.FileFormats namespace OpenRA.FileFormats

View File

@@ -1,157 +1,157 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class TerrainTypeInfo public class TerrainTypeInfo
{ {
public string Type; public string Type;
public bool Buildable = true; public bool Buildable = true;
public bool AcceptSmudge = true; public bool AcceptSmudge = true;
public bool IsWater = false; public bool IsWater = false;
public Color Color; public Color Color;
public TerrainTypeInfo() {} public TerrainTypeInfo() {}
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); } public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
public MiniYaml Save() { return FieldSaver.Save(this); } public MiniYaml Save() { return FieldSaver.Save(this); }
} }
public class TileTemplate public class TileTemplate
{ {
[FieldLoader.Load] public ushort Id; [FieldLoader.Load] public ushort Id;
[FieldLoader.Load] public string Image; [FieldLoader.Load] public string Image;
[FieldLoader.Load] public int2 Size; [FieldLoader.Load] public int2 Size;
[FieldLoader.Load] public bool PickAny; [FieldLoader.Load] public bool PickAny;
[FieldLoader.LoadUsing( "LoadTiles" )] [FieldLoader.LoadUsing( "LoadTiles" )]
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>(); public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
public TileTemplate() {} public TileTemplate() {}
public TileTemplate(MiniYaml my) public TileTemplate(MiniYaml my)
{ {
FieldLoader.Load( this, my ); FieldLoader.Load( this, my );
} }
static object LoadTiles( MiniYaml y ) static object LoadTiles( MiniYaml y )
{ {
return y.NodesDict["Tiles"].NodesDict.ToDictionary( return y.NodesDict["Tiles"].NodesDict.ToDictionary(
t => byte.Parse(t.Key), t => byte.Parse(t.Key),
t => t.Value.Value ); t => t.Value.Value );
} }
public MiniYaml Save() public MiniYaml Save()
{ {
var root = new List<MiniYamlNode>(); var root = new List<MiniYamlNode>();
foreach (var field in new string[] {"Id", "Image", "Size", "PickAny"}) foreach (var field in new string[] {"Id", "Image", "Size", "PickAny"})
{ {
FieldInfo f = this.GetType().GetField(field); FieldInfo f = this.GetType().GetField(field);
if (f.GetValue(this) == null) continue; if (f.GetValue(this) == null) continue;
root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) ); root.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
} }
root.Add( new MiniYamlNode( "Tiles", null, root.Add( new MiniYamlNode( "Tiles", null,
Tiles.Select( x => new MiniYamlNode( x.Key.ToString(), x.Value ) ).ToList() ) ); Tiles.Select( x => new MiniYamlNode( x.Key.ToString(), x.Value ) ).ToList() ) );
return new MiniYaml(null, root); return new MiniYaml(null, root);
} }
} }
public class TileSet public class TileSet
{ {
public string Name; public string Name;
public string Id; public string Id;
public string Palette; public string Palette;
public int TileSize = 24; public int TileSize = 24;
public string[] Extensions; public string[] Extensions;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>(); public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>(); public Dictionary<ushort, Terrain> Tiles = new Dictionary<ushort, Terrain>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>(); public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"}; static List<string> fields = new List<string>() {"Name", "TileSize", "Id", "Palette", "Extensions"};
public TileSet() {} public TileSet() {}
public TileSet( string filepath ) public TileSet( string filepath )
{ {
var yaml = MiniYaml.DictFromFile( filepath ); var yaml = MiniYaml.DictFromFile( filepath );
// General info // General info
FieldLoader.Load(this, yaml["General"]); FieldLoader.Load(this, yaml["General"]);
// TerrainTypes // TerrainTypes
Terrain = yaml["Terrain"].NodesDict.Values Terrain = yaml["Terrain"].NodesDict.Values
.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type); .Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
// Templates // Templates
Templates = yaml["Templates"].NodesDict.Values Templates = yaml["Templates"].NodesDict.Values
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id); .Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
} }
public void LoadTiles() public void LoadTiles()
{ {
foreach (var t in Templates) foreach (var t in Templates)
using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) ) using( Stream s = FileSystem.OpenWithExts(t.Value.Image, Extensions) )
{ {
if( !Tiles.ContainsKey( t.Key ) ) if( !Tiles.ContainsKey( t.Key ) )
Tiles.Add( t.Key, new Terrain( s, TileSize ) ); Tiles.Add( t.Key, new Terrain( s, TileSize ) );
} }
} }
public void Save(string filepath) public void Save(string filepath)
{ {
var root = new List<MiniYamlNode>(); var root = new List<MiniYamlNode>();
var gen = new List<MiniYamlNode>(); var gen = new List<MiniYamlNode>();
foreach (var field in fields) foreach (var field in fields)
{ {
FieldInfo f = this.GetType().GetField(field); FieldInfo f = this.GetType().GetField(field);
if (f.GetValue(this) == null) continue; if (f.GetValue(this) == null) continue;
gen.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) ); gen.Add( new MiniYamlNode( field, FieldSaver.FormatValue( this, f ) ) );
} }
root.Add( new MiniYamlNode( "General", null, gen ) ); root.Add( new MiniYamlNode( "General", null, gen ) );
root.Add( new MiniYamlNode( "Terrain", null, root.Add( new MiniYamlNode( "Terrain", null,
Terrain.Select( t => new MiniYamlNode( Terrain.Select( t => new MiniYamlNode(
"TerrainType@{0}".F( t.Value.Type ), "TerrainType@{0}".F( t.Value.Type ),
t.Value.Save() ) ).ToList() ) ); t.Value.Save() ) ).ToList() ) );
root.Add( new MiniYamlNode( "Templates", null, root.Add( new MiniYamlNode( "Templates", null,
Templates.Select( t => new MiniYamlNode( Templates.Select( t => new MiniYamlNode(
"Template@{0}".F( t.Value.Id ), "Template@{0}".F( t.Value.Id ),
t.Value.Save() ) ).ToList() ) ); t.Value.Save() ) ).ToList() ) );
root.WriteToFile(filepath); root.WriteToFile(filepath);
} }
public byte[] GetBytes(TileReference<ushort,byte> r) public byte[] GetBytes(TileReference<ushort,byte> r)
{ {
Terrain tile; Terrain tile;
if( Tiles.TryGetValue( r.type, out tile ) ) if( Tiles.TryGetValue( r.type, out tile ) )
return tile.TileBitmapBytes[ r.index ]; return tile.TileBitmapBytes[ r.index ];
byte[] missingTile = new byte[ TileSize * TileSize ]; byte[] missingTile = new byte[ TileSize * TileSize ];
for( int i = 0 ; i < missingTile.Length ; i++ ) for( int i = 0 ; i < missingTile.Length ; i++ )
missingTile[ i ] = 0x36; missingTile[ i ] = 0x36;
return missingTile; return missingTile;
} }
public string GetTerrainType(TileReference<ushort, byte> r) public string GetTerrainType(TileReference<ushort, byte> r)
{ {
var tt = Templates[r.type].Tiles; var tt = Templates[r.type].Tiles;
string ret; string ret;
if (!tt.TryGetValue(r.index, out ret)) if (!tt.TryGetValue(r.index, out ret))
return "Clear"; // Default walkable return "Clear"; // Default walkable
return ret; return ret;
} }
} }
} }

View File

@@ -1,240 +1,240 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
using MiniYamlNodes = List<MiniYamlNode>; using MiniYamlNodes = List<MiniYamlNode>;
public class MiniYamlNode public class MiniYamlNode
{ {
public struct SourceLocation public struct SourceLocation
{ {
public string Filename; public int Line; public string Filename; public int Line;
} }
public SourceLocation Location; public SourceLocation Location;
public string Key; public string Key;
public MiniYaml Value; public MiniYaml Value;
public MiniYamlNode( string k, MiniYaml v ) public MiniYamlNode( string k, MiniYaml v )
{ {
Key = k; Key = k;
Value = v; Value = v;
} }
public MiniYamlNode( string k, MiniYaml v, SourceLocation loc ) public MiniYamlNode( string k, MiniYaml v, SourceLocation loc )
: this( k, v ) : this( k, v )
{ {
Location = loc; Location = loc;
} }
public MiniYamlNode( string k, string v ) public MiniYamlNode( string k, string v )
: this( k, v, null ) : this( k, v, null )
{ {
} }
public MiniYamlNode( string k, string v, List<MiniYamlNode> n ) public MiniYamlNode( string k, string v, List<MiniYamlNode> n )
: this( k, new MiniYaml( v, n ) ) : this( k, new MiniYaml( v, n ) )
{ {
} }
public MiniYamlNode( string k, string v, List<MiniYamlNode> n, SourceLocation loc ) public MiniYamlNode( string k, string v, List<MiniYamlNode> n, SourceLocation loc )
: this( k, new MiniYaml( v, n ), loc ) : this( k, new MiniYaml( v, n ), loc )
{ {
} }
} }
public class MiniYaml public class MiniYaml
{ {
public string Value; public string Value;
public List<MiniYamlNode> Nodes; public List<MiniYamlNode> Nodes;
public Dictionary<string, MiniYaml> NodesDict { get { return Nodes.ToDictionary( x => x.Key, x => x.Value ); } } public Dictionary<string, MiniYaml> NodesDict { get { return Nodes.ToDictionary( x => x.Key, x => x.Value ); } }
public MiniYaml( string value ) : this( value, null ) { } public MiniYaml( string value ) : this( value, null ) { }
public MiniYaml( string value, List<MiniYamlNode> nodes ) public MiniYaml( string value, List<MiniYamlNode> nodes )
{ {
Value = value; Value = value;
Nodes = nodes ?? new List<MiniYamlNode>(); Nodes = nodes ?? new List<MiniYamlNode>();
} }
public static MiniYaml FromDictionary<K, V>( Dictionary<K, V> dict ) public static MiniYaml FromDictionary<K, V>( Dictionary<K, V> dict )
{ {
return new MiniYaml( null, dict.Select( x => new MiniYamlNode( x.Key.ToString(), new MiniYaml( x.Value.ToString() ) ) ).ToList() ); return new MiniYaml( null, dict.Select( x => new MiniYamlNode( x.Key.ToString(), new MiniYaml( x.Value.ToString() ) ) ).ToList() );
} }
public static MiniYaml FromList<T>( List<T> list ) public static MiniYaml FromList<T>( List<T> list )
{ {
return new MiniYaml( null, list.Select( x => new MiniYamlNode( x.ToString(), new MiniYaml( null ) ) ).ToList() ); return new MiniYaml( null, list.Select( x => new MiniYamlNode( x.ToString(), new MiniYaml( null ) ) ).ToList() );
} }
static List<MiniYamlNode> FromLines(string[] lines, string filename) static List<MiniYamlNode> FromLines(string[] lines, string filename)
{ {
var levels = new List<List<MiniYamlNode>>(); var levels = new List<List<MiniYamlNode>>();
levels.Add(new List<MiniYamlNode>()); levels.Add(new List<MiniYamlNode>());
var lineNo = 0; var lineNo = 0;
foreach (var line in lines) foreach (var line in lines)
{ {
++lineNo; ++lineNo;
var t = line.TrimStart(' ', '\t'); var t = line.TrimStart(' ', '\t');
if (t.Length == 0 || t[0] == '#') if (t.Length == 0 || t[0] == '#')
continue; continue;
var level = line.Length - t.Length; var level = line.Length - t.Length;
if (levels.Count <= level) if (levels.Count <= level)
throw new InvalidOperationException("Bad indent in miniyaml"); throw new InvalidOperationException("Bad indent in miniyaml");
while (levels.Count > level + 1) while (levels.Count > level + 1)
levels.RemoveAt(levels.Count - 1); levels.RemoveAt(levels.Count - 1);
var d = new List<MiniYamlNode>(); var d = new List<MiniYamlNode>();
var rhs = SplitAtColon( ref t ); var rhs = SplitAtColon( ref t );
levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) ); levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) );
levels.Add(d); levels.Add(d);
} }
return levels[ 0 ]; return levels[ 0 ];
} }
static string SplitAtColon( ref string t ) static string SplitAtColon( ref string t )
{ {
var colon = t.IndexOf(':'); var colon = t.IndexOf(':');
if( colon == -1 ) if( colon == -1 )
return null; return null;
var ret = t.Substring( colon + 1 ).Trim(); var ret = t.Substring( colon + 1 ).Trim();
if( ret.Length == 0 ) if( ret.Length == 0 )
ret = null; ret = null;
t = t.Substring( 0, colon ).Trim(); t = t.Substring( 0, colon ).Trim();
return ret; return ret;
} }
public static List<MiniYamlNode> FromFileInPackage( string path ) public static List<MiniYamlNode> FromFileInPackage( string path )
{ {
StreamReader reader = new StreamReader( FileSystem.Open(path) ); StreamReader reader = new StreamReader( FileSystem.Open(path) );
List<string> lines = new List<string>(); List<string> lines = new List<string>();
while( !reader.EndOfStream ) while( !reader.EndOfStream )
lines.Add(reader.ReadLine()); lines.Add(reader.ReadLine());
reader.Close(); reader.Close();
return FromLines(lines.ToArray(), path); return FromLines(lines.ToArray(), path);
} }
public static Dictionary<string, MiniYaml> DictFromFile( string path ) public static Dictionary<string, MiniYaml> DictFromFile( string path )
{ {
return FromFile( path ).ToDictionary( x => x.Key, x => x.Value ); return FromFile( path ).ToDictionary( x => x.Key, x => x.Value );
} }
public static Dictionary<string, MiniYaml> DictFromStream( Stream stream ) public static Dictionary<string, MiniYaml> DictFromStream( Stream stream )
{ {
return FromStream( stream ).ToDictionary( x => x.Key, x => x.Value ); return FromStream( stream ).ToDictionary( x => x.Key, x => x.Value );
} }
public static List<MiniYamlNode> FromFile( string path ) public static List<MiniYamlNode> FromFile( string path )
{ {
return FromLines(File.ReadAllLines( path ), path); return FromLines(File.ReadAllLines( path ), path);
} }
public static List<MiniYamlNode> FromStream(Stream s) public static List<MiniYamlNode> FromStream(Stream s)
{ {
using (var reader = new StreamReader(s)) using (var reader = new StreamReader(s))
return FromString(reader.ReadToEnd()); return FromString(reader.ReadToEnd());
} }
public static List<MiniYamlNode> FromString(string text) public static List<MiniYamlNode> FromString(string text)
{ {
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), "<no filename available>"); return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), "<no filename available>");
} }
public static List<MiniYamlNode> Merge( List<MiniYamlNode> a, List<MiniYamlNode> b ) public static List<MiniYamlNode> Merge( List<MiniYamlNode> a, List<MiniYamlNode> b )
{ {
if( a.Count == 0 ) if( a.Count == 0 )
return b; return b;
if( b.Count == 0 ) if( b.Count == 0 )
return a; return a;
var ret = new List<MiniYamlNode>(); var ret = new List<MiniYamlNode>();
var aDict = a.ToDictionary( x => x.Key ); var aDict = a.ToDictionary( x => x.Key );
var bDict = b.ToDictionary( x => x.Key ); var bDict = b.ToDictionary( x => x.Key );
var keys = aDict.Keys.Union( bDict.Keys ).ToList(); var keys = aDict.Keys.Union( bDict.Keys ).ToList();
var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList(); var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList();
foreach( var key in keys ) foreach( var key in keys )
{ {
MiniYamlNode aa, bb; MiniYamlNode aa, bb;
aDict.TryGetValue( key, out aa ); aDict.TryGetValue( key, out aa );
bDict.TryGetValue( key, out bb ); bDict.TryGetValue( key, out bb );
if( noInherit.Contains( key ) ) if( noInherit.Contains( key ) )
{ {
if( aa != null ) if( aa != null )
ret.Add( aa ); ret.Add( aa );
} }
else else
{ {
var loc = aa == null ? default( MiniYamlNode.SourceLocation ) : aa.Location; var loc = aa == null ? default( MiniYamlNode.SourceLocation ) : aa.Location;
var merged = ( aa == null || bb == null ) ? aa ?? bb : new MiniYamlNode( key, Merge( aa.Value, bb.Value ), loc ); var merged = ( aa == null || bb == null ) ? aa ?? bb : new MiniYamlNode( key, Merge( aa.Value, bb.Value ), loc );
ret.Add( merged ); ret.Add( merged );
} }
} }
return ret; return ret;
} }
public static MiniYaml Merge( MiniYaml a, MiniYaml b ) public static MiniYaml Merge( MiniYaml a, MiniYaml b )
{ {
if( a == null ) if( a == null )
return b; return b;
if( b == null ) if( b == null )
return a; return a;
return new MiniYaml( a.Value ?? b.Value, Merge( a.Nodes, b.Nodes ) ); return new MiniYaml( a.Value ?? b.Value, Merge( a.Nodes, b.Nodes ) );
} }
public IEnumerable<string> ToLines(string name) public IEnumerable<string> ToLines(string name)
{ {
yield return name + ": " + Value; yield return name + ": " + Value;
if (Nodes != null) if (Nodes != null)
foreach (var line in Nodes.ToLines(false)) foreach (var line in Nodes.ToLines(false))
yield return "\t" + line; yield return "\t" + line;
} }
} }
public static class MiniYamlExts public static class MiniYamlExts
{ {
public static void WriteToFile(this MiniYamlNodes y, string filename) public static void WriteToFile(this MiniYamlNodes y, string filename)
{ {
File.WriteAllLines(filename, y.ToLines(true).Select(x => x.TrimEnd()).ToArray()); File.WriteAllLines(filename, y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
} }
public static string WriteToString(this MiniYamlNodes y) public static string WriteToString(this MiniYamlNodes y)
{ {
return string.Join("\n", y.ToLines(true).Select(x => x.TrimEnd()).ToArray()); return string.Join("\n", y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
} }
public static IEnumerable<string> ToLines(this MiniYamlNodes y, bool lowest) public static IEnumerable<string> ToLines(this MiniYamlNodes y, bool lowest)
{ {
foreach (var kv in y) foreach (var kv in y)
{ {
foreach (var line in kv.Value.ToLines(kv.Key)) foreach (var line in kv.Value.ToLines(kv.Key))
yield return line; yield return line;
if (lowest) if (lowest)
yield return ""; yield return "";
} }
} }
} }
} }

View File

@@ -1,85 +1,85 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class PackageEntry public class PackageEntry
{ {
public readonly uint Hash; public readonly uint Hash;
public readonly uint Offset; public readonly uint Offset;
public readonly uint Length; public readonly uint Length;
public PackageEntry(uint hash, uint offset, uint length) public PackageEntry(uint hash, uint offset, uint length)
{ {
Hash = hash; Hash = hash;
Offset = offset; Offset = offset;
Length = length; Length = length;
} }
public PackageEntry(BinaryReader r) public PackageEntry(BinaryReader r)
{ {
Hash = r.ReadUInt32(); Hash = r.ReadUInt32();
Offset = r.ReadUInt32(); Offset = r.ReadUInt32();
Length = r.ReadUInt32(); Length = r.ReadUInt32();
} }
public void Write(BinaryWriter w) public void Write(BinaryWriter w)
{ {
w.Write(Hash); w.Write(Hash);
w.Write(Offset); w.Write(Offset);
w.Write(Length); w.Write(Length);
} }
public override string ToString() public override string ToString()
{ {
string filename; string filename;
if (Names.TryGetValue(Hash, out filename)) if (Names.TryGetValue(Hash, out filename))
return string.Format("{0} - offset 0x{1:x8} - length 0x{2:x8}", filename, Offset, Length); return string.Format("{0} - offset 0x{1:x8} - length 0x{2:x8}", filename, Offset, Length);
else else
return string.Format("0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}", Hash, Offset, Length); return string.Format("0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}", Hash, Offset, Length);
} }
public static uint HashFilename(string name) public static uint HashFilename(string name)
{ {
if (name.Length > 12) if (name.Length > 12)
name = name.Substring(0, 12); name = name.Substring(0, 12);
name = name.ToUpperInvariant(); name = name.ToUpperInvariant();
if (name.Length % 4 != 0) if (name.Length % 4 != 0)
name = name.PadRight(name.Length + (4 - name.Length % 4), '\0'); name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name)); MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
BinaryReader reader = new BinaryReader(ms); BinaryReader reader = new BinaryReader(ms);
int len = name.Length >> 2; int len = name.Length >> 2;
uint result = 0; uint result = 0;
while (len-- != 0) while (len-- != 0)
result = ((result << 1) | (result >> 31)) + reader.ReadUInt32(); result = ((result << 1) | (result >> 31)) + reader.ReadUInt32();
return result; return result;
} }
static Dictionary<uint, string> Names = new Dictionary<uint,string>(); static Dictionary<uint, string> Names = new Dictionary<uint,string>();
public static void AddStandardName(string s) public static void AddStandardName(string s)
{ {
uint hash = HashFilename(s); uint hash = HashFilename(s);
Names.Add(hash, s); Names.Add(hash, s);
} }
public const int Size = 12; public const int Size = 12;
} }
} }

View File

@@ -1,77 +1,77 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class Palette public class Palette
{ {
uint[] colors; uint[] colors;
public Color GetColor(int index) public Color GetColor(int index)
{ {
return Color.FromArgb((int)colors[index]); return Color.FromArgb((int)colors[index]);
} }
public void SetColor(int index, Color color) public void SetColor(int index, Color color)
{ {
colors[index] = (uint)color.ToArgb(); colors[index] = (uint)color.ToArgb();
} }
public void SetColor(int index, uint color) public void SetColor(int index, uint color)
{ {
colors[index] = (uint)color; colors[index] = (uint)color;
} }
public uint[] Values public uint[] Values
{ {
get { return colors; } get { return colors; }
} }
public Palette(Stream s, bool remapTransparent) public Palette(Stream s, bool remapTransparent)
{ {
colors = new uint[256]; colors = new uint[256];
using (BinaryReader reader = new BinaryReader(s)) using (BinaryReader reader = new BinaryReader(s))
{ {
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
byte r = (byte)(reader.ReadByte() << 2); byte r = (byte)(reader.ReadByte() << 2);
byte g = (byte)(reader.ReadByte() << 2); byte g = (byte)(reader.ReadByte() << 2);
byte b = (byte)(reader.ReadByte() << 2); byte b = (byte)(reader.ReadByte() << 2);
colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b); colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b);
} }
} }
colors[0] = 0; colors[0] = 0;
if (remapTransparent) if (remapTransparent)
{ {
colors[1] = 178u << 24; // Hack for d2k; may have side effects colors[1] = 178u << 24; // Hack for d2k; may have side effects
colors[3] = 178u << 24; colors[3] = 178u << 24;
colors[4] = 140u << 24; colors[4] = 140u << 24;
} }
} }
public Palette(Palette p, IPaletteRemap r) public Palette(Palette p, IPaletteRemap r)
{ {
colors = new uint[256]; colors = new uint[256];
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb(); colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb();
} }
public Palette(Palette p) public Palette(Palette p)
{ {
colors = (uint[])p.colors.Clone(); colors = (uint[])p.colors.Clone();
} }
} }
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); } public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
} }

View File

@@ -1,53 +1,53 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
// TODO: ship this out of here. // TODO: ship this out of here.
public enum PaletteFormat { ra, cnc, d2k } public enum PaletteFormat { ra, cnc, d2k }
public class PlayerColorRemap : IPaletteRemap public class PlayerColorRemap : IPaletteRemap
{ {
Dictionary<int, Color> remapColors; Dictionary<int, Color> remapColors;
public PlayerColorRemap(ColorRamp c, PaletteFormat fmt) public PlayerColorRemap(ColorRamp c, PaletteFormat fmt)
{ {
var c1 = c.GetColor(0); var c1 = c.GetColor(0);
var c2 = c.GetColor(1); /* temptemp: this can be expressed better */ var c2 = c.GetColor(1); /* temptemp: this can be expressed better */
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80; var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
var ramp = (fmt == PaletteFormat.cnc) var ramp = (fmt == PaletteFormat.cnc)
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 } ? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; : new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
remapColors = ramp.Select((x, i) => Pair.New(baseIndex + i, ColorLerp(x / 16f, c1, c2))) remapColors = ramp.Select((x, i) => Pair.New(baseIndex + i, ColorLerp(x / 16f, c1, c2)))
.ToDictionary(u => u.First, u => u.Second); .ToDictionary(u => u.First, u => u.Second);
} }
public static Color ColorLerp(float t, Color c1, Color c2) public static Color ColorLerp(float t, Color c1, Color c2)
{ {
return Color.FromArgb(255, return Color.FromArgb(255,
(int)(t * c2.R + (1 - t) * c1.R), (int)(t * c2.R + (1 - t) * c1.R),
(int)(t * c2.G + (1 - t) * c1.G), (int)(t * c2.G + (1 - t) * c1.G),
(int)(t * c2.B + (1 - t) * c1.B)); (int)(t * c2.B + (1 - t) * c1.B));
} }
public Color GetRemappedColor(Color original, int index) public Color GetRemappedColor(Color original, int index)
{ {
Color c; Color c;
return remapColors.TryGetValue(index, out c) return remapColors.TryGetValue(index, out c)
? c : original; ? c : original;
} }
} }
} }

View File

@@ -1,40 +1,40 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
/// <summary> /// <summary>
/// A thread-safe action queue, suitable for passing units of work between threads. /// A thread-safe action queue, suitable for passing units of work between threads.
/// </summary> /// </summary>
public class ActionQueue public class ActionQueue
{ {
object syncRoot = new object(); object syncRoot = new object();
Action actions = () => { }; Action actions = () => { };
public void Add(Action a) public void Add(Action a)
{ {
lock (syncRoot) lock (syncRoot)
actions += a; actions += a;
} }
public void PerformActions() public void PerformActions()
{ {
Action a; Action a;
lock (syncRoot) lock (syncRoot)
{ {
a = actions; a = actions;
actions = () => { }; actions = () => { };
} }
a(); a();
} }
} }
} }

View File

@@ -1,49 +1,49 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class Cache<T, U> : IEnumerable<KeyValuePair<T, U>> public class Cache<T, U> : IEnumerable<KeyValuePair<T, U>>
{ {
Dictionary<T, U> hax = new Dictionary<T, U>(); Dictionary<T, U> hax = new Dictionary<T, U>();
Func<T,U> loader; Func<T,U> loader;
public Cache(Func<T,U> loader) public Cache(Func<T,U> loader)
{ {
if (loader == null) if (loader == null)
throw new ArgumentNullException(); throw new ArgumentNullException();
this.loader = loader; this.loader = loader;
} }
public U this[T key] public U this[T key]
{ {
get get
{ {
U result; U result;
if (!hax.TryGetValue(key, out result)) if (!hax.TryGetValue(key, out result))
hax.Add(key, result = loader(key)); hax.Add(key, result = loader(key));
return result; return result;
} }
} }
public IEnumerator<KeyValuePair<T, U>> GetEnumerator() { return hax.GetEnumerator(); } public IEnumerator<KeyValuePair<T, U>> GetEnumerator() { return hax.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerable<T> Keys { get { return hax.Keys; } } public IEnumerable<T> Keys { get { return hax.Keys; } }
public IEnumerable<U> Values { get { return hax.Values; } } public IEnumerable<U> Values { get { return hax.Values; } }
} }
} }

View File

@@ -1,35 +1,35 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
namespace OpenRA namespace OpenRA
{ {
public class DisposableAction : IDisposable public class DisposableAction : IDisposable
{ {
public DisposableAction(Action a) { this.a = a; } public DisposableAction(Action a) { this.a = a; }
Action a; Action a;
bool disposed; bool disposed;
public void Dispose() public void Dispose()
{ {
if (disposed) return; if (disposed) return;
disposed = true; disposed = true;
a(); a();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
~DisposableAction() ~DisposableAction()
{ {
Dispose(); Dispose();
} }
} }
} }

View File

@@ -1,46 +1,46 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class Lazy<T> public class Lazy<T>
{ {
Func<T> p; Func<T> p;
T value; T value;
public Lazy(Func<T> p) public Lazy(Func<T> p)
{ {
if (p == null) if (p == null)
throw new ArgumentNullException(); throw new ArgumentNullException();
this.p = p; this.p = p;
} }
public T Value public T Value
{ {
get get
{ {
if (p == null) if (p == null)
return value; return value;
value = p(); value = p();
p = null; p = null;
return value; return value;
} }
} }
} }
public static class Lazy public static class Lazy
{ {
public static Lazy<T> New<T>(Func<T> p) { return new Lazy<T>(p); } public static Lazy<T> New<T>(Func<T> p) { return new Lazy<T>(p); }
} }
} }

View File

@@ -1,70 +1,70 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public struct Pair<T, U> public struct Pair<T, U>
{ {
public T First; public T First;
public U Second; public U Second;
public Pair(T first, U second) public Pair(T first, U second)
{ {
First = first; First = first;
Second = second; Second = second;
} }
static IEqualityComparer<T> tc = EqualityComparer<T>.Default; static IEqualityComparer<T> tc = EqualityComparer<T>.Default;
static IEqualityComparer<U> uc = EqualityComparer<U>.Default; static IEqualityComparer<U> uc = EqualityComparer<U>.Default;
public static bool operator ==(Pair<T, U> a, Pair<T, U> b) public static bool operator ==(Pair<T, U> a, Pair<T, U> b)
{ {
return tc.Equals(a.First, b.First) && uc.Equals(a.Second, b.Second); return tc.Equals(a.First, b.First) && uc.Equals(a.Second, b.Second);
} }
public static bool operator !=(Pair<T, U> a, Pair<T, U> b) public static bool operator !=(Pair<T, U> a, Pair<T, U> b)
{ {
return !(a == b); return !(a == b);
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (!(obj is Pair<T, U>)) if (!(obj is Pair<T, U>))
return false; return false;
return (Pair<T, U>)obj == this; return (Pair<T, U>)obj == this;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return First.GetHashCode() ^ Second.GetHashCode(); return First.GetHashCode() ^ Second.GetHashCode();
} }
public Pair<T, U> WithFirst(T t) { return new Pair<T, U>(t, Second); } public Pair<T, U> WithFirst(T t) { return new Pair<T, U>(t, Second); }
public Pair<T, U> WithSecond(U u) { return new Pair<T, U>(First, u); } public Pair<T, U> WithSecond(U u) { return new Pair<T, U>(First, u); }
public static T AsFirst(Pair<T, U> p) { return p.First; } public static T AsFirst(Pair<T, U> p) { return p.First; }
public static U AsSecond(Pair<T, U> p) { return p.Second; } public static U AsSecond(Pair<T, U> p) { return p.Second; }
public Pair<U, T> Swap() { return Pair.New(Second, First); } public Pair<U, T> Swap() { return Pair.New(Second, First); }
public override string ToString() public override string ToString()
{ {
return "({0},{1})".F(First, Second); return "({0},{1})".F(First, Second);
} }
} }
public static class Pair public static class Pair
{ {
public static Pair<T, U> New<T, U>(T t, U u) { return new Pair<T, U>(t, u); } public static Pair<T, U> New<T, U>(T t, U u) { return new Pair<T, U>(t, u); }
} }
} }

View File

@@ -1,103 +1,103 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class PriorityQueue<T> public class PriorityQueue<T>
where T : IComparable<T> where T : IComparable<T>
{ {
List<T[]> items = new List<T[]>(); List<T[]> items = new List<T[]>();
int level, index; int level, index;
public PriorityQueue() public PriorityQueue()
{ {
items.Add(new T[1]); items.Add(new T[1]);
} }
public void Add(T item) public void Add(T item)
{ {
int addLevel = level; int addLevel = level;
int addIndex = index; int addIndex = index;
while (addLevel >= 1 && Above(addLevel, addIndex).CompareTo(item) > 0) while (addLevel >= 1 && Above(addLevel, addIndex).CompareTo(item) > 0)
{ {
items[addLevel][addIndex] = Above(addLevel, addIndex); items[addLevel][addIndex] = Above(addLevel, addIndex);
--addLevel; --addLevel;
addIndex >>= 1; addIndex >>= 1;
} }
items[addLevel][addIndex] = item; items[addLevel][addIndex] = item;
if (++index >= (1 << level)) if (++index >= (1 << level))
{ {
index = 0; index = 0;
if (items.Count <= ++level) if (items.Count <= ++level)
items.Add(new T[1 << level]); items.Add(new T[1 << level]);
} }
} }
public bool Empty { get { return (level == 0); } } public bool Empty { get { return (level == 0); } }
T At(int level, int index) { return items[level][index]; } T At(int level, int index) { return items[level][index]; }
T Above(int level, int index) { return items[level - 1][index >> 1]; } T Above(int level, int index) { return items[level - 1][index >> 1]; }
T Last() T Last()
{ {
int lastLevel = level; int lastLevel = level;
int lastIndex = index; int lastIndex = index;
if (--lastIndex < 0) if (--lastIndex < 0)
lastIndex = (1 << --lastLevel) - 1; lastIndex = (1 << --lastLevel) - 1;
return At(lastLevel, lastIndex); return At(lastLevel, lastIndex);
} }
public T Pop() public T Pop()
{ {
if (level == 0 && index == 0) if (level == 0 && index == 0)
throw new InvalidOperationException("Attempting to pop empty PriorityQueue"); throw new InvalidOperationException("Attempting to pop empty PriorityQueue");
T ret = At(0, 0); T ret = At(0, 0);
BubbleInto(0, 0, Last()); BubbleInto(0, 0, Last());
if (--index < 0) if (--index < 0)
index = (1 << --level) - 1; index = (1 << --level) - 1;
return ret; return ret;
} }
void BubbleInto(int intoLevel, int intoIndex, T val) void BubbleInto(int intoLevel, int intoIndex, T val)
{ {
int downLevel = intoLevel + 1; int downLevel = intoLevel + 1;
int downIndex = intoIndex << 1; int downIndex = intoIndex << 1;
if (downLevel > level || (downLevel == level && downIndex >= index)) if (downLevel > level || (downLevel == level && downIndex >= index))
{ {
items[intoLevel][intoIndex] = val; items[intoLevel][intoIndex] = val;
return; return;
} }
if (downLevel <= level && downIndex < index - 1 && if (downLevel <= level && downIndex < index - 1 &&
At(downLevel, downIndex).CompareTo(At(downLevel, downIndex + 1)) >= 0) At(downLevel, downIndex).CompareTo(At(downLevel, downIndex + 1)) >= 0)
++downIndex; ++downIndex;
if (val.CompareTo(At(downLevel, downIndex)) <= 0) if (val.CompareTo(At(downLevel, downIndex)) <= 0)
{ {
items[intoLevel][intoIndex] = val; items[intoLevel][intoIndex] = val;
return; return;
} }
items[intoLevel][intoIndex] = At(downLevel, downIndex); items[intoLevel][intoIndex] = At(downLevel, downIndex);
BubbleInto(downLevel, downIndex, val); BubbleInto(downLevel, downIndex, val);
} }
} }
} }

View File

@@ -1,66 +1,66 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenRA.Collections namespace OpenRA.Collections
{ {
public class Set<T> : IEnumerable<T> public class Set<T> : IEnumerable<T>
{ {
Dictionary<T, bool> data = new Dictionary<T, bool>(); Dictionary<T, bool> data = new Dictionary<T, bool>();
public void Add( T obj ) public void Add( T obj )
{ {
data.Add( obj, false ); data.Add( obj, false );
if( OnAdd != null ) if( OnAdd != null )
OnAdd( obj ); OnAdd( obj );
} }
public void Remove( T obj ) public void Remove( T obj )
{ {
data.Remove( obj ); data.Remove( obj );
if( OnRemove != null ) if( OnRemove != null )
OnRemove( obj ); OnRemove( obj );
} }
public event Action<T> OnAdd; public event Action<T> OnAdd;
public event Action<T> OnRemove; public event Action<T> OnRemove;
public IEnumerator<T> GetEnumerator() public IEnumerator<T> GetEnumerator()
{ {
return data.Keys.GetEnumerator(); return data.Keys.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return GetEnumerator();
} }
} }
public class CachedView<T,U> : Set<U> public class CachedView<T,U> : Set<U>
{ {
public CachedView( Set<T> set, Func<T, bool> include, Func<T, U> store ) public CachedView( Set<T> set, Func<T, bool> include, Func<T, U> store )
: this( set, include, x => new[] { store( x ) } ) : this( set, include, x => new[] { store( x ) } )
{ {
} }
public CachedView( Set<T> set, Func<T,bool> include, Func<T,IEnumerable<U>> store ) public CachedView( Set<T> set, Func<T,bool> include, Func<T,IEnumerable<U>> store )
{ {
foreach( var t in set ) foreach( var t in set )
if( include( t ) ) if( include( t ) )
store( t ).Do( x => Add( x ) ); store( t ).Do( x => Add( x ) );
set.OnAdd += obj => { if( include( obj ) ) store( obj ).Do( x => Add( x ) ); }; set.OnAdd += obj => { if( include( obj ) ) store( obj ).Do( x => Add( x ) ); };
set.OnRemove += obj => { if( include( obj ) ) store( obj ).Do( x => Remove( x ) ); }; set.OnRemove += obj => { if( include( obj ) ) store( obj ).Do( x => Remove( x ) ); };
} }
} }
} }

View File

@@ -1,104 +1,104 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace OpenRA namespace OpenRA
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct float2 public struct float2
{ {
public float X, Y; public float X, Y;
public float2(float x, float y) { X = x; Y = y; } public float2(float x, float y) { X = x; Y = y; }
public float2(PointF p) { X = p.X; Y = p.Y; } public float2(PointF p) { X = p.X; Y = p.Y; }
public float2(Point p) { X = p.X; Y = p.Y; } public float2(Point p) { X = p.X; Y = p.Y; }
public float2(Size p) { X = p.Width; Y = p.Height; } public float2(Size p) { X = p.Width; Y = p.Height; }
public float2(SizeF p) { X = p.Width; Y = p.Height; } public float2(SizeF p) { X = p.Width; Y = p.Height; }
public PointF ToPointF() { return new PointF(X, Y); } public PointF ToPointF() { return new PointF(X, Y); }
public SizeF ToSizeF() { return new SizeF(X, Y); } public SizeF ToSizeF() { return new SizeF(X, Y); }
public static implicit operator float2(int2 src) { return new float2(src.X, src.Y); } public static implicit operator float2(int2 src) { return new float2(src.X, src.Y); }
public static float2 operator +(float2 a, float2 b) { return new float2(a.X + b.X, a.Y + b.Y); } public static float2 operator +(float2 a, float2 b) { return new float2(a.X + b.X, a.Y + b.Y); }
public static float2 operator -(float2 a, float2 b) { return new float2(a.X - b.X, a.Y - b.Y); } public static float2 operator -(float2 a, float2 b) { return new float2(a.X - b.X, a.Y - b.Y); }
public static float2 operator -(float2 a) { return new float2(-a.X, -a.Y); } public static float2 operator -(float2 a) { return new float2(-a.X, -a.Y); }
public static float Lerp(float a, float b, float t) { return a + t * (b - a); } public static float Lerp(float a, float b, float t) { return a + t * (b - a); }
public static float2 Lerp(float2 a, float2 b, float t) public static float2 Lerp(float2 a, float2 b, float t)
{ {
return new float2( return new float2(
Lerp(a.X, b.X, t), Lerp(a.X, b.X, t),
Lerp(a.Y, b.Y, t)); Lerp(a.Y, b.Y, t));
} }
public static float2 Lerp(float2 a, float2 b, float2 t) public static float2 Lerp(float2 a, float2 b, float2 t)
{ {
return new float2( return new float2(
Lerp(a.X, b.X, t.X), Lerp(a.X, b.X, t.X),
Lerp(a.Y, b.Y, t.Y)); Lerp(a.Y, b.Y, t.Y));
} }
public static float2 FromAngle(float a) { return new float2((float)Math.Sin(a), (float)Math.Cos(a)); } public static float2 FromAngle(float a) { return new float2((float)Math.Sin(a), (float)Math.Cos(a)); }
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; } static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
public float2 Constrain(float2 min, float2 max) public float2 Constrain(float2 min, float2 max)
{ {
return new float2( return new float2(
Constrain(X, min.X, max.X), Constrain(X, min.X, max.X),
Constrain(Y, min.Y, max.Y)); Constrain(Y, min.Y, max.Y));
} }
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); } public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
public static float2 operator *(float2 b, float a) { return new float2(a * b.X, a * b.Y); } public static float2 operator *(float2 b, float a) { return new float2(a * b.X, a * b.Y); }
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); } public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); } public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }
public static bool operator ==(float2 me, float2 other) { return (me.X == other.X && me.Y == other.Y); } public static bool operator ==(float2 me, float2 other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(float2 me, float2 other) { return !(me == other); } public static bool operator !=(float2 me, float2 other) { return !(me == other); }
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); } public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null) if (obj == null)
return false; return false;
float2 o = (float2)obj; float2 o = (float2)obj;
return o == this; return o == this;
} }
public static readonly float2 Zero = new float2(0, 0); public static readonly float2 Zero = new float2(0, 0);
public static bool WithinEpsilon(float2 a, float2 b, float e) public static bool WithinEpsilon(float2 a, float2 b, float e)
{ {
float2 d = a - b; float2 d = a - b;
return Math.Abs(d.X) < e && Math.Abs(d.Y) < e; return Math.Abs(d.X) < e && Math.Abs(d.Y) < e;
} }
public float2 Sign() { return new float2(Math.Sign(X), Math.Sign(Y)); } public float2 Sign() { return new float2(Math.Sign(X), Math.Sign(Y)); }
public static float Dot(float2 a, float2 b) { return a.X * b.X + a.Y * b.Y; } public static float Dot(float2 a, float2 b) { return a.X * b.X + a.Y * b.Y; }
public float2 Round() { return new float2((float)Math.Round(X), (float)Math.Round(Y)); } public float2 Round() { return new float2((float)Math.Round(X), (float)Math.Round(Y)); }
public override string ToString() { return string.Format("({0},{1})", X, Y); } public override string ToString() { return string.Format("({0},{1})", X, Y); }
public int2 ToInt2() { return new int2((int)X, (int)Y); } public int2 ToInt2() { return new int2((int)X, (int)Y); }
public static float2 Max(float2 a, float2 b) { return new float2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); } public static float2 Max(float2 a, float2 b) { return new float2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static float2 Min(float2 a, float2 b) { return new float2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); } public static float2 Min(float2 a, float2 b) { return new float2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public float LengthSquared { get { return X * X + Y * Y; } } public float LengthSquared { get { return X * X + Y * Y; } }
public float Length { get { return (float)Math.Sqrt(LengthSquared); } } public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
} }
} }

View File

@@ -1,85 +1,85 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
namespace OpenRA namespace OpenRA
{ {
public struct int2 public struct int2
{ {
public int X,Y; public int X,Y;
public int2( int x, int y ) { this.X = x; this.Y = y; } public int2( int x, int y ) { this.X = x; this.Y = y; }
public int2( Point p ) { X = p.X; Y = p.Y; } public int2( Point p ) { X = p.X; Y = p.Y; }
public int2( Size p ) { X = p.Width; Y = p.Height; } public int2( Size p ) { X = p.Width; Y = p.Height; }
public static int2 operator +(int2 a, int2 b) { return new int2(a.X + b.X, a.Y + b.Y); } public static int2 operator +(int2 a, int2 b) { return new int2(a.X + b.X, a.Y + b.Y); }
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); } public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); } public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); } public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); } public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); }
public static int2 operator -(int2 a) { return new int2(-a.X, -a.Y); } public static int2 operator -(int2 a) { return new int2(-a.X, -a.Y); }
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); } public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(int2 me, int2 other) { return !(me == other); } public static bool operator !=(int2 me, int2 other) { return !(me == other); }
public int2 Sign() { return new int2(Math.Sign(X), Math.Sign(Y)); } public int2 Sign() { return new int2(Math.Sign(X), Math.Sign(Y)); }
public int2 Abs() { return new int2( Math.Abs( X ), Math.Abs( Y ) ); } public int2 Abs() { return new int2( Math.Abs( X ), Math.Abs( Y ) ); }
public int LengthSquared { get { return X * X + Y * Y; } } public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); } public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public static int2 Max(int2 a, int2 b) { return new int2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); } public static int2 Max(int2 a, int2 b) { return new int2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static int2 Min(int2 a, int2 b) { return new int2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); } public static int2 Min(int2 a, int2 b) { return new int2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null) if (obj == null)
return false; return false;
int2 o = (int2)obj; int2 o = (int2)obj;
return o == this; return o == this;
} }
public static readonly int2 Zero = new int2(0, 0); public static readonly int2 Zero = new int2(0, 0);
public Point ToPoint() { return new Point(X, Y); } public Point ToPoint() { return new Point(X, Y); }
public PointF ToPointF() { return new PointF(X, Y); } public PointF ToPointF() { return new PointF(X, Y); }
public float2 ToFloat2() { return new float2(X, Y); } public float2 ToFloat2() { return new float2(X, Y); }
public override string ToString() { return string.Format("{0},{1}", X, Y); } public override string ToString() { return string.Format("{0},{1}", X, Y); }
// Change endianness of a uint32 // Change endianness of a uint32
public static uint Swap(uint orig) public static uint Swap(uint orig)
{ {
return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24); return (uint)((orig & 0xff000000) >> 24) | ((orig & 0x00ff0000) >> 8) | ((orig & 0x0000ff00) << 8) | ((orig & 0x000000ff) << 24);
} }
public static int Lerp( int a, int b, int mul, int div ) public static int Lerp( int a, int b, int mul, int div )
{ {
return a + ( b - a ) * mul / div; return a + ( b - a ) * mul / div;
} }
public static int2 Lerp( int2 a, int2 b, int mul, int div ) public static int2 Lerp( int2 a, int2 b, int mul, int div )
{ {
return a + ( b - a ) * mul / div; return a + ( b - a ) * mul / div;
} }
public int2 Clamp(Rectangle r) public int2 Clamp(Rectangle r)
{ {
return new int2(Math.Min(r.Right, Math.Max(X, r.Left)), return new int2(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))); Math.Min(r.Bottom, Math.Max(Y, r.Top)));
} }
public static int Dot(int2 a, int2 b) { return a.X * b.X + a.Y * b.Y; } public static int Dot(int2 a, int2 b) { return a.X * b.X + a.Y * b.Y; }
} }
} }

View File

@@ -1,74 +1,74 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
namespace OpenRA namespace OpenRA
{ {
public struct ChannelInfo public struct ChannelInfo
{ {
public string Filename; public string Filename;
public StreamWriter Writer; public StreamWriter Writer;
} }
public static class Log public static class Log
{ {
static string LogPathPrefix = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar; static string LogPathPrefix = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar;
static Dictionary<string, ChannelInfo> channels = new Dictionary<string,ChannelInfo>(); static Dictionary<string, ChannelInfo> channels = new Dictionary<string,ChannelInfo>();
public static string LogPath public static string LogPath
{ {
get { return LogPathPrefix; } get { return LogPathPrefix; }
set set
{ {
LogPathPrefix = value; LogPathPrefix = value;
if (!Directory.Exists(LogPathPrefix)) if (!Directory.Exists(LogPathPrefix))
Directory.CreateDirectory(LogPathPrefix); Directory.CreateDirectory(LogPathPrefix);
} }
} }
public static void AddChannel(string channelName, string filename) public static void AddChannel(string channelName, string filename)
{ {
if (channels.ContainsKey(channelName)) return; if (channels.ContainsKey(channelName)) return;
var i = 0; var i = 0;
var f = filename; var f = filename;
while (File.Exists(LogPathPrefix + filename)) while (File.Exists(LogPathPrefix + filename))
try try
{ {
StreamWriter writer = File.CreateText(LogPathPrefix + filename); StreamWriter writer = File.CreateText(LogPathPrefix + filename);
writer.AutoFlush = true; writer.AutoFlush = true;
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = writer }); channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = writer });
return; return;
} }
catch (IOException) { filename = f + ".{0}".F(++i); } catch (IOException) { filename = f + ".{0}".F(++i); }
//if no logs exist, just make it //if no logs exist, just make it
StreamWriter w = File.CreateText(LogPathPrefix + filename); StreamWriter w = File.CreateText(LogPathPrefix + filename);
w.AutoFlush = true; w.AutoFlush = true;
channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = w }); channels.Add(channelName, new ChannelInfo() { Filename = filename, Writer = w });
} }
public static void Write(string channel, string format, params object[] args) public static void Write(string channel, string format, params object[] args)
{ {
ChannelInfo info; ChannelInfo info;
if (!channels.TryGetValue(channel, out info)) if (!channels.TryGetValue(channel, out info))
throw new Exception("Tried logging to non-existant channel " + channel); throw new Exception("Tried logging to non-existant channel " + channel);
info.Writer.WriteLine(format, args); info.Writer.WriteLine(format, args);
} }
} }
} }

View File

@@ -1,31 +1,31 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.Support namespace OpenRA.Support
{ {
public class Stopwatch public class Stopwatch
{ {
System.Diagnostics.Stopwatch sw; System.Diagnostics.Stopwatch sw;
public Stopwatch () public Stopwatch ()
{ {
Reset(); Reset();
} }
public double ElapsedTime() public double ElapsedTime()
{ {
return sw.Elapsed.TotalMilliseconds / 1000.0; return sw.Elapsed.TotalMilliseconds / 1000.0;
} }
public void Reset() public void Reset()
{ {
sw = System.Diagnostics.Stopwatch.StartNew(); sw = System.Diagnostics.Stopwatch.StartNew();
} }
} }
} }

View File

@@ -1,27 +1,27 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
namespace OpenRA.Support namespace OpenRA.Support
{ {
public static class Timer public static class Timer
{ {
static Stopwatch sw = new Stopwatch(); static Stopwatch sw = new Stopwatch();
static double lastTime = 0; static double lastTime = 0;
public static void Time( string message ) public static void Time( string message )
{ {
var time = sw.ElapsedTime(); var time = sw.ElapsedTime();
var dt = time - lastTime; var dt = time - lastTime;
if( dt > 0.0001 ) if( dt > 0.0001 )
Log.Write("perf", message, dt ); Log.Write("perf", message, dt );
lastTime = time; lastTime = time;
} }
} }
} }

View File

@@ -1,66 +1,66 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
namespace OpenRA.Thirdparty namespace OpenRA.Thirdparty
{ {
// quick & dirty Mersenne Twister [MT19937] implementation // quick & dirty Mersenne Twister [MT19937] implementation
public class Random public class Random
{ {
uint[] mt = new uint[624]; uint[] mt = new uint[624];
int index = 0; int index = 0;
public int Last; public int Last;
public Random() : this(Environment.TickCount) { } public Random() : this(Environment.TickCount) { }
public Random(int seed) public Random(int seed)
{ {
mt[0] = (uint)seed; mt[0] = (uint)seed;
for (var i = 1u; i < mt.Length; i++) for (var i = 1u; i < mt.Length; i++)
mt[i] = 1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i; mt[i] = 1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i;
} }
public int Next() public int Next()
{ {
if (index == 0) Generate(); if (index == 0) Generate();
var y = mt[index]; var y = mt[index];
y ^= (y >> 11); y ^= (y >> 11);
y ^= ((y << 7) & 2636928640); y ^= ((y << 7) & 2636928640);
y ^= ((y << 15) & 4022730752); y ^= ((y << 15) & 4022730752);
y ^= y >> 18; y ^= y >> 18;
index = (index + 1) % 624; index = (index + 1) % 624;
Last = (int)(y % int.MaxValue); Last = (int)(y % int.MaxValue);
return Last; return Last;
} }
public int Next(int low, int high) { return low + Next() % (high - low); } public int Next(int low, int high) { return low + Next() % (high - low); }
public int Next(int high) { return Next() % high; } public int Next(int high) { return Next() % high; }
public double NextDouble() { return Math.Abs(Next() / (double)0x7fffffff); } public double NextDouble() { return Math.Abs(Next() / (double)0x7fffffff); }
void Generate() void Generate()
{ {
unchecked unchecked
{ {
for (var i = 0u; i < mt.Length; i++) for (var i = 0u; i < mt.Length; i++)
{ {
var y = (mt[i] & 0x80000000) | (mt[(i + 1) % 624] & 0x7fffffff); var y = (mt[i] & 0x80000000) | (mt[(i + 1) % 624] & 0x7fffffff);
mt[i] = mt[(i + 397u) % 624u] ^ (y >> 1); mt[i] = mt[(i + 397u) % 624u] ^ (y >> 1);
if ((y & 1) == 1) if ((y & 1) == 1)
mt[i] = (mt[i] ^ 2567483615); mt[i] = (mt[i] ^ 2567483615);
} }
} }
} }
} }
} }

View File

@@ -1,106 +1,106 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class TypeDictionary : IEnumerable public class TypeDictionary : IEnumerable
{ {
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>(); Dictionary<Type, object> dataSingular = new Dictionary<Type, object>();
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>(); Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>();
public void Add( object val ) public void Add( object val )
{ {
var t = val.GetType(); var t = val.GetType();
foreach( var i in t.GetInterfaces() ) foreach( var i in t.GetInterfaces() )
InnerAdd( i, val ); InnerAdd( i, val );
foreach( var tt in t.BaseTypes() ) foreach( var tt in t.BaseTypes() )
InnerAdd( tt, val ); InnerAdd( tt, val );
} }
void InnerAdd( Type t, object val ) void InnerAdd( Type t, object val )
{ {
List<object> objs; List<object> objs;
object obj; object obj;
if( dataMultiple.TryGetValue( t, out objs ) ) if( dataMultiple.TryGetValue( t, out objs ) )
objs.Add( val ); objs.Add( val );
else if( dataSingular.TryGetValue( t, out obj ) ) else if( dataSingular.TryGetValue( t, out obj ) )
{ {
dataSingular.Remove( t ); dataSingular.Remove( t );
dataMultiple.Add( t, new List<object> { obj, val } ); dataMultiple.Add( t, new List<object> { obj, val } );
} }
else else
dataSingular.Add( t, val ); dataSingular.Add( t, val );
} }
public bool Contains<T>() public bool Contains<T>()
{ {
return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) ); return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) );
} }
public T Get<T>() public T Get<T>()
{ {
if( dataMultiple.ContainsKey( typeof( T ) ) ) if( dataMultiple.ContainsKey( typeof( T ) ) )
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
object ret; object ret;
if( !dataSingular.TryGetValue( typeof( T ), out ret ) ) if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T))); throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
return (T)ret; return (T)ret;
} }
public T GetOrDefault<T>() public T GetOrDefault<T>()
{ {
if( dataMultiple.ContainsKey( typeof( T ) ) ) if( dataMultiple.ContainsKey( typeof( T ) ) )
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
object ret; object ret;
if( !dataSingular.TryGetValue( typeof( T ), out ret ) ) if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
return default( T ); return default( T );
return (T)ret; return (T)ret;
} }
public IEnumerable<T> WithInterface<T>() public IEnumerable<T> WithInterface<T>()
{ {
List<object> objs; List<object> objs;
object obj; object obj;
if( dataMultiple.TryGetValue( typeof( T ), out objs ) ) if( dataMultiple.TryGetValue( typeof( T ), out objs ) )
return objs.Cast<T>(); return objs.Cast<T>();
else if( dataSingular.TryGetValue( typeof( T ), out obj ) ) else if( dataSingular.TryGetValue( typeof( T ), out obj ) )
return new T[] { (T)obj }; return new T[] { (T)obj };
else else
return new T[ 0 ]; return new T[ 0 ];
} }
public IEnumerator GetEnumerator() public IEnumerator GetEnumerator()
{ {
return WithInterface<object>().GetEnumerator(); return WithInterface<object>().GetEnumerator();
} }
} }
public static class TypeExts public static class TypeExts
{ {
public static IEnumerable<Type> BaseTypes( this Type t ) public static IEnumerable<Type> BaseTypes( this Type t )
{ {
while( t != null ) while( t != null )
{ {
yield return t; yield return t;
t = t.BaseType; t = t.BaseType;
} }
} }
} }
} }

View File

@@ -1,20 +1,20 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Support; using OpenRA.Support;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Traits.Activities; using OpenRA.Traits.Activities;
namespace OpenRA namespace OpenRA
@@ -24,23 +24,23 @@ namespace OpenRA
public readonly ActorInfo Info; public readonly ActorInfo Info;
public readonly World World; public readonly World World;
public readonly uint ActorID; public readonly uint ActorID;
public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } } public int2 Location { get { return Trait<IOccupySpace>().TopLeft; } }
public int2 CenterLocation { get { return Trait<IHasLocation>().PxPosition; } } public int2 CenterLocation { get { return Trait<IHasLocation>().PxPosition; } }
[Sync] [Sync]
public Player Owner; public Player Owner;
private IActivity currentActivity; private IActivity currentActivity;
public Group Group; public Group Group;
internal Actor(World world, string name, TypeDictionary initDict ) internal Actor(World world, string name, TypeDictionary initDict )
{ {
var init = new ActorInitializer( this, initDict ); var init = new ActorInitializer( this, initDict );
World = world; World = world;
ActorID = world.NextAID(); ActorID = world.NextAID();
if( initDict.Contains<OwnerInit>() ) if( initDict.Contains<OwnerInit>() )
Owner = init.Get<OwnerInit,Player>(); Owner = init.Get<OwnerInit,Player>();
if (name != null) if (name != null)
@@ -51,8 +51,8 @@ namespace OpenRA
Info = Rules.Info[name.ToLowerInvariant()]; Info = Rules.Info[name.ToLowerInvariant()];
foreach (var trait in Info.TraitsInConstructOrder()) foreach (var trait in Info.TraitsInConstructOrder())
AddTrait(trait.Create(init)); AddTrait(trait.Create(init));
} }
Size = Lazy.New(() => Size = Lazy.New(() =>
{ {
var si = Info.Traits.GetOrDefault<SelectableInfo>(); var si = Info.Traits.GetOrDefault<SelectableInfo>();
@@ -61,13 +61,13 @@ namespace OpenRA
// auto size from render // auto size from render
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault(); var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
if (firstSprite.Sprite == null) return float2.Zero; if (firstSprite.Sprite == null) return float2.Zero;
return firstSprite.Sprite.size * firstSprite.Scale; return firstSprite.Sprite.size * firstSprite.Scale;
}); });
} }
public void Tick() public void Tick()
{ {
if (currentActivity == null) if (currentActivity == null)
foreach (var ni in TraitsImplementing<INotifyIdle>()) foreach (var ni in TraitsImplementing<INotifyIdle>())
ni.TickIdle(this); ni.TickIdle(this);
@@ -88,38 +88,38 @@ namespace OpenRA
var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)); var sprites = TraitsImplementing<IRender>().SelectMany(x => x.Render(this));
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m)); return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
} }
// When useAltitude = true, the bounding box is extended // When useAltitude = true, the bounding box is extended
// vertically to altitude = 0 to support FindUnitsInCircle queries // vertically to altitude = 0 to support FindUnitsInCircle queries
// When false, the bounding box is given for the actor // When false, the bounding box is given for the actor
// at its current altitude // at its current altitude
public RectangleF GetBounds(bool useAltitude) public RectangleF GetBounds(bool useAltitude)
{ {
var size = Size.Value; var size = Size.Value;
var loc = CenterLocation - 0.5f * size; var loc = CenterLocation - 0.5f * size;
var si = Info.Traits.GetOrDefault<SelectableInfo>(); var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null && si.Bounds.Length > 2) if (si != null && si.Bounds != null && si.Bounds.Length > 2)
loc += new float2(si.Bounds[2], si.Bounds[3]); loc += new float2(si.Bounds[2], si.Bounds[3]);
var move = TraitOrDefault<IMove>(); var move = TraitOrDefault<IMove>();
if (move != null) if (move != null)
{ {
loc -= new float2(0, move.Altitude); loc -= new float2(0, move.Altitude);
if (useAltitude) if (useAltitude)
size = new float2(size.X, size.Y + move.Altitude); size = new float2(size.X, size.Y + move.Altitude);
} }
return new RectangleF(loc.X, loc.Y, size.X, size.Y); return new RectangleF(loc.X, loc.Y, size.X, size.Y);
} }
public bool IsInWorld { get; internal set; } public bool IsInWorld { get; internal set; }
public void QueueActivity( bool queued, IActivity nextActivity ) public void QueueActivity( bool queued, IActivity nextActivity )
{ {
if( !queued ) if( !queued )
CancelActivity(); CancelActivity();
QueueActivity( nextActivity ); QueueActivity( nextActivity );
} }
public void QueueActivity( IActivity nextActivity ) public void QueueActivity( IActivity nextActivity )
@@ -152,60 +152,60 @@ namespace OpenRA
return ( o != null && o.ActorID == ActorID ); return ( o != null && o.ActorID == ActorID );
} }
public override string ToString() public override string ToString()
{ {
return "{0} {1}{2}".F( Info.Name, ActorID, IsInWorld ? "" : " (not in world)" ); return "{0} {1}{2}".F( Info.Name, ActorID, IsInWorld ? "" : " (not in world)" );
} }
public T Trait<T>() public T Trait<T>()
{ {
return World.traitDict.Get<T>( this ); return World.traitDict.Get<T>( this );
} }
public T TraitOrDefault<T>() public T TraitOrDefault<T>()
{ {
return World.traitDict.GetOrDefault<T>( this ); return World.traitDict.GetOrDefault<T>( this );
} }
public IEnumerable<T> TraitsImplementing<T>() public IEnumerable<T> TraitsImplementing<T>()
{ {
return World.traitDict.WithInterface<T>( this ); return World.traitDict.WithInterface<T>( this );
} }
public bool HasTrait<T>() public bool HasTrait<T>()
{ {
return World.traitDict.Contains<T>( this ); return World.traitDict.Contains<T>( this );
} }
public void AddTrait( object trait ) public void AddTrait( object trait )
{ {
World.traitDict.AddTrait( this, trait ); World.traitDict.AddTrait( this, trait );
} }
public bool Destroyed { get; private set; } public bool Destroyed { get; private set; }
public void Destroy() public void Destroy()
{ {
World.AddFrameEndTask( w => World.AddFrameEndTask( w =>
{ {
if (Destroyed) return; if (Destroyed) return;
World.Remove( this ); World.Remove( this );
World.traitDict.RemoveActor( this ); World.traitDict.RemoveActor( this );
Destroyed = true; Destroyed = true;
} ); } );
} }
// todo: move elsewhere. // todo: move elsewhere.
public void ChangeOwner(Player newOwner) public void ChangeOwner(Player newOwner)
{ {
World.AddFrameEndTask(w => World.AddFrameEndTask(w =>
{ {
// momentarily remove from world so the ownership queries don't get confused // momentarily remove from world so the ownership queries don't get confused
w.Remove(this); w.Remove(this);
Owner = newOwner; Owner = newOwner;
w.Add(this); w.Add(this);
}); });
} }
} }
} }

View File

@@ -1,134 +1,134 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA namespace OpenRA
{ {
public class ActorInitializer public class ActorInitializer
{ {
public readonly Actor self; public readonly Actor self;
public World world { get { return self.World; } } public World world { get { return self.World; } }
internal TypeDictionary dict; internal TypeDictionary dict;
public ActorInitializer( Actor actor, TypeDictionary dict ) public ActorInitializer( Actor actor, TypeDictionary dict )
{ {
this.self = actor; this.self = actor;
this.dict = dict; this.dict = dict;
} }
public T Get<T>() public T Get<T>()
where T : IActorInit where T : IActorInit
{ {
return dict.Get<T>(); return dict.Get<T>();
} }
public U Get<T,U>() public U Get<T,U>()
where T : IActorInit<U> where T : IActorInit<U>
{ {
return dict.Get<T>().Value( world ); return dict.Get<T>().Value( world );
} }
public bool Contains<T>() public bool Contains<T>()
where T : IActorInit where T : IActorInit
{ {
return dict.Contains<T>(); return dict.Contains<T>();
} }
}
public interface IActorInit {}
public interface IActorInit<T> : IActorInit
{
T Value( World world );
}
public class FacingInit : IActorInit<int>
{
[FieldFromYamlKey]
public readonly int value = 128;
public FacingInit() { }
public FacingInit( int init )
{
value = init;
}
public int Value( World world )
{
return value;
}
}
public class AltitudeInit : IActorInit<int>
{
[FieldFromYamlKey]
public readonly int value = 0;
public AltitudeInit() { }
public AltitudeInit( int init )
{
value = init;
}
public int Value( World world )
{
return value;
}
} }
public class LocationInit : IActorInit<int2> public interface IActorInit {}
{
[FieldFromYamlKey] public interface IActorInit<T> : IActorInit
public readonly int2 value = int2.Zero; {
T Value( World world );
public LocationInit() { } }
public LocationInit( int2 init ) public class FacingInit : IActorInit<int>
{ {
value = init; [FieldFromYamlKey]
} public readonly int value = 128;
public int2 Value( World world ) public FacingInit() { }
{
return value; public FacingInit( int init )
} {
} value = init;
}
public class OwnerInit : IActorInit<Player>
{ public int Value( World world )
[FieldFromYamlKey] {
public readonly string PlayerName = "Neutral"; return value;
Player player; }
}
public OwnerInit() { }
public class AltitudeInit : IActorInit<int>
public OwnerInit( string playerName ) {
{ [FieldFromYamlKey]
this.PlayerName = playerName; public readonly int value = 0;
}
public AltitudeInit() { }
public OwnerInit( Player player )
{ public AltitudeInit( int init )
this.player = player; {
this.PlayerName = player.InternalName; value = init;
} }
public Player Value( World world ) public int Value( World world )
{ {
if( player != null ) return value;
return player; }
return world.players.Values.First( x => x.InternalName == PlayerName ); }
}
} public class LocationInit : IActorInit<int2>
} {
[FieldFromYamlKey]
public readonly int2 value = int2.Zero;
public LocationInit() { }
public LocationInit( int2 init )
{
value = init;
}
public int2 Value( World world )
{
return value;
}
}
public class OwnerInit : IActorInit<Player>
{
[FieldFromYamlKey]
public readonly string PlayerName = "Neutral";
Player player;
public OwnerInit() { }
public OwnerInit( string playerName )
{
this.PlayerName = playerName;
}
public OwnerInit( Player player )
{
this.player = player;
this.PlayerName = player.InternalName;
}
public Player Value( World world )
{
if( player != null )
return player;
return world.players.Values.First( x => x.InternalName == PlayerName );
}
}
}

View File

@@ -1,54 +1,54 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
public class ActorReference : IEnumerable public class ActorReference : IEnumerable
{ {
public readonly string Type; public readonly string Type;
public readonly TypeDictionary InitDict; public readonly TypeDictionary InitDict;
public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { } public ActorReference( string type ) : this( type, new Dictionary<string, MiniYaml>() ) { }
public ActorReference( string type, Dictionary<string, MiniYaml> inits ) public ActorReference( string type, Dictionary<string, MiniYaml> inits )
{ {
Type = type; Type = type;
InitDict = new TypeDictionary(); InitDict = new TypeDictionary();
foreach( var i in inits ) foreach( var i in inits )
InitDict.Add( LoadInit( i.Key, i.Value ) ); InitDict.Add( LoadInit( i.Key, i.Value ) );
} }
static IActorInit LoadInit(string traitName, MiniYaml my) static IActorInit LoadInit(string traitName, MiniYaml my)
{ {
var info = Game.CreateObject<IActorInit>(traitName + "Init"); var info = Game.CreateObject<IActorInit>(traitName + "Init");
FieldLoader.Load(info, my); FieldLoader.Load(info, my);
return info; return info;
} }
public MiniYaml Save() public MiniYaml Save()
{ {
var ret = new MiniYaml( Type ); var ret = new MiniYaml( Type );
foreach( var init in InitDict ) foreach( var init in InitDict )
{ {
var initName = init.GetType().Name; var initName = init.GetType().Name;
ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) ); ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) );
} }
return ret; return ret;
} }
// for initialization syntax // for initialization syntax
public void Add( object o ) { InitDict.Add( o ); } public void Add( object o ) { InitDict.Add( o ); }
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); } public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
} }
} }

View File

@@ -1,28 +1,28 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using OpenRA.Graphics; using OpenRA.Graphics;
namespace OpenRA namespace OpenRA
{ {
public class Cursor public class Cursor
{ {
CursorSequence sequence; CursorSequence sequence;
public Cursor(string cursor) public Cursor(string cursor)
{ {
sequence = CursorProvider.GetCursorSequence(cursor); sequence = CursorProvider.GetCursorSequence(cursor);
} }
public void Draw(int frame, float2 pos) public void Draw(int frame, float2 pos)
{ {
sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, Game.modData.Palette.GetPaletteIndex(sequence.Palette)); sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, Game.modData.Palette.GetPaletteIndex(sequence.Palette));
} }
} }
} }

View File

@@ -1,36 +1,36 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Effects namespace OpenRA.Effects
{ {
public class DelayedAction : IEffect public class DelayedAction : IEffect
{ {
Action a; Action a;
int delay; int delay;
public DelayedAction(int delay, Action a) public DelayedAction(int delay, Action a)
{ {
this.a = a; this.a = a;
this.delay = delay; this.delay = delay;
} }
public void Tick( World world ) public void Tick( World world )
{ {
if (--delay <= 0) if (--delay <= 0)
world.AddFrameEndTask(w => { w.Remove(this); a(); }); world.AddFrameEndTask(w => { w.Remove(this); a(); });
} }
public IEnumerable<Renderable> Render() { yield break; } public IEnumerable<Renderable> Render() { yield break; }
} }
} }

View File

@@ -1,45 +1,45 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Effects namespace OpenRA.Effects
{ {
public class FlashTarget : IEffect public class FlashTarget : IEffect
{ {
Actor target; Actor target;
int remainingTicks = 4; int remainingTicks = 4;
public FlashTarget(Actor target) public FlashTarget(Actor target)
{ {
this.target = target; this.target = target;
foreach (var e in target.World.Effects.OfType<FlashTarget>().Where(a => a.target == target).ToArray()) foreach (var e in target.World.Effects.OfType<FlashTarget>().Where(a => a.target == target).ToArray())
target.World.Remove(e); target.World.Remove(e);
} }
public void Tick( World world ) public void Tick( World world )
{ {
if (--remainingTicks == 0 || !target.IsInWorld) if (--remainingTicks == 0 || !target.IsInWorld)
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
} }
public IEnumerable<Renderable> Render() public IEnumerable<Renderable> Render()
{ {
if (!target.IsInWorld) if (!target.IsInWorld)
yield break; yield break;
if (remainingTicks % 2 == 0) if (remainingTicks % 2 == 0)
foreach (var r in target.Render()) foreach (var r in target.Render())
yield return r.WithPalette("highlight"); yield return r.WithPalette("highlight");
} }
} }
} }

View File

@@ -1,21 +1,21 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Effects namespace OpenRA.Effects
{ {
public interface IEffect public interface IEffect
{ {
void Tick( World world ); void Tick( World world );
IEnumerable<Renderable> Render(); IEnumerable<Renderable> Render();
} }
} }

View File

@@ -1,70 +1,70 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Support; using OpenRA.Support;
namespace OpenRA namespace OpenRA
{ {
public static class Exts public static class Exts
{ {
public static bool HasModifier(this Modifiers k, Modifiers mod) public static bool HasModifier(this Modifiers k, Modifiers mod)
{ {
return (k & mod) == mod; return (k & mod) == mod;
} }
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys) public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys)
{ {
// this is probably a shockingly-slow way to do this, but it's concise. // this is probably a shockingly-slow way to do this, but it's concise.
return xs.Except(ys).Concat(ys.Except(xs)); return xs.Except(ys).Concat(ys.Except(xs));
} }
public static float Product(this IEnumerable<float> xs) public static float Product(this IEnumerable<float> xs)
{ {
return xs.Aggregate(1f, (a, x) => a * x); return xs.Aggregate(1f, (a, x) => a * x);
} }
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k) public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k)
where V : new() where V : new()
{ {
return d.GetOrAdd(k, _ => new V()); return d.GetOrAdd(k, _ => new V());
} }
public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn) public static V GetOrAdd<K, V>(this Dictionary<K, V> d, K k, Func<K, V> createFn)
{ {
V ret; V ret;
if (!d.TryGetValue(k, out ret)) if (!d.TryGetValue(k, out ret))
d.Add(k, ret = createFn(k)); d.Add(k, ret = createFn(k));
return ret; return ret;
} }
public static T Random<T>(this IEnumerable<T> ts, Thirdparty.Random r) public static T Random<T>(this IEnumerable<T> ts, Thirdparty.Random r)
{ {
var xs = ts.ToArray(); var xs = ts.ToArray();
return xs[r.Next(xs.Length)]; return xs[r.Next(xs.Length)];
} }
public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time) public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text, double time)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
e.Do(x => e.Do(x =>
{ {
var t = sw.ElapsedTime(); var t = sw.ElapsedTime();
a(x); a(x);
var dt = sw.ElapsedTime() - t; var dt = sw.ElapsedTime() - t;
if (dt > time) if (dt > time)
Log.Write("perf", text, x, dt * 1000, Game.LocalTick); Log.Write("perf", text, x, dt * 1000, Game.LocalTick);
}); });
} }
} }
} }

View File

@@ -1,369 +1,369 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Network; using OpenRA.Network;
using OpenRA.Server; using OpenRA.Server;
using OpenRA.Support; using OpenRA.Support;
using OpenRA.Widgets; using OpenRA.Widgets;
using XRandom = OpenRA.Thirdparty.Random; using XRandom = OpenRA.Thirdparty.Random;
namespace OpenRA namespace OpenRA
{ {
public static class Game public static class Game
{ {
public static Utilities Utilities; public static Utilities Utilities;
public static int CellSize { get { return modData.Manifest.TileSize; } } public static int CellSize { get { return modData.Manifest.TileSize; } }
public static ModData modData; public static ModData modData;
private static WorldRenderer worldRenderer; private static WorldRenderer worldRenderer;
public static Viewport viewport; public static Viewport viewport;
public static Settings Settings; public static Settings Settings;
internal static OrderManager orderManager; internal static OrderManager orderManager;
static Server.Server server; static Server.Server server;
public static XRandom CosmeticRandom = new XRandom(); // not synced public static XRandom CosmeticRandom = new XRandom(); // not synced
public static Renderer Renderer; public static Renderer Renderer;
public static bool HasInputFocus = false; public static bool HasInputFocus = false;
public static void MoveViewport(float2 loc) public static void MoveViewport(float2 loc)
{ {
viewport.Center(loc); viewport.Center(loc);
} }
public static void JoinServer(string host, int port) public static void JoinServer(string host, int port)
{ {
var replayFilename = ChooseReplayFilename(); var replayFilename = ChooseReplayFilename();
string path = Path.Combine( Game.SupportDir, "Replays" ); string path = Path.Combine( Game.SupportDir, "Replays" );
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path ); if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
var replayFile = File.Create( Path.Combine( path, replayFilename ) ); var replayFile = File.Create( Path.Combine( path, replayFilename ) );
JoinInner(new OrderManager(host, port, JoinInner(new OrderManager(host, port,
new ReplayRecorderConnection(new NetworkConnection(host, port), replayFile))); new ReplayRecorderConnection(new NetworkConnection(host, port), replayFile)));
} }
static string ChooseReplayFilename() static string ChooseReplayFilename()
{ {
return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddTHHmmssZ.rep"); return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddTHHmmssZ.rep");
} }
static void JoinInner(OrderManager om) static void JoinInner(OrderManager om)
{ {
if (orderManager != null) orderManager.Dispose(); if (orderManager != null) orderManager.Dispose();
orderManager = om; orderManager = om;
lastConnectionState = ConnectionState.PreConnecting; lastConnectionState = ConnectionState.PreConnecting;
ConnectionStateChanged(orderManager); ConnectionStateChanged(orderManager);
} }
public static void JoinReplay(string replayFile) public static void JoinReplay(string replayFile)
{ {
JoinInner(new OrderManager("<no server>", -1, new ReplayConnection(replayFile))); JoinInner(new OrderManager("<no server>", -1, new ReplayConnection(replayFile)));
} }
static void JoinLocal() static void JoinLocal()
{ {
JoinInner(new OrderManager("<no server>", -1, new EchoConnection())); JoinInner(new OrderManager("<no server>", -1, new EchoConnection()));
} }
public static int RenderFrame = 0; public static int RenderFrame = 0;
public static int NetFrameNumber { get { return orderManager.NetFrameNumber; } } public static int NetFrameNumber { get { return orderManager.NetFrameNumber; } }
public static int LocalTick { get { return orderManager.LocalFrameNumber; } } public static int LocalTick { get { return orderManager.LocalFrameNumber; } }
const int NetTickScale = 3; // 120ms net tick for 40ms local tick const int NetTickScale = 3; // 120ms net tick for 40ms local tick
public static event Action<OrderManager> ConnectionStateChanged = _ => { }; public static event Action<OrderManager> ConnectionStateChanged = _ => { };
static ConnectionState lastConnectionState = ConnectionState.PreConnecting; static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } } public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
// Hacky workaround for orderManager visibility // Hacky workaround for orderManager visibility
public static Widget OpenWindow(World world, string widget) public static Widget OpenWindow(World world, string widget)
{ {
return Widget.OpenWindow(widget, new Dictionary<string,object>{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }}); return Widget.OpenWindow(widget, new Dictionary<string,object>{{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }});
} }
static ActionQueue afterTickActions = new ActionQueue(); static ActionQueue afterTickActions = new ActionQueue();
public static void RunAfterTick(Action a) { afterTickActions.Add(a); } public static void RunAfterTick(Action a) { afterTickActions.Add(a); }
static void Tick( OrderManager orderManager, Viewport viewPort ) static void Tick( OrderManager orderManager, Viewport viewPort )
{ {
if (orderManager.Connection.ConnectionState != lastConnectionState) if (orderManager.Connection.ConnectionState != lastConnectionState)
{ {
lastConnectionState = orderManager.Connection.ConnectionState; lastConnectionState = orderManager.Connection.ConnectionState;
ConnectionStateChanged( orderManager ); ConnectionStateChanged( orderManager );
} }
Tick( orderManager ); Tick( orderManager );
if( worldRenderer != null && orderManager.world != worldRenderer.world ) if( worldRenderer != null && orderManager.world != worldRenderer.world )
Tick( worldRenderer.world.orderManager ); Tick( worldRenderer.world.orderManager );
using (new PerfSample("render")) using (new PerfSample("render"))
{ {
++RenderFrame; ++RenderFrame;
viewport.DrawRegions(worldRenderer, new DefaultInputHandler( orderManager.world )); viewport.DrawRegions(worldRenderer, new DefaultInputHandler( orderManager.world ));
Sound.SetListenerPosition(viewport.Location + .5f * new float2(viewport.Width, viewport.Height)); Sound.SetListenerPosition(viewport.Location + .5f * new float2(viewport.Width, viewport.Height));
} }
PerfHistory.items["render"].Tick(); PerfHistory.items["render"].Tick();
PerfHistory.items["batches"].Tick(); PerfHistory.items["batches"].Tick();
MasterServerQuery.Tick(); MasterServerQuery.Tick();
afterTickActions.PerformActions(); afterTickActions.PerformActions();
} }
private static void Tick( OrderManager orderManager ) private static void Tick( OrderManager orderManager )
{ {
int t = Environment.TickCount; int t = Environment.TickCount;
int dt = t - orderManager.LastTickTime; int dt = t - orderManager.LastTickTime;
if (dt >= Settings.Game.Timestep) if (dt >= Settings.Game.Timestep)
using( new PerfSample( "tick_time" ) ) using( new PerfSample( "tick_time" ) )
{ {
orderManager.LastTickTime += Settings.Game.Timestep; orderManager.LastTickTime += Settings.Game.Timestep;
Widget.DoTick(); Widget.DoTick();
var world = orderManager.world; var world = orderManager.world;
if( orderManager.GameStarted && world.LocalPlayer != null ) if( orderManager.GameStarted && world.LocalPlayer != null )
++Viewport.TicksSinceLastMove; ++Viewport.TicksSinceLastMove;
Sound.Tick(); Sound.Tick();
Sync.CheckSyncUnchanged( world, () => { orderManager.TickImmediate(); } ); Sync.CheckSyncUnchanged( world, () => { orderManager.TickImmediate(); } );
if (world != null) if (world != null)
{ {
var isNetTick = LocalTick % NetTickScale == 0; var isNetTick = LocalTick % NetTickScale == 0;
if (!isNetTick || orderManager.IsReadyForNextFrame) if (!isNetTick || orderManager.IsReadyForNextFrame)
{ {
++orderManager.LocalFrameNumber; ++orderManager.LocalFrameNumber;
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local"); Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
if (isNetTick) orderManager.Tick(); if (isNetTick) orderManager.Tick();
Sync.CheckSyncUnchanged(world, () => Sync.CheckSyncUnchanged(world, () =>
{ {
world.OrderGenerator.Tick(world); world.OrderGenerator.Tick(world);
world.Selection.Tick(world); world.Selection.Tick(world);
}); });
world.Tick(); world.Tick();
PerfHistory.Tick(); PerfHistory.Tick();
} }
else else
if (orderManager.NetFrameNumber == 0) if (orderManager.NetFrameNumber == 0)
orderManager.LastTickTime = Environment.TickCount; orderManager.LastTickTime = Environment.TickCount;
} }
} }
} }
public static event Action LobbyInfoChanged = () => { }; public static event Action LobbyInfoChanged = () => { };
internal static void SyncLobbyInfo() internal static void SyncLobbyInfo()
{ {
LobbyInfoChanged(); LobbyInfoChanged();
} }
public static event Action<World> AfterGameStart = _ => {}; public static event Action<World> AfterGameStart = _ => {};
public static event Action BeforeGameStart = () => {}; public static event Action BeforeGameStart = () => {};
internal static void StartGame(string mapUID) internal static void StartGame(string mapUID)
{ {
BeforeGameStart(); BeforeGameStart();
var map = modData.PrepareMap(mapUID); var map = modData.PrepareMap(mapUID);
viewport = new Viewport(new int2(Renderer.Resolution), map.Bounds, Renderer); viewport = new Viewport(new int2(Renderer.Resolution), map.Bounds, Renderer);
orderManager.world = new World(modData.Manifest, map, orderManager); orderManager.world = new World(modData.Manifest, map, orderManager);
worldRenderer = new WorldRenderer(orderManager.world); worldRenderer = new WorldRenderer(orderManager.world);
if (orderManager.GameStarted) return; if (orderManager.GameStarted) return;
Widget.SelectedWidget = null; Widget.SelectedWidget = null;
orderManager.LocalFrameNumber = 0; orderManager.LocalFrameNumber = 0;
orderManager.StartGame(); orderManager.StartGame();
worldRenderer.RefreshPalette(); worldRenderer.RefreshPalette();
AfterGameStart( orderManager.world ); AfterGameStart( orderManager.world );
} }
public static bool IsHost public static bool IsHost
{ {
get { return orderManager.Connection.LocalClientId == 0; } get { return orderManager.Connection.LocalClientId == 0; }
} }
public static Dictionary<String, Mod> CurrentMods public static Dictionary<String, Mod> 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; static Modifiers modifiers;
public static Modifiers GetModifierKeys() { return modifiers; } public static Modifiers GetModifierKeys() { return modifiers; }
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; } internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
internal static void Initialize(Arguments args) internal static void Initialize(Arguments args)
{ {
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly; AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal) var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ Path.DirectorySeparatorChar + "OpenRA"; + Path.DirectorySeparatorChar + "OpenRA";
SupportDir = args.GetValue("SupportDir", defaultSupport); SupportDir = args.GetValue("SupportDir", defaultSupport);
FileSystem.SpecialPackageRoot = args.GetValue("SpecialPackageRoot", ""); FileSystem.SpecialPackageRoot = args.GetValue("SpecialPackageRoot", "");
Utilities = new Utilities(args.GetValue("UtilityPath", "OpenRA.Utility.exe")); Utilities = new Utilities(args.GetValue("UtilityPath", "OpenRA.Utility.exe"));
Settings = new Settings(SupportDir + "settings.yaml", args); Settings = new Settings(SupportDir + "settings.yaml", args);
Settings.Save(); Settings.Save();
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar; Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
Log.AddChannel("perf", "perf.log"); Log.AddChannel("perf", "perf.log");
Log.AddChannel("debug", "debug.log"); Log.AddChannel("debug", "debug.log");
Log.AddChannel("sync", "syncreport.log"); Log.AddChannel("sync", "syncreport.log");
FileSystem.Mount("."); // Needed to access shaders FileSystem.Mount("."); // Needed to access shaders
Renderer.Initialize( Game.Settings.Graphics.Mode ); Renderer.Initialize( Game.Settings.Graphics.Mode );
Renderer.SheetSize = Settings.Game.SheetSize; Renderer.SheetSize = Settings.Game.SheetSize;
Renderer = new Renderer(); Renderer = new Renderer();
Console.WriteLine("Available mods:"); Console.WriteLine("Available mods:");
foreach(var mod in Mod.AllMods) foreach(var mod in Mod.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
Sound.Create(); Sound.Create();
InitializeWithMods(Settings.Game.Mods); InitializeWithMods(Settings.Game.Mods);
} }
public static void InitializeWithMods(string[] mods) public static void InitializeWithMods(string[] mods)
{ {
// Clear static state if we have switched mods // Clear static state if we have switched mods
LobbyInfoChanged = () => {}; LobbyInfoChanged = () => {};
AddChatLine = (a,b,c) => {}; AddChatLine = (a,b,c) => {};
worldRenderer = null; worldRenderer = null;
if (server != null) if (server != null)
server.Shutdown(); server.Shutdown();
if (orderManager != null) if (orderManager != null)
orderManager.Dispose(); orderManager.Dispose();
// Discard any invalid mods // Discard any invalid mods
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray(); var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
Console.WriteLine("Loading mods: {0}",string.Join(",",mm)); Console.WriteLine("Loading mods: {0}",string.Join(",",mm));
Settings.Game.Mods = mm; Settings.Game.Mods = mm;
Settings.Save(); Settings.Save();
Sound.Initialize(); Sound.Initialize();
modData = new ModData( mm ); modData = new ModData( mm );
modData.LoadInitialAssets(); modData.LoadInitialAssets();
PerfHistory.items["render"].hasNormalTick = false; PerfHistory.items["render"].hasNormalTick = false;
PerfHistory.items["batches"].hasNormalTick = false; PerfHistory.items["batches"].hasNormalTick = false;
JoinLocal(); JoinLocal();
viewport = new Viewport(new int2(Renderer.Resolution), Rectangle.Empty, Renderer); viewport = new Viewport(new int2(Renderer.Resolution), Rectangle.Empty, Renderer);
Widget.RootWidget.RemoveChildren(); Widget.RootWidget.RemoveChildren();
modData.WidgetLoader.LoadWidget( new Dictionary<string,object>(), Widget.RootWidget, "INIT_SETUP" ); modData.WidgetLoader.LoadWidget( new Dictionary<string,object>(), Widget.RootWidget, "INIT_SETUP" );
} }
public static void LoadShellMap() public static void LoadShellMap()
{ {
StartGame(ChooseShellmap()); StartGame(ChooseShellmap());
Game.orderManager.LastTickTime = Environment.TickCount; Game.orderManager.LastTickTime = Environment.TickCount;
} }
static string ChooseShellmap() static string ChooseShellmap()
{ {
var shellmaps = modData.AvailableMaps var shellmaps = modData.AvailableMaps
.Where(m => m.Value.UseAsShellmap); .Where(m => m.Value.UseAsShellmap);
if (shellmaps.Count() == 0) if (shellmaps.Count() == 0)
throw new InvalidDataException("No valid shellmaps available"); throw new InvalidDataException("No valid shellmaps available");
return shellmaps.Random(CosmeticRandom).Key; return shellmaps.Random(CosmeticRandom).Key;
} }
static bool quit; static bool quit;
public static event Action OnQuit = () => {}; public static event Action OnQuit = () => {};
internal static void Run() internal static void Run()
{ {
while (!quit) while (!quit)
{ {
Tick( orderManager, viewport ); Tick( orderManager, viewport );
Application.DoEvents(); Application.DoEvents();
} }
OnQuit(); OnQuit();
} }
public static void Exit() { quit = true; } public static void Exit() { quit = true; }
public static Action<Color,string,string> AddChatLine = (c,n,s) => {}; public static Action<Color,string,string> AddChatLine = (c,n,s) => {};
public static void Debug(string s, params object[] args) public static void Debug(string s, params object[] args)
{ {
AddChatLine(Color.White, "Debug", String.Format(s,args)); AddChatLine(Color.White, "Debug", String.Format(s,args));
} }
public static void Disconnect() public static void Disconnect()
{ {
if (IsHost && server != null) if (IsHost && server != null)
server.Shutdown(); server.Shutdown();
orderManager.Dispose(); orderManager.Dispose();
var shellmap = ChooseShellmap(); var shellmap = ChooseShellmap();
JoinLocal(); JoinLocal();
StartGame(shellmap); StartGame(shellmap);
Widget.CloseWindow(); Widget.CloseWindow();
Widget.OpenWindow("MAINMENU_BG"); Widget.OpenWindow("MAINMENU_BG");
} }
static string baseSupportDir = null; static string baseSupportDir = null;
public static string SupportDir public static string SupportDir
{ {
set set
{ {
var dir = value; var dir = value;
// Expand paths relative to the personal directory // Expand paths relative to the personal directory
if (dir.ElementAt(0) == '~') if (dir.ElementAt(0) == '~')
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1); dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
if (!Directory.Exists(dir)) if (!Directory.Exists(dir))
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
baseSupportDir = dir + Path.DirectorySeparatorChar; baseSupportDir = dir + Path.DirectorySeparatorChar;
} }
get { return baseSupportDir; } get { return baseSupportDir; }
} }
public static T CreateObject<T>( string name ) public static T CreateObject<T>( string name )
{ {
return modData.ObjectCreator.CreateObject<T>( name ); return modData.ObjectCreator.CreateObject<T>( name );
} }
public static void CreateAndJoinServer(Settings settings, string map) public static void CreateAndJoinServer(Settings settings, string map)
{ {
server = new Server.Server(modData, settings, map); server = new Server.Server(modData, settings, map);
JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort); JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort);
} }
} }
} }

View File

@@ -1,99 +1,99 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA namespace OpenRA
{ {
public class ActorInfo public class ActorInfo
{ {
public readonly string Name; public readonly string Name;
public readonly TypeDictionary Traits = new TypeDictionary(); public readonly TypeDictionary Traits = new TypeDictionary();
public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits ) public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits )
{ {
var mergedNode = MergeWithParent( node, allUnits ).NodesDict; var mergedNode = MergeWithParent( node, allUnits ).NodesDict;
Name = name; Name = name;
foreach( var t in mergedNode ) foreach( var t in mergedNode )
if( t.Key != "Inherits" && !t.Key.StartsWith("-") ) if( t.Key != "Inherits" && !t.Key.StartsWith("-") )
Traits.Add( LoadTraitInfo( t.Key.Split('@')[0], t.Value ) ); Traits.Add( LoadTraitInfo( t.Key.Split('@')[0], t.Value ) );
} }
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits ) static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
{ {
MiniYaml inherits; MiniYaml inherits;
node.NodesDict.TryGetValue( "Inherits", out inherits ); node.NodesDict.TryGetValue( "Inherits", out inherits );
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) ) if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
return null; return null;
MiniYaml parent; MiniYaml parent;
allUnits.TryGetValue( inherits.Value, out parent ); allUnits.TryGetValue( inherits.Value, out parent );
if( parent == null ) if( parent == null )
return null; return null;
return parent; return parent;
} }
static MiniYaml MergeWithParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits ) static MiniYaml MergeWithParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
{ {
var parent = GetParent( node, allUnits ); var parent = GetParent( node, allUnits );
if( parent != null ) if( parent != null )
return MiniYaml.Merge( node, MergeWithParent( parent, allUnits ) ); return MiniYaml.Merge( node, MergeWithParent( parent, allUnits ) );
return node; return node;
} }
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my) static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my)
{ {
var info = Game.CreateObject<ITraitInfo>(traitName + "Info"); var info = Game.CreateObject<ITraitInfo>(traitName + "Info");
FieldLoader.Load(info, my); FieldLoader.Load(info, my);
return info; return info;
} }
public IEnumerable<ITraitInfo> TraitsInConstructOrder() public IEnumerable<ITraitInfo> TraitsInConstructOrder()
{ {
var ret = new List<ITraitInfo>(); var ret = new List<ITraitInfo>();
var t = Traits.WithInterface<ITraitInfo>().ToList(); var t = Traits.WithInterface<ITraitInfo>().ToList();
int index = 0; int index = 0;
while (t.Count != 0) while (t.Count != 0)
{ {
var prereqs = PrerequisitesOf(t[index]); var prereqs = PrerequisitesOf(t[index]);
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || x.GetType().IsSubclassOf(n))); var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || x.GetType().IsSubclassOf(n)));
if (!unsatisfied.Any()) if (!unsatisfied.Any())
{ {
ret.Add(t[index]); ret.Add(t[index]);
t.RemoveAt(index); t.RemoveAt(index);
index = 0; index = 0;
} }
else if (++index >= t.Count) else if (++index >= t.Count)
throw new InvalidOperationException("Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1} Missing={2}".F( throw new InvalidOperationException("Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1} Missing={2}".F(
Name, Name,
string.Join(",", t.Select(x => x.GetType().Name).ToArray()), string.Join(",", t.Select(x => x.GetType().Name).ToArray()),
string.Join(",", unsatisfied.Select(x => x.Name).ToArray()))); string.Join(",", unsatisfied.Select(x => x.Name).ToArray())));
} }
return ret; return ret;
} }
static List<Type> PrerequisitesOf( ITraitInfo info ) static List<Type> PrerequisitesOf( ITraitInfo info )
{ {
return info return info
.GetType() .GetType()
.GetInterfaces() .GetInterfaces()
.Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( ITraitPrerequisite<> ) ) .Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( ITraitPrerequisite<> ) )
.Select( t => t.GetGenericArguments()[ 0 ] ) .Select( t => t.GetGenericArguments()[ 0 ] )
.ToList(); .ToList();
} }
} }
} }

View File

@@ -1,34 +1,34 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
public class MusicInfo public class MusicInfo
{ {
public readonly string Filename = null; public readonly string Filename = null;
public readonly string Title = null; public readonly string Title = null;
public readonly int Length = 0; // seconds public readonly int Length = 0; // seconds
public readonly bool Exists = false; public readonly bool Exists = false;
public MusicInfo( string key, MiniYaml value ) public MusicInfo( string key, MiniYaml value )
{ {
Filename = key+".aud"; Filename = key+".aud";
Title = value.Value; Title = value.Value;
if (!FileSystem.Exists(Filename)) if (!FileSystem.Exists(Filename))
return; return;
Exists = true; Exists = true;
Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename)); Length = (int)AudLoader.SoundLength(FileSystem.Open(Filename));
} }
} }
} }

View File

@@ -1,52 +1,52 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.GameRules; using OpenRA.GameRules;
namespace OpenRA namespace OpenRA
{ {
public static class Rules public static class Rules
{ {
public static Dictionary<string, ActorInfo> Info; public static Dictionary<string, ActorInfo> Info;
public static Dictionary<string, WeaponInfo> Weapons; public static Dictionary<string, WeaponInfo> Weapons;
public static Dictionary<string, VoiceInfo> Voices; public static Dictionary<string, VoiceInfo> Voices;
public static Dictionary<string, MusicInfo> Music; public static Dictionary<string, MusicInfo> Music;
public static Dictionary<string, string> Movies; public static Dictionary<string, string> Movies;
public static Dictionary<string, TileSet> TileSets; public static Dictionary<string, TileSet> TileSets;
public static void LoadRules(Manifest m, Map map) public static void LoadRules(Manifest m, Map map)
{ {
// Added support to extend the list of rules (add it to m.LocalRules) // Added support to extend the list of rules (add it to m.LocalRules)
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y)); Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value)); Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value)); Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value)); Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value); Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
TileSets = new Dictionary<string, TileSet>(); TileSets = new Dictionary<string, TileSet>();
foreach (var file in m.TileSets) foreach (var file in m.TileSets)
{ {
var t = new TileSet(file); var t = new TileSet(file);
TileSets.Add(t.Id,t); TileSets.Add(t.Id,t);
} }
} }
static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f) static Dictionary<string, T> LoadYamlRules<T>(string[] files, List<MiniYamlNode> dict, Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
{ {
var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict,MiniYaml.Merge); var y = files.Select(a => MiniYaml.FromFile(a)).Aggregate(dict,MiniYaml.Merge);
var yy = y.ToDictionary( x => x.Key, x => x.Value ); var yy = y.ToDictionary( x => x.Key, x => x.Value );
return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy)); return y.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => f(kv, yy));
} }
} }
} }

View File

@@ -1,162 +1,162 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
using OpenRA.Server; using OpenRA.Server;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
public class ServerSettings public class ServerSettings
{ {
public string Name = "OpenRA Game"; public string Name = "OpenRA Game";
public int ListenPort = 1234; public int ListenPort = 1234;
public int ExternalPort = 1234; public int ExternalPort = 1234;
public bool AdvertiseOnline = true; public bool AdvertiseOnline = true;
public string MasterServer = "http://master.open-ra.org/"; public string MasterServer = "http://master.open-ra.org/";
public bool AllowCheats = false; public bool AllowCheats = false;
} }
public class DebugSettings public class DebugSettings
{ {
public bool BotDebug = false; public bool BotDebug = false;
public bool PerfGraph = false; public bool PerfGraph = false;
public float LongTickThreshold = 0.001f; public float LongTickThreshold = 0.001f;
public bool SanityCheckUnsyncedCode = false; public bool SanityCheckUnsyncedCode = false;
} }
public class GraphicSettings public class GraphicSettings
{ {
public string Renderer = "Gl"; public string Renderer = "Gl";
public WindowMode Mode = WindowMode.PseudoFullscreen; public WindowMode Mode = WindowMode.PseudoFullscreen;
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
public int2 WindowedSize = new int2(1024, 768); public int2 WindowedSize = new int2(1024, 768);
public readonly int2 MinResolution = new int2(800, 600); public readonly int2 MinResolution = new int2(800, 600);
} }
public class SoundSettings public class SoundSettings
{ {
public float SoundVolume = 0.5f; public float SoundVolume = 0.5f;
public float MusicVolume = 0.5f; public float MusicVolume = 0.5f;
public float VideoVolume = 0.5f; public float VideoVolume = 0.5f;
public bool Shuffle = false; public bool Shuffle = false;
public bool Repeat = false; public bool Repeat = false;
} }
public class PlayerSettings public class PlayerSettings
{ {
public string Name = "Newbie"; public string Name = "Newbie";
[Obsolete] public Color Color1 = Color.FromArgb(255,160,238); [Obsolete] public Color Color1 = Color.FromArgb(255,160,238);
[Obsolete] public Color Color2 = Color.FromArgb(68,0,56); [Obsolete] public Color Color2 = Color.FromArgb(68,0,56);
public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25); public ColorRamp ColorRamp = new ColorRamp(75, 255, 180, 25);
public string LastServer = "localhost:1234"; public string LastServer = "localhost:1234";
} }
public class GameSettings public class GameSettings
{ {
public string[] Mods = { "ra" }; public string[] Mods = { "ra" };
public bool MatchTimer = true; public bool MatchTimer = true;
// Chat settings // Chat settings
public bool TeamChatToggle = false; public bool TeamChatToggle = false;
// Behaviour settings // Behaviour settings
public bool ViewportEdgeScroll = true; public bool ViewportEdgeScroll = true;
public bool InverseDragScroll = false; public bool InverseDragScroll = false;
public float ViewportEdgeScrollStep = 10f; public float ViewportEdgeScrollStep = 10f;
// Internal game settings // Internal game settings
public int Timestep = 40; public int Timestep = 40;
public int SheetSize = 2048; public int SheetSize = 2048;
} }
public class Settings public class Settings
{ {
string SettingsFile; string SettingsFile;
public PlayerSettings Player = new PlayerSettings(); public PlayerSettings Player = new PlayerSettings();
public GameSettings Game = new GameSettings(); public GameSettings Game = new GameSettings();
public SoundSettings Sound = new SoundSettings(); public SoundSettings Sound = new SoundSettings();
public GraphicSettings Graphics = new GraphicSettings(); public GraphicSettings Graphics = new GraphicSettings();
public ServerSettings Server = new ServerSettings(); public ServerSettings Server = new ServerSettings();
public DebugSettings Debug = new DebugSettings(); public DebugSettings Debug = new DebugSettings();
public Dictionary<string, object> Sections; public Dictionary<string, object> Sections;
public Settings(string file, Arguments args) public Settings(string file, Arguments args)
{ {
SettingsFile = file; SettingsFile = file;
Sections = new Dictionary<string, object>() Sections = new Dictionary<string, object>()
{ {
{"Player", Player}, {"Player", Player},
{"Game", Game}, {"Game", Game},
{"Sound", Sound}, {"Sound", Sound},
{"Graphics", Graphics}, {"Graphics", Graphics},
{"Server", Server}, {"Server", Server},
{"Debug", Debug} {"Debug", Debug}
}; };
// Override fieldloader to ignore invalid entries // Override fieldloader to ignore invalid entries
var err1 = FieldLoader.UnknownFieldAction; var err1 = FieldLoader.UnknownFieldAction;
var err2 = FieldLoader.InvalidValueAction; var err2 = FieldLoader.InvalidValueAction;
FieldLoader.UnknownFieldAction = (s,f) => FieldLoader.UnknownFieldAction = (s,f) =>
{ {
Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) ); Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
}; };
if (File.Exists(SettingsFile)) if (File.Exists(SettingsFile))
{ {
//Console.WriteLine("Loading settings file {0}",SettingsFile); //Console.WriteLine("Loading settings file {0}",SettingsFile);
var yaml = MiniYaml.DictFromFile(SettingsFile); var yaml = MiniYaml.DictFromFile(SettingsFile);
foreach (var kv in Sections) foreach (var kv in Sections)
if (yaml.ContainsKey(kv.Key)) if (yaml.ContainsKey(kv.Key))
LoadSectionYaml(yaml[kv.Key], kv.Value); LoadSectionYaml(yaml[kv.Key], kv.Value);
} }
// Override with commandline args // Override with commandline args
foreach (var kv in Sections) foreach (var kv in Sections)
foreach (var f in kv.Value.GetType().GetFields()) foreach (var f in kv.Value.GetType().GetFields())
if (args.Contains(kv.Key+"."+f.Name)) if (args.Contains(kv.Key+"."+f.Name))
FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") ); FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
FieldLoader.UnknownFieldAction = err1; FieldLoader.UnknownFieldAction = err1;
FieldLoader.InvalidValueAction = err2; FieldLoader.InvalidValueAction = err2;
} }
public void Save() public void Save()
{ {
var root = new List<MiniYamlNode>(); var root = new List<MiniYamlNode>();
foreach( var kv in Sections ) foreach( var kv in Sections )
root.Add( new MiniYamlNode( kv.Key, FieldSaver.SaveDifferences(kv.Value, Activator.CreateInstance(kv.Value.GetType())) ) ); root.Add( new MiniYamlNode( kv.Key, FieldSaver.SaveDifferences(kv.Value, Activator.CreateInstance(kv.Value.GetType())) ) );
root.WriteToFile(SettingsFile); root.WriteToFile(SettingsFile);
} }
void LoadSectionYaml(MiniYaml yaml, object section) void LoadSectionYaml(MiniYaml yaml, object section)
{ {
object defaults = Activator.CreateInstance(section.GetType()); object defaults = Activator.CreateInstance(section.GetType());
FieldLoader.InvalidValueAction = (s,t,f) => FieldLoader.InvalidValueAction = (s,t,f) =>
{ {
object ret = defaults.GetType().GetField(f).GetValue(defaults); object ret = defaults.GetType().GetField(f).GetValue(defaults);
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) ); System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
return ret; return ret;
}; };
FieldLoader.Load(section, yaml); FieldLoader.Load(section, yaml);
} }
} }
} }

View File

@@ -1,76 +1,76 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using System; using System;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
public class VoiceInfo public class VoiceInfo
{ {
public readonly Dictionary<string,string[]> Variants; public readonly Dictionary<string,string[]> Variants;
public readonly Dictionary<string,string[]> Voices; public readonly Dictionary<string,string[]> Voices;
public readonly string DefaultVariant = ".aud" ; public readonly string DefaultVariant = ".aud" ;
[FieldLoader.Load] public readonly string[] DisableVariants = { }; [FieldLoader.Load] public readonly string[] DisableVariants = { };
static Dictionary<string, string[]> Load( MiniYaml y, string name ) static Dictionary<string, string[]> Load( MiniYaml y, string name )
{ {
return y.NodesDict.ContainsKey( name ) return y.NodesDict.ContainsKey( name )
? y.NodesDict[ name ].NodesDict.ToDictionary( ? y.NodesDict[ name ].NodesDict.ToDictionary(
a => a.Key, a => a.Key,
a => (string[])FieldLoader.GetValue( "(value)", typeof( string[] ), a.Value.Value ) ) a => (string[])FieldLoader.GetValue( "(value)", typeof( string[] ), a.Value.Value ) )
: new Dictionary<string, string[]>(); : new Dictionary<string, string[]>();
} }
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools; public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools;
public VoiceInfo( MiniYaml y ) public VoiceInfo( MiniYaml y )
{ {
FieldLoader.Load( this, y ); FieldLoader.Load( this, y );
Variants = Load(y, "Variants"); Variants = Load(y, "Variants");
Voices = Load(y, "Voices"); Voices = Load(y, "Voices");
if (!Voices.ContainsKey("Attack")) if (!Voices.ContainsKey("Attack"))
Voices.Add("Attack", Voices["Move"]); Voices.Add("Attack", Voices["Move"]);
if (!Voices.ContainsKey("AttackMove")) if (!Voices.ContainsKey("AttackMove"))
Voices.Add("AttackMove", Voices["Move"]); Voices.Add("AttackMove", Voices["Move"]);
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) )); Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
} }
} }
public class VoicePool public class VoicePool
{ {
readonly string[] clips; readonly string[] clips;
readonly List<string> liveclips = new List<string>(); readonly List<string> liveclips = new List<string>();
public VoicePool(params string[] clips) public VoicePool(params string[] clips)
{ {
this.clips = clips; this.clips = clips;
} }
public string GetNext() public string GetNext()
{ {
if (liveclips.Count == 0) if (liveclips.Count == 0)
liveclips.AddRange(clips); liveclips.AddRange(clips);
if (liveclips.Count == 0) if (liveclips.Count == 0)
return null; /* avoid crashing if there's no clips at all */ return null; /* avoid crashing if there's no clips at all */
var i = Game.CosmeticRandom.Next(liveclips.Count); var i = Game.CosmeticRandom.Next(liveclips.Count);
var s = liveclips[i]; var s = liveclips[i];
liveclips.RemoveAt(i); liveclips.RemoveAt(i);
return s; return s;
} }
} }
} }

View File

@@ -1,126 +1,126 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
using System.Linq; using System.Linq;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
public class WarheadInfo public class WarheadInfo
{ {
[FieldLoader.Load] public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2. [FieldLoader.Load] public readonly int Spread = 1; // distance (in pixels) from the explosion center at which damage is 1/2.
[FieldLoader.LoadUsing( "LoadVersus" )] [FieldLoader.LoadUsing( "LoadVersus" )]
public readonly Dictionary<string, float> Versus; // damage vs each armortype public readonly Dictionary<string, float> Versus; // damage vs each armortype
[FieldLoader.Load] public readonly bool Ore = false; // can this damage ore? [FieldLoader.Load] public readonly bool Ore = false; // can this damage ore?
[FieldLoader.Load] public readonly string Explosion = null; // explosion effect to use [FieldLoader.Load] public readonly string Explosion = null; // explosion effect to use
[FieldLoader.Load] public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash) [FieldLoader.Load] public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
[FieldLoader.Load] public readonly string SmudgeType = null; // type of smudge to apply [FieldLoader.Load] public readonly string SmudgeType = null; // type of smudge to apply
[FieldLoader.Load] public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner) [FieldLoader.Load] public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
[FieldLoader.Load] public readonly int InfDeath = 0; // infantry death animation to use [FieldLoader.Load] public readonly int InfDeath = 0; // infantry death animation to use
[FieldLoader.Load] public readonly string ImpactSound = null; // sound to play on impact [FieldLoader.Load] public readonly string ImpactSound = null; // sound to play on impact
[FieldLoader.Load] public readonly string WaterImpactSound = null; // sound to play on impact with water [FieldLoader.Load] public readonly string WaterImpactSound = null; // sound to play on impact with water
[FieldLoader.Load] public readonly int Damage = 0; // how much (raw) damage to deal [FieldLoader.Load] public readonly int Damage = 0; // how much (raw) damage to deal
[FieldLoader.Load] public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model) [FieldLoader.Load] public readonly int Delay = 0; // delay in ticks before dealing the damage. 0=instant (old model)
[FieldLoader.Load] public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use [FieldLoader.Load] public readonly DamageModel DamageModel = DamageModel.Normal; // which damage model to use
[FieldLoader.Load] public readonly bool PreventProne = false; // whether we should prevent prone response in infantry. [FieldLoader.Load] public readonly bool PreventProne = false; // whether we should prevent prone response in infantry.
public float EffectivenessAgainst(Actor self) public float EffectivenessAgainst(Actor self)
{ {
var health = self.Info.Traits.GetOrDefault<HealthInfo>(); var health = self.Info.Traits.GetOrDefault<HealthInfo>();
if (health == null) return 0f; if (health == null) return 0f;
var armor = self.Info.Traits.GetOrDefault<ArmorInfo>(); var armor = self.Info.Traits.GetOrDefault<ArmorInfo>();
if (armor == null || armor.Type == null) return 1; if (armor == null || armor.Type == null) return 1;
float versus; float versus;
return Versus.TryGetValue(armor.Type, out versus) ? versus : 1; return Versus.TryGetValue(armor.Type, out versus) ? versus : 1;
} }
public WarheadInfo( MiniYaml yaml ) public WarheadInfo( MiniYaml yaml )
{ {
FieldLoader.Load( this, yaml ); FieldLoader.Load( this, yaml );
} }
static object LoadVersus( MiniYaml y ) static object LoadVersus( MiniYaml y )
{ {
return y.NodesDict.ContainsKey( "Versus" ) return y.NodesDict.ContainsKey( "Versus" )
? y.NodesDict[ "Versus" ].NodesDict.ToDictionary( ? y.NodesDict[ "Versus" ].NodesDict.ToDictionary(
a => a.Key, a => a.Key,
a => (float)FieldLoader.GetValue( "(value)", typeof( float ), a.Value.Value ) ) a => (float)FieldLoader.GetValue( "(value)", typeof( float ), a.Value.Value ) )
: new Dictionary<string, float>(); : new Dictionary<string, float>();
} }
} }
public enum DamageModel public enum DamageModel
{ {
Normal, // classic RA damage model: point actors, distance-based falloff Normal, // classic RA damage model: point actors, distance-based falloff
PerCell, // like RA's "nuke damage" PerCell, // like RA's "nuke damage"
} }
public class ProjectileArgs public class ProjectileArgs
{ {
public WeaponInfo weapon; public WeaponInfo weapon;
public Actor firedBy; public Actor firedBy;
public int2 src; public int2 src;
public int srcAltitude; public int srcAltitude;
public int facing; public int facing;
public Target target; public Target target;
public int2 dest; public int2 dest;
public int destAltitude; public int destAltitude;
public float firepowerModifier = 1.0f; public float firepowerModifier = 1.0f;
} }
public interface IProjectileInfo { IEffect Create(ProjectileArgs args); } public interface IProjectileInfo { IEffect Create(ProjectileArgs args); }
public class WeaponInfo public class WeaponInfo
{ {
[FieldLoader.Load] public readonly float Range = 0; [FieldLoader.Load] public readonly float Range = 0;
[FieldLoader.Load] public readonly string Report = null; [FieldLoader.Load] public readonly string Report = null;
[FieldLoader.Load] public readonly int ROF = 1; [FieldLoader.Load] public readonly int ROF = 1;
[FieldLoader.Load] public readonly int Burst = 1; [FieldLoader.Load] public readonly int Burst = 1;
[FieldLoader.Load] public readonly bool Charges = false; [FieldLoader.Load] public readonly bool Charges = false;
[FieldLoader.Load] public readonly bool Underwater = false; [FieldLoader.Load] public readonly bool Underwater = false;
[FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" }; [FieldLoader.Load] public readonly string[] ValidTargets = { "Ground" };
[FieldLoader.Load] public readonly int BurstDelay = 5; [FieldLoader.Load] public readonly int BurstDelay = 5;
[FieldLoader.Load] public readonly float MinRange = 0; [FieldLoader.Load] public readonly float MinRange = 0;
[FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile; [FieldLoader.LoadUsing( "LoadProjectile" )] public IProjectileInfo Projectile;
[FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads; [FieldLoader.LoadUsing( "LoadWarheads" )] public List<WarheadInfo> Warheads;
public WeaponInfo(string name, MiniYaml content) public WeaponInfo(string name, MiniYaml content)
{ {
FieldLoader.Load( this, content ); FieldLoader.Load( this, content );
} }
static object LoadProjectile( MiniYaml yaml ) static object LoadProjectile( MiniYaml yaml )
{ {
MiniYaml proj; MiniYaml proj;
if( !yaml.NodesDict.TryGetValue( "Projectile", out proj ) ) if( !yaml.NodesDict.TryGetValue( "Projectile", out proj ) )
return null; return null;
var ret = Game.CreateObject<IProjectileInfo>( proj.Value + "Info" ); var ret = Game.CreateObject<IProjectileInfo>( proj.Value + "Info" );
FieldLoader.Load( ret, proj ); FieldLoader.Load( ret, proj );
return ret; return ret;
} }
static object LoadWarheads( MiniYaml yaml ) static object LoadWarheads( MiniYaml yaml )
{ {
var ret = new List<WarheadInfo>(); var ret = new List<WarheadInfo>();
foreach( var w in yaml.Nodes ) foreach( var w in yaml.Nodes )
if( w.Key.Split( '@' )[ 0 ] == "Warhead" ) if( w.Key.Split( '@' )[ 0 ] == "Warhead" )
ret.Add( new WarheadInfo( w.Value ) ); ret.Add( new WarheadInfo( w.Value ) );
return ret; return ret;
} }
} }
} }

View File

@@ -1,145 +1,145 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Animation public class Animation
{ {
string name; string name;
public Sequence CurrentSequence { get; private set; } public Sequence CurrentSequence { get; private set; }
int frame = 0; int frame = 0;
bool backwards = false; bool backwards = false;
bool tickAlways; bool tickAlways;
Func<int> facingFunc; Func<int> facingFunc;
public string Name { get { return name; } } public string Name { get { return name; } }
public Animation( string name ) public Animation( string name )
: this( name, () => 0 ) : this( name, () => 0 )
{ {
} }
public Animation( string name, Func<int> facingFunc ) public Animation( string name, Func<int> facingFunc )
{ {
this.name = name.ToLowerInvariant(); this.name = name.ToLowerInvariant();
this.tickFunc = () => { }; this.tickFunc = () => { };
this.facingFunc = facingFunc; this.facingFunc = facingFunc;
} }
public Sprite Image public Sprite Image
{ {
get get
{ {
return backwards return backwards
? CurrentSequence.GetSprite(CurrentSequence.End - frame - 1, facingFunc()) ? CurrentSequence.GetSprite(CurrentSequence.End - frame - 1, facingFunc())
: CurrentSequence.GetSprite(frame, facingFunc()); : CurrentSequence.GetSprite(frame, facingFunc());
} }
} }
public void Play( string sequenceName ) public void Play( string sequenceName )
{ {
PlayThen(sequenceName, () => { }); PlayThen(sequenceName, () => { });
} }
public void PlayRepeating( string sequenceName ) public void PlayRepeating( string sequenceName )
{ {
PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) ); PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) );
} }
public bool ReplaceAnim(string sequenceName) public bool ReplaceAnim(string sequenceName)
{ {
if (!HasSequence(sequenceName)) if (!HasSequence(sequenceName))
return false; return false;
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName); CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
frame %= CurrentSequence.Length; frame %= CurrentSequence.Length;
return true; return true;
} }
public void PlayThen( string sequenceName, Action after ) public void PlayThen( string sequenceName, Action after )
{ {
after = after ?? ( () => { } ); after = after ?? ( () => { } );
backwards = false; backwards = false;
tickAlways = false; tickAlways = false;
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName ); CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
frame = 0; frame = 0;
tickFunc = () => tickFunc = () =>
{ {
++frame; ++frame;
if( frame >= CurrentSequence.Length ) if( frame >= CurrentSequence.Length )
{ {
frame = CurrentSequence.Length - 1; frame = CurrentSequence.Length - 1;
tickFunc = () => { }; tickFunc = () => { };
after(); after();
} }
}; };
} }
public void PlayBackwardsThen(string sequenceName, Action after) public void PlayBackwardsThen(string sequenceName, Action after)
{ {
PlayThen(sequenceName, after); PlayThen(sequenceName, after);
backwards = true; backwards = true;
} }
public void PlayFetchIndex( string sequenceName, Func<int> func ) public void PlayFetchIndex( string sequenceName, Func<int> func )
{ {
backwards = false; backwards = false;
tickAlways = true; tickAlways = true;
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName ); CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
frame = func(); frame = func();
tickFunc = () => frame = func(); tickFunc = () => frame = func();
} }
int timeUntilNextFrame; int timeUntilNextFrame;
Action tickFunc; Action tickFunc;
public void Tick() public void Tick()
{ {
Tick( 40 ); // tick one frame 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 ) public void Tick( int t )
{ {
if( tickAlways ) if( tickAlways )
tickFunc(); tickFunc();
else else
{ {
timeUntilNextFrame -= t; timeUntilNextFrame -= t;
while( timeUntilNextFrame <= 0 ) while( timeUntilNextFrame <= 0 )
{ {
tickFunc(); tickFunc();
timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : 40; // 25 fps == 40 ms timeUntilNextFrame += CurrentSequence != null ? CurrentSequence.Tick : 40; // 25 fps == 40 ms
} }
} }
} }
public void ChangeImage(string newImage, string newAnimIfMissing) public void ChangeImage(string newImage, string newAnimIfMissing)
{ {
newImage = newImage.ToLowerInvariant(); newImage = newImage.ToLowerInvariant();
if (name != newImage) if (name != newImage)
{ {
name = newImage.ToLowerInvariant(); name = newImage.ToLowerInvariant();
if (!ReplaceAnim(CurrentSequence.Name)) if (!ReplaceAnim(CurrentSequence.Name))
ReplaceAnim(newAnimIfMissing); ReplaceAnim(newAnimIfMissing);
} }
} }
public Sequence GetSequence( string sequenceName ) public Sequence GetSequence( string sequenceName )
{ {
return SequenceProvider.GetSequence( name, sequenceName ); return SequenceProvider.GetSequence( name, sequenceName );
} }
} }
} }

View File

@@ -1,87 +1,87 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml; using System.Xml;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public static class ChromeProvider public static class ChromeProvider
{ {
static Dictionary<string, Dictionary<string, MappedImage>> collections; static Dictionary<string, Dictionary<string, MappedImage>> collections;
static Dictionary<string, Sheet> cachedSheets; static Dictionary<string, Sheet> cachedSheets;
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites; static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
public static void Initialize(params string[] chromeFiles) public static void Initialize(params string[] chromeFiles)
{ {
collections = new Dictionary<string, Dictionary<string, MappedImage>>(); collections = new Dictionary<string, Dictionary<string, MappedImage>>();
cachedSheets = new Dictionary<string, Sheet>(); cachedSheets = new Dictionary<string, Sheet>();
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>(); cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
foreach (var f in chromeFiles) foreach (var f in chromeFiles)
LoadChromeSource(f); LoadChromeSource(f);
} }
static void LoadChromeSource(string filename) static void LoadChromeSource(string filename)
{ {
XmlDocument document = new XmlDocument(); XmlDocument document = new XmlDocument();
document.Load(FileSystem.Open(filename)); document.Load(FileSystem.Open(filename));
foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection")) foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection"))
LoadChromeForCollection(eCollection); LoadChromeForCollection(eCollection);
} }
static void LoadChromeForCollection(XmlElement eCollection) static void LoadChromeForCollection(XmlElement eCollection)
{ {
string elementName = eCollection.GetAttribute("name"); string elementName = eCollection.GetAttribute("name");
string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null); string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null);
var images = eCollection.SelectNodes("./image").OfType<XmlElement>() var images = eCollection.SelectNodes("./image").OfType<XmlElement>()
.Select(e => new MappedImage(defaultSrc, e)) .Select(e => new MappedImage(defaultSrc, e))
.ToDictionary(s => s.Name); .ToDictionary(s => s.Name);
collections.Add(elementName, images); collections.Add(elementName, images);
} }
public static Sprite GetImage(string collection, string image) public static Sprite GetImage(string collection, string image)
{ {
// Cached sprite // Cached sprite
if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image)) if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image))
return cachedSprites[collection][image]; return cachedSprites[collection][image];
MappedImage mi; MappedImage mi;
try { mi = collections[collection][image]; } try { mi = collections[collection][image]; }
catch (KeyNotFoundException) catch (KeyNotFoundException)
{ {
throw new InvalidOperationException( throw new InvalidOperationException(
"Collection `{0}` does not have an image `{1}`".F(collection, image)); "Collection `{0}` does not have an image `{1}`".F(collection, image));
} }
// Cached sheet // Cached sheet
Sheet sheet; Sheet sheet;
if (cachedSheets.ContainsKey(mi.Src)) if (cachedSheets.ContainsKey(mi.Src))
sheet = cachedSheets[mi.Src]; sheet = cachedSheets[mi.Src];
else else
{ {
sheet = new Sheet(mi.Src); sheet = new Sheet(mi.Src);
cachedSheets.Add(mi.Src, sheet); cachedSheets.Add(mi.Src, sheet);
} }
// Cache the sprite // Cache the sprite
if (!cachedSprites.ContainsKey(collection)) if (!cachedSprites.ContainsKey(collection))
cachedSprites.Add(collection, new Dictionary<string, Sprite>()); cachedSprites.Add(collection, new Dictionary<string, Sprite>());
cachedSprites[collection].Add(image, mi.GetImage(sheet)); cachedSprites[collection].Add(image, mi.GetImage(sheet));
return cachedSprites[collection][image]; return cachedSprites[collection][image];
} }
} }
} }

View File

@@ -1,10 +1,10 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion

View File

@@ -1,57 +1,57 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Xml; using System.Xml;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class CursorSequence public class CursorSequence
{ {
readonly int start, length; readonly int start, length;
readonly string palette; readonly string palette;
public int Start { get { return start; } } public int Start { get { return start; } }
public int End { get { return start + length; } } public int End { get { return start + length; } }
public int Length { get { return length; } } public int Length { get { return length; } }
public string Palette { get { return palette; } } public string Palette { get { return palette; } }
public readonly int2 Hotspot; public readonly int2 Hotspot;
Sprite[] sprites; Sprite[] sprites;
public CursorSequence(string cursorSrc, string palette, MiniYaml info) public CursorSequence(string cursorSrc, string palette, MiniYaml info)
{ {
sprites = Game.modData.CursorSheetBuilder.LoadAllSprites(cursorSrc); sprites = Game.modData.CursorSheetBuilder.LoadAllSprites(cursorSrc);
var d = info.NodesDict; var d = info.NodesDict;
start = int.Parse(d["start"].Value); start = int.Parse(d["start"].Value);
this.palette = palette; this.palette = palette;
if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*")) if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*"))
length = sprites.Length - start; length = sprites.Length - start;
else if (d.ContainsKey("length")) else if (d.ContainsKey("length"))
length = int.Parse(d["length"].Value); length = int.Parse(d["length"].Value);
else if (d.ContainsKey("end")) else if (d.ContainsKey("end"))
length = int.Parse(d["end"].Value) - start; length = int.Parse(d["end"].Value) - start;
else else
length = 1; length = 1;
if (d.ContainsKey("x")) if (d.ContainsKey("x"))
int.TryParse(d["x"].Value, out Hotspot.X ); int.TryParse(d["x"].Value, out Hotspot.X );
if (d.ContainsKey("y")) if (d.ContainsKey("y"))
int.TryParse(d["y"].Value, out Hotspot.Y ); int.TryParse(d["y"].Value, out Hotspot.Y );
} }
public Sprite GetSprite(int frame) public Sprite GetSprite(int frame)
{ {
return sprites[(frame % length) + start]; return sprites[(frame % length) + start];
} }
} }
} }

View File

@@ -1,45 +1,45 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class CursorSheetBuilder public class CursorSheetBuilder
{ {
ModData modData; ModData modData;
Cache<string, Sprite[]> cursors; Cache<string, Sprite[]> cursors;
readonly string[] exts = { ".shp" }; readonly string[] exts = { ".shp" };
public CursorSheetBuilder( ModData modData ) public CursorSheetBuilder( ModData modData )
{ {
this.modData = modData; this.modData = modData;
this.cursors = new Cache<string, Sprite[]>( LoadCursors ); this.cursors = new Cache<string, Sprite[]>( LoadCursors );
} }
Sprite[] LoadCursors(string filename) Sprite[] LoadCursors(string filename)
{ {
try try
{ {
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts)); var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
return shp.Select(a => modData.SheetBuilder.Add(a.Image, a.Size)).ToArray(); return shp.Select(a => modData.SheetBuilder.Add(a.Image, a.Size)).ToArray();
} }
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
{ {
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts)); var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
return shp.Select(a => modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray(); return shp.Select(a => modData.SheetBuilder.Add(a.Image, shp.Size)).ToArray();
} }
} }
public Sprite[] LoadAllSprites(string filename) { return cursors[filename]; } public Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
} }
} }

View File

@@ -1,82 +1,82 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class HardwarePalette public class HardwarePalette
{ {
public const int MaxPalettes = 64; public const int MaxPalettes = 64;
int allocated = 0; int allocated = 0;
ITexture texture; ITexture texture;
Dictionary<string, Palette> palettes; Dictionary<string, Palette> palettes;
Dictionary<string, int> indices; Dictionary<string, int> indices;
public HardwarePalette() public HardwarePalette()
{ {
palettes = new Dictionary<string, Palette>(); palettes = new Dictionary<string, Palette>();
indices = new Dictionary<string, int>(); indices = new Dictionary<string, int>();
texture = Game.Renderer.Device.CreateTexture(); texture = Game.Renderer.Device.CreateTexture();
} }
public Palette GetPalette(string name) public Palette GetPalette(string name)
{ {
Palette ret; Palette ret;
if (!palettes.TryGetValue(name,out ret)) if (!palettes.TryGetValue(name,out ret))
throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return ret; return ret;
} }
public int GetPaletteIndex(string name) public int GetPaletteIndex(string name)
{ {
int ret; int ret;
if (!indices.TryGetValue(name,out ret)) if (!indices.TryGetValue(name,out ret))
throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return ret; return ret;
} }
public void AddPalette(string name, Palette p) public void AddPalette(string name, Palette p)
{ {
if (palettes.ContainsKey(name)) if (palettes.ContainsKey(name))
throw new InvalidOperationException("Palette {0} has already been defined".F(name)); throw new InvalidOperationException("Palette {0} has already been defined".F(name));
palettes.Add(name, p); palettes.Add(name, p);
indices.Add(name, allocated++); indices.Add(name, allocated++);
} }
public void Update(IEnumerable<IPaletteModifier> paletteMods) public void Update(IEnumerable<IPaletteModifier> paletteMods)
{ {
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value)); var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
foreach (var mod in paletteMods) foreach (var mod in paletteMods)
mod.AdjustPalette(copy); mod.AdjustPalette(copy);
var data = new uint[MaxPalettes,256]; var data = new uint[MaxPalettes,256];
foreach (var pal in copy) foreach (var pal in copy)
{ {
var j = indices[pal.Key]; var j = indices[pal.Key];
var c = pal.Value.Values; var c = pal.Value.Values;
for (var i = 0; i < 256; i++) for (var i = 0; i < 256; i++)
data[j,i] = c[i]; data[j,i] = c[i];
} }
// Doesn't work // Doesn't work
texture.SetData(data); texture.SetData(data);
Game.Renderer.PaletteTexture = texture; Game.Renderer.PaletteTexture = texture;
} }
} }
} }

View File

@@ -1,77 +1,77 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class LineRenderer : Renderer.IBatchRenderer public class LineRenderer : Renderer.IBatchRenderer
{ {
Renderer renderer; Renderer renderer;
Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ]; Vertex[] vertices = new Vertex[ Renderer.TempBufferSize ];
ushort[] indices = new ushort[ Renderer.TempBufferSize ]; ushort[] indices = new ushort[ Renderer.TempBufferSize ];
int nv = 0, ni = 0; int nv = 0, ni = 0;
public LineRenderer( Renderer renderer ) public LineRenderer( Renderer renderer )
{ {
this.renderer = renderer; this.renderer = renderer;
} }
public void Flush() public void Flush()
{ {
if( ni > 0 ) if( ni > 0 )
{ {
renderer.LineShader.Render( () => renderer.LineShader.Render( () =>
{ {
var vb = renderer.GetTempVertexBuffer(); var vb = renderer.GetTempVertexBuffer();
var ib = renderer.GetTempIndexBuffer(); var ib = renderer.GetTempIndexBuffer();
vb.SetData( vertices, nv ); vb.SetData( vertices, nv );
ib.SetData( indices, ni ); ib.SetData( indices, ni );
renderer.DrawBatch( vb, ib, renderer.DrawBatch( vb, ib,
nv, ni / 2, PrimitiveType.LineList ); nv, ni / 2, PrimitiveType.LineList );
} ); } );
nv = 0; ni = 0; nv = 0; ni = 0;
} }
} }
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor ) public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
{ {
Renderer.CurrentBatchRenderer = this; Renderer.CurrentBatchRenderer = this;
if( ni + 2 > Renderer.TempBufferSize ) if( ni + 2 > Renderer.TempBufferSize )
Flush(); Flush();
if( nv + 2 > Renderer.TempBufferSize ) if( nv + 2 > Renderer.TempBufferSize )
Flush(); Flush();
indices[ ni++ ] = (ushort)nv; indices[ ni++ ] = (ushort)nv;
vertices[ nv++ ] = new Vertex( start, vertices[ nv++ ] = new Vertex( start,
new float2( startColor.R / 255.0f, startColor.G / 255.0f ), new float2( startColor.R / 255.0f, startColor.G / 255.0f ),
new float2( startColor.B / 255.0f, startColor.A / 255.0f ) ); new float2( startColor.B / 255.0f, startColor.A / 255.0f ) );
indices[ ni++ ] = (ushort)nv; indices[ ni++ ] = (ushort)nv;
vertices[ nv++ ] = new Vertex( end, vertices[ nv++ ] = new Vertex( end,
new float2( endColor.R / 255.0f, endColor.G / 255.0f ), new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) ); new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
} }
public void FillRect( RectangleF r, Color color ) public void FillRect( RectangleF r, Color color )
{ {
for (float y = r.Top; y < r.Bottom; y++) for (float y = r.Top; y < r.Bottom; y++)
{ {
DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color); DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color);
} }
} }
} }
} }

View File

@@ -1,41 +1,41 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
class MappedImage class MappedImage
{ {
readonly Rectangle rect; readonly Rectangle rect;
public readonly string Src; public readonly string Src;
public readonly string Name; public readonly string Name;
public MappedImage(string defaultSrc, XmlElement e) public MappedImage(string defaultSrc, XmlElement e)
{ {
Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc; Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc;
Name = e.GetAttribute("name"); Name = e.GetAttribute("name");
if (Src == null) if (Src == null)
throw new InvalidDataException("Image src missing"); throw new InvalidDataException("Image src missing");
rect = new Rectangle(int.Parse(e.GetAttribute("x")), rect = new Rectangle(int.Parse(e.GetAttribute("x")),
int.Parse(e.GetAttribute("y")), int.Parse(e.GetAttribute("y")),
int.Parse(e.GetAttribute("width")), int.Parse(e.GetAttribute("width")),
int.Parse(e.GetAttribute("height"))); int.Parse(e.GetAttribute("height")));
} }
public Sprite GetImage(Sheet s) public Sprite GetImage(Sheet s)
{ {
return new Sprite(s, rect, TextureChannel.Alpha); return new Sprite(s, rect, TextureChannel.Alpha);
} }
} }
} }

View File

@@ -1,195 +1,195 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Traits; using OpenRA.Traits;
using System.IO; using System.IO;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Minimap public class Minimap
{ {
public static Bitmap TerrainBitmap(Map map) public static Bitmap TerrainBitmap(Map map)
{ {
return TerrainBitmap(map, false); return TerrainBitmap(map, false);
} }
public static Bitmap TerrainBitmap(Map map, bool actualSize) public static Bitmap TerrainBitmap(Map map, bool actualSize)
{ {
var tileset = Rules.TileSets[map.Tileset]; var tileset = Rules.TileSets[map.Tileset];
var width = map.Bounds.Width; var width = map.Bounds.Width;
var height = map.Bounds.Height; var height = map.Bounds.Height;
if (!actualSize) if (!actualSize)
{ {
width = height = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); width = height = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
} }
Bitmap terrain = new Bitmap(width, height); Bitmap terrain = new Bitmap(width, height);
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height), var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe unsafe
{ {
int* c = (int*)bitmapData.Scan0; int* c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++) for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++) for (var y = 0; y < map.Bounds.Height; y++)
{ {
var mapX = x + map.Bounds.Left; var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top; var mapY = y + map.Bounds.Top;
var type = tileset.GetTerrainType(map.MapTiles.Value[mapX, mapY]); var type = tileset.GetTerrainType(map.MapTiles.Value[mapX, mapY]);
if (!tileset.Terrain.ContainsKey(type)) if (!tileset.Terrain.ContainsKey(type))
throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type)); throw new InvalidDataException("Tileset {0} lacks terraintype {1}".F(tileset.Id, type));
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb(); *(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[type].Color.ToArgb();
} }
} }
terrain.UnlockBits(bitmapData); terrain.UnlockBits(bitmapData);
return terrain; return terrain;
} }
// Add the static resources defined in the map; if the map lives // Add the static resources defined in the map; if the map lives
// in a world use AddCustomTerrain instead // in a world use AddCustomTerrain instead
public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap) public static Bitmap AddStaticResources(Map map, Bitmap terrainBitmap)
{ {
Bitmap terrain = new Bitmap(terrainBitmap); Bitmap terrain = new Bitmap(terrainBitmap);
var tileset = Rules.TileSets[map.Tileset]; var tileset = Rules.TileSets[map.Tileset];
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height), var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe unsafe
{ {
int* c = (int*)bitmapData.Scan0; int* c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++) for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++) for (var y = 0; y < map.Bounds.Height; y++)
{ {
var mapX = x + map.Bounds.Left; var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top; var mapY = y + map.Bounds.Top;
if (map.MapResources.Value[mapX, mapY].type == 0) if (map.MapResources.Value[mapX, mapY].type == 0)
continue; continue;
var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>() var res = Rules.Info["world"].Traits.WithInterface<ResourceTypeInfo>()
.Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].type) .Where(t => t.ResourceType == map.MapResources.Value[mapX, mapY].type)
.Select(t => t.TerrainType).FirstOrDefault(); .Select(t => t.TerrainType).FirstOrDefault();
if (res == null) if (res == null)
continue; continue;
*(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[res].Color.ToArgb(); *(c + (y * bitmapData.Stride >> 2) + x) = tileset.Terrain[res].Color.ToArgb();
} }
} }
terrain.UnlockBits(bitmapData); terrain.UnlockBits(bitmapData);
return terrain; return terrain;
} }
public static Bitmap CustomTerrainBitmap(World world) public static Bitmap CustomTerrainBitmap(World world)
{ {
var map = world.Map; var map = world.Map;
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
Bitmap bitmap = new Bitmap(size, size); Bitmap bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe unsafe
{ {
int* c = (int*)bitmapData.Scan0; int* c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++) for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++) for (var y = 0; y < map.Bounds.Height; y++)
{ {
var mapX = x + map.Bounds.Left; var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top; var mapY = y + map.Bounds.Top;
var custom = map.CustomTerrain[mapX,mapY]; var custom = map.CustomTerrain[mapX,mapY];
if (custom == null) if (custom == null)
continue; continue;
*(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb(); *(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet.Terrain[custom].Color.ToArgb();
} }
} }
bitmap.UnlockBits(bitmapData); bitmap.UnlockBits(bitmapData);
return bitmap; return bitmap;
} }
public static Bitmap ActorsBitmap(World world) public static Bitmap ActorsBitmap(World world)
{ {
var map = world.Map; var map = world.Map;
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
Bitmap bitmap = new Bitmap(size, size); Bitmap bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe unsafe
{ {
int* c = (int*)bitmapData.Scan0; int* c = (int*)bitmapData.Scan0;
foreach (var t in world.Queries.WithTrait<IRadarSignature>()) foreach (var t in world.Queries.WithTrait<IRadarSignature>())
{ {
if (!world.LocalShroud.IsVisible(t.Actor)) if (!world.LocalShroud.IsVisible(t.Actor))
continue; continue;
var color = t.Trait.RadarSignatureColor(t.Actor); var color = t.Trait.RadarSignatureColor(t.Actor);
foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) foreach (var cell in t.Trait.RadarSignatureCells(t.Actor))
if (world.Map.IsInMap(cell)) if (world.Map.IsInMap(cell))
*(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb(); *(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb();
} }
} }
bitmap.UnlockBits(bitmapData); bitmap.UnlockBits(bitmapData);
return bitmap; return bitmap;
} }
public static Bitmap ShroudBitmap(World world) public static Bitmap ShroudBitmap(World world)
{ {
var map = world.Map; var map = world.Map;
var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); var size = Util.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
Bitmap bitmap = new Bitmap(size, size); Bitmap bitmap = new Bitmap(size, size);
if (world.LocalShroud.Disabled) if (world.LocalShroud.Disabled)
return bitmap; return bitmap;
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var shroud = Color.Black.ToArgb(); var shroud = Color.Black.ToArgb();
var fog = Color.FromArgb(128, Color.Black).ToArgb(); var fog = Color.FromArgb(128, Color.Black).ToArgb();
unsafe unsafe
{ {
int* c = (int*)bitmapData.Scan0; int* c = (int*)bitmapData.Scan0;
for (var x = 0; x < map.Bounds.Width; x++) for (var x = 0; x < map.Bounds.Width; x++)
for (var y = 0; y < map.Bounds.Height; y++) for (var y = 0; y < map.Bounds.Height; y++)
{ {
var mapX = x + map.Bounds.Left; var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top; var mapY = y + map.Bounds.Top;
if (!world.LocalShroud.IsExplored(mapX, mapY)) if (!world.LocalShroud.IsExplored(mapX, mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = shroud; *(c + (y * bitmapData.Stride >> 2) + x) = shroud;
else if (!world.LocalShroud.IsVisible(mapX,mapY)) else if (!world.LocalShroud.IsVisible(mapX,mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = fog; *(c + (y * bitmapData.Stride >> 2) + x) = fog;
} }
} }
bitmap.UnlockBits(bitmapData); bitmap.UnlockBits(bitmapData);
return bitmap; return bitmap;
} }
public static Bitmap RenderMapPreview(Map map) public static Bitmap RenderMapPreview(Map map)
{ {
Bitmap terrain = TerrainBitmap(map); Bitmap terrain = TerrainBitmap(map);
return AddStaticResources(map, terrain); return AddStaticResources(map, terrain);
} }
} }
} }

View File

@@ -1,208 +1,208 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
using OpenRA.Support; using OpenRA.Support;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Renderer public class Renderer
{ {
internal static int SheetSize; internal static int SheetSize;
internal IShader SpriteShader { get; private set; } /* note: shared shader params */ internal IShader SpriteShader { get; private set; } /* note: shared shader params */
internal IShader LineShader { get; private set; } internal IShader LineShader { get; private set; }
internal IShader RgbaSpriteShader { get; private set; } internal IShader RgbaSpriteShader { get; private set; }
internal IShader WorldSpriteShader { get; private set; } internal IShader WorldSpriteShader { get; private set; }
public SpriteRenderer SpriteRenderer { get; private set; } public SpriteRenderer SpriteRenderer { get; private set; }
public SpriteRenderer RgbaSpriteRenderer { get; private set; } public SpriteRenderer RgbaSpriteRenderer { get; private set; }
public SpriteRenderer WorldSpriteRenderer { get; private set; } public SpriteRenderer WorldSpriteRenderer { get; private set; }
public LineRenderer LineRenderer { get; private set; } public LineRenderer LineRenderer { get; private set; }
public ITexture PaletteTexture; public ITexture PaletteTexture;
public readonly SpriteFont RegularFont, BoldFont, TitleFont, TinyFont; public readonly SpriteFont RegularFont, BoldFont, TitleFont, TinyFont;
internal const int TempBufferSize = 8192; internal const int TempBufferSize = 8192;
const int TempBufferCount = 8; const int TempBufferCount = 8;
Queue<IVertexBuffer<Vertex>> tempBuffersV = new Queue<IVertexBuffer<Vertex>>(); Queue<IVertexBuffer<Vertex>> tempBuffersV = new Queue<IVertexBuffer<Vertex>>();
Queue<IIndexBuffer> tempBuffersI = new Queue<IIndexBuffer>(); Queue<IIndexBuffer> tempBuffersI = new Queue<IIndexBuffer>();
public Renderer() public Renderer()
{ {
SpriteShader = device.CreateShader("world-shp"); SpriteShader = device.CreateShader("world-shp");
LineShader = device.CreateShader("world-line"); LineShader = device.CreateShader("world-line");
RgbaSpriteShader = device.CreateShader("chrome-rgba"); RgbaSpriteShader = device.CreateShader("chrome-rgba");
WorldSpriteShader = device.CreateShader("chrome-shp"); WorldSpriteShader = device.CreateShader("chrome-shp");
SpriteRenderer = new SpriteRenderer( this, SpriteShader ); SpriteRenderer = new SpriteRenderer( this, SpriteShader );
RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader ); RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader );
WorldSpriteRenderer = new SpriteRenderer( this, WorldSpriteShader ); WorldSpriteRenderer = new SpriteRenderer( this, WorldSpriteShader );
LineRenderer = new LineRenderer(this); LineRenderer = new LineRenderer(this);
RegularFont = new SpriteFont("FreeSans.ttf", 14); RegularFont = new SpriteFont("FreeSans.ttf", 14);
BoldFont = new SpriteFont("FreeSansBold.ttf", 14); BoldFont = new SpriteFont("FreeSansBold.ttf", 14);
TitleFont = new SpriteFont("titles.ttf", 48); TitleFont = new SpriteFont("titles.ttf", 48);
TinyFont = new SpriteFont("FreeSans.ttf", 10); TinyFont = new SpriteFont("FreeSans.ttf", 10);
for( int i = 0 ; i < TempBufferCount ; i++ ) for( int i = 0 ; i < TempBufferCount ; i++ )
{ {
tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) ); tempBuffersV.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
tempBuffersI.Enqueue( device.CreateIndexBuffer( TempBufferSize ) ); tempBuffersI.Enqueue( device.CreateIndexBuffer( TempBufferSize ) );
} }
} }
internal IGraphicsDevice Device { get { return device; } } internal IGraphicsDevice Device { get { return device; } }
public void BeginFrame(float2 scroll) public void BeginFrame(float2 scroll)
{ {
device.Clear(Color.Black); device.Clear(Color.Black);
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height); float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
float2 r2 = new float2(-1, 1); float2 r2 = new float2(-1, 1);
SetShaderParams( SpriteShader, r1, r2, scroll ); SetShaderParams( SpriteShader, r1, r2, scroll );
SetShaderParams( LineShader, r1, r2, scroll ); SetShaderParams( LineShader, r1, r2, scroll );
SetShaderParams( RgbaSpriteShader, r1, r2, scroll ); SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
SetShaderParams( WorldSpriteShader, r1, r2, scroll ); SetShaderParams( WorldSpriteShader, r1, r2, scroll );
} }
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll ) private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
{ {
s.SetValue( "Palette", PaletteTexture ); s.SetValue( "Palette", PaletteTexture );
s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y ); s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y );
s.SetValue( "r1", r1.X, r1.Y ); s.SetValue( "r1", r1.X, r1.Y );
s.SetValue( "r2", r2.X, r2.Y ); s.SetValue( "r2", r2.X, r2.Y );
s.Commit(); s.Commit();
} }
public void EndFrame( IInputHandler inputHandler ) public void EndFrame( IInputHandler inputHandler )
{ {
Flush(); Flush();
device.Present( inputHandler ); device.Present( inputHandler );
} }
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices, public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
Range<int> vertexRange, Range<int> indexRange, PrimitiveType type, IShader shader) Range<int> vertexRange, Range<int> indexRange, PrimitiveType type, IShader shader)
where T : struct where T : struct
{ {
vertices.Bind(); vertices.Bind();
indices.Bind(); indices.Bind();
device.DrawIndexedPrimitives(type, vertexRange, indexRange); device.DrawIndexedPrimitives(type, vertexRange, indexRange);
PerfHistory.Increment("batches", 1); PerfHistory.Increment("batches", 1);
} }
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices, public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
int vertexPool, int numPrimitives, PrimitiveType type) int vertexPool, int numPrimitives, PrimitiveType type)
where T : struct where T : struct
{ {
vertices.Bind(); vertices.Bind();
indices.Bind(); indices.Bind();
device.DrawIndexedPrimitives(type, vertexPool, numPrimitives); device.DrawIndexedPrimitives(type, vertexPool, numPrimitives);
PerfHistory.Increment("batches", 1); PerfHistory.Increment("batches", 1);
} }
public void Flush() public void Flush()
{ {
CurrentBatchRenderer = null; CurrentBatchRenderer = null;
} }
static IGraphicsDevice device; static IGraphicsDevice device;
public static Size Resolution { get { return device.WindowSize; } } public static Size Resolution { get { return device.WindowSize; } }
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode ) internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
{ {
var resolution = GetResolution( windowMode ); var resolution = GetResolution( windowMode );
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) ) ), resolution.Width, resolution.Height, windowMode, false ); device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) ) ), resolution.Width, resolution.Height, windowMode, false );
} }
static Size GetResolution(WindowMode windowmode) static Size GetResolution(WindowMode windowmode)
{ {
var desktopResolution = Screen.PrimaryScreen.Bounds.Size; var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize; var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize;
if (customSize.X > 0 && customSize.Y > 0) if (customSize.X > 0 && customSize.Y > 0)
{ {
desktopResolution.Width = customSize.X; desktopResolution.Width = customSize.X;
desktopResolution.Height = customSize.Y; desktopResolution.Height = customSize.Y;
} }
return new Size( return new Size(
desktopResolution.Width, desktopResolution.Width,
desktopResolution.Height); desktopResolution.Height);
} }
static IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync ) static IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window, bool vsync )
{ {
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) ) foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
{ {
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } ) return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( WindowMode ), typeof( bool ) } )
.Invoke( new object[] { width, height, window, vsync } ); .Invoke( new object[] { width, height, window, vsync } );
} }
throw new NotImplementedException(); throw new NotImplementedException();
} }
internal IVertexBuffer<Vertex> GetTempVertexBuffer() internal IVertexBuffer<Vertex> GetTempVertexBuffer()
{ {
var ret = tempBuffersV.Dequeue(); var ret = tempBuffersV.Dequeue();
tempBuffersV.Enqueue( ret ); tempBuffersV.Enqueue( ret );
return ret; return ret;
} }
internal IIndexBuffer GetTempIndexBuffer() internal IIndexBuffer GetTempIndexBuffer()
{ {
var ret = tempBuffersI.Dequeue(); var ret = tempBuffersI.Dequeue();
tempBuffersI.Enqueue( ret ); tempBuffersI.Enqueue( ret );
return ret; return ret;
} }
public interface IBatchRenderer public interface IBatchRenderer
{ {
void Flush(); void Flush();
} }
static IBatchRenderer currentBatchRenderer; static IBatchRenderer currentBatchRenderer;
public static IBatchRenderer CurrentBatchRenderer public static IBatchRenderer CurrentBatchRenderer
{ {
get { return currentBatchRenderer; } get { return currentBatchRenderer; }
set set
{ {
if( currentBatchRenderer == value ) return; if( currentBatchRenderer == value ) return;
if( currentBatchRenderer != null ) if( currentBatchRenderer != null )
currentBatchRenderer.Flush(); currentBatchRenderer.Flush();
currentBatchRenderer = value; currentBatchRenderer = value;
} }
} }
public void EnableScissor(int left, int top, int width, int height) public void EnableScissor(int left, int top, int width, int height)
{ {
Flush(); Flush();
Device.EnableScissor( left, top, width, height ); Device.EnableScissor( left, top, width, height );
} }
public void DisableScissor() public void DisableScissor()
{ {
Flush(); Flush();
Device.DisableScissor(); Device.DisableScissor();
} }
} }
} }

View File

@@ -1,89 +1,89 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Xml; using System.Xml;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using System.Collections.Generic; using System.Collections.Generic;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Sequence public class Sequence
{ {
readonly Sprite[] sprites; readonly Sprite[] sprites;
readonly int start, length, facings, tick; readonly int start, length, facings, tick;
public readonly string Name; public readonly string Name;
public int Start { get { return start; } } public int Start { get { return start; } }
public int End { get { return start + length; } } public int End { get { return start + length; } }
public int Length { get { return length; } } public int Length { get { return length; } }
public int Facings { get { return facings; } } public int Facings { get { return facings; } }
public int Tick { get { return tick; } } public int Tick { get { return tick; } }
string srcOverride; string srcOverride;
public Sequence(string unit, string name, MiniYaml info) public Sequence(string unit, string name, MiniYaml info)
{ {
srcOverride = info.Value; srcOverride = info.Value;
Name = name; Name = name;
var d = info.NodesDict; var d = info.NodesDict;
sprites = Game.modData.SpriteLoader.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride ); sprites = Game.modData.SpriteLoader.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
start = int.Parse(d["Start"].Value); start = int.Parse(d["Start"].Value);
if (!d.ContainsKey("Length")) if (!d.ContainsKey("Length"))
length = 1; length = 1;
else if (d["Length"].Value == "*") else if (d["Length"].Value == "*")
length = sprites.Length - Start; length = sprites.Length - Start;
else else
length = int.Parse(d["Length"].Value); length = int.Parse(d["Length"].Value);
if(d.ContainsKey("Facings")) if(d.ContainsKey("Facings"))
facings = int.Parse(d["Facings"].Value); facings = int.Parse(d["Facings"].Value);
else else
facings = 1; facings = 1;
if(d.ContainsKey("Tick")) if(d.ContainsKey("Tick"))
tick = int.Parse(d["Tick"].Value); tick = int.Parse(d["Tick"].Value);
else else
tick = 40; tick = 40;
} }
public MiniYaml Save() public MiniYaml Save()
{ {
var root = new List<MiniYamlNode>(); var root = new List<MiniYamlNode>();
root.Add(new MiniYamlNode("Start", start.ToString())); root.Add(new MiniYamlNode("Start", start.ToString()));
if (length > 1 && (start != 0 || length != sprites.Length - start)) if (length > 1 && (start != 0 || length != sprites.Length - start))
root.Add(new MiniYamlNode("Length", length.ToString())); root.Add(new MiniYamlNode("Length", length.ToString()));
else if (length > 1 && length == sprites.Length - start) else if (length > 1 && length == sprites.Length - start)
root.Add(new MiniYamlNode("Length", "*")); root.Add(new MiniYamlNode("Length", "*"));
if (facings > 1) if (facings > 1)
root.Add(new MiniYamlNode("Facings", facings.ToString())); root.Add(new MiniYamlNode("Facings", facings.ToString()));
if (tick != 40) if (tick != 40)
root.Add(new MiniYamlNode("Tick", tick.ToString())); root.Add(new MiniYamlNode("Tick", tick.ToString()));
return new MiniYaml(srcOverride, root); return new MiniYaml(srcOverride, root);
} }
public Sprite GetSprite( int frame ) public Sprite GetSprite( int frame )
{ {
return GetSprite( frame, 0 ); return GetSprite( frame, 0 );
} }
public Sprite GetSprite(int frame, int facing) public Sprite GetSprite(int frame, int facing)
{ {
var f = Traits.Util.QuantizeFacing( facing, facings ); var f = Traits.Util.QuantizeFacing( facing, facings );
return sprites[ (f * length) + ( frame % length ) + start ]; return sprites[ (f * length) + ( frame % length ) + start ];
} }
} }
} }

View File

@@ -1,72 +1,72 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public static class SequenceProvider public static class SequenceProvider
{ {
static Dictionary<string, Dictionary<string, Sequence>> units; static Dictionary<string, Dictionary<string, Sequence>> units;
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes) public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
{ {
units = new Dictionary<string, Dictionary<string, Sequence>>(); units = new Dictionary<string, Dictionary<string, Sequence>>();
if (sequenceFiles.Length == 0) if (sequenceFiles.Length == 0)
return; return;
var sequences = sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(sequenceNodes, MiniYaml.Merge); var sequences = sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(sequenceNodes, MiniYaml.Merge);
foreach (var s in sequences) foreach (var s in sequences)
LoadSequencesForUnit(s.Key, s.Value); LoadSequencesForUnit(s.Key, s.Value);
} }
static void LoadSequencesForUnit(string unit, MiniYaml sequences) static void LoadSequencesForUnit(string unit, MiniYaml sequences)
{ {
Game.modData.LoadScreen.Display(); Game.modData.LoadScreen.Display();
try { try {
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value)); var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
units.Add(unit, seq); units.Add(unit, seq);
} catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art } catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art
} }
public static MiniYaml SaveSequencesForUnit(string unitname) public static MiniYaml SaveSequencesForUnit(string unitname)
{ {
var ret = new List<MiniYamlNode>(); var ret = new List<MiniYamlNode>();
foreach (var s in units[unitname]) foreach (var s in units[unitname])
ret.Add(new MiniYamlNode(s.Key, s.Value.Save())); ret.Add(new MiniYamlNode(s.Key, s.Value.Save()));
return new MiniYaml(null, ret); return new MiniYaml(null, ret);
} }
public static Sequence GetSequence(string unitName, string sequenceName) public static Sequence GetSequence(string unitName, string sequenceName)
{ {
try { return units[unitName][sequenceName]; } try { return units[unitName][sequenceName]; }
catch (KeyNotFoundException) catch (KeyNotFoundException)
{ {
if (units.ContainsKey(unitName)) if (units.ContainsKey(unitName))
throw new InvalidOperationException( throw new InvalidOperationException(
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName)); "Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
else else
throw new InvalidOperationException( throw new InvalidOperationException(
"Unit `{0}` does not have any sequences defined.".F(unitName)); "Unit `{0}` does not have any sequences defined.".F(unitName));
} }
} }
public static bool HasSequence(string unit, string seq) public static bool HasSequence(string unit, string seq)
{ {
return units[unit].ContainsKey(seq); return units[unit].ContainsKey(seq);
} }
} }
} }

View File

@@ -1,67 +1,67 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Sheet public class Sheet
{ {
Bitmap bitmap; Bitmap bitmap;
ITexture texture; ITexture texture;
bool dirty; bool dirty;
byte[] data; byte[] data;
public readonly Size Size; public readonly Size Size;
public Sheet(Size size) public Sheet(Size size)
{ {
Size = size; Size = size;
} }
public Sheet(string filename) public Sheet(string filename)
{ {
bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename)); bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
Size = bitmap.Size; Size = bitmap.Size;
} }
public ITexture Texture public ITexture Texture
{ {
get get
{ {
if (texture == null) if (texture == null)
{ {
texture = Game.Renderer.Device.CreateTexture(); texture = Game.Renderer.Device.CreateTexture();
dirty = true; dirty = true;
} }
if (dirty) if (dirty)
{ {
if (data != null) if (data != null)
{ {
texture.SetData(data, Size.Width, Size.Height); texture.SetData(data, Size.Width, Size.Height);
dirty = false; dirty = false;
} }
else if (bitmap != null) else if (bitmap != null)
{ {
texture.SetData(bitmap); texture.SetData(bitmap);
dirty = false; dirty = false;
} }
} }
return texture; return texture;
} }
} }
public byte[] Data { get { if (data == null) data = new byte[4 * Size.Width * Size.Height]; return data; } } public byte[] Data { get { if (data == null) data = new byte[4 * Size.Width * Size.Height]; return data; } }
public void MakeDirty() { dirty = true; } public void MakeDirty() { dirty = true; }
} }
} }

View File

@@ -1,102 +1,102 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class SheetBuilder public class SheetBuilder
{ {
internal SheetBuilder(TextureChannel ch) internal SheetBuilder(TextureChannel ch)
{ {
current = null; current = null;
rowHeight = 0; rowHeight = 0;
channel = null; channel = null;
initialChannel = ch; initialChannel = ch;
} }
public Sprite Add(byte[] src, Size size) public Sprite Add(byte[] src, Size size)
{ {
Sprite rect = Allocate(size); Sprite rect = Allocate(size);
Util.FastCopyIntoChannel(rect, src); Util.FastCopyIntoChannel(rect, src);
return rect; return rect;
} }
public Sprite Add(Size size, byte paletteIndex) public Sprite Add(Size size, byte paletteIndex)
{ {
byte[] data = new byte[size.Width * size.Height]; byte[] data = new byte[size.Width * size.Height];
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
data[i] = paletteIndex; data[i] = paletteIndex;
return Add(data, size); return Add(data, size);
} }
Sheet NewSheet() { return new Sheet(new Size( Renderer.SheetSize, Renderer.SheetSize ) ); } Sheet NewSheet() { return new Sheet(new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
Sheet current = null; Sheet current = null;
int rowHeight = 0; int rowHeight = 0;
Point p; Point p;
TextureChannel? channel = null; TextureChannel? channel = null;
TextureChannel initialChannel; TextureChannel initialChannel;
TextureChannel? NextChannel(TextureChannel? t) TextureChannel? NextChannel(TextureChannel? t)
{ {
if (t == null) if (t == null)
return initialChannel; return initialChannel;
switch (t.Value) switch (t.Value)
{ {
case TextureChannel.Red: return TextureChannel.Green; case TextureChannel.Red: return TextureChannel.Green;
case TextureChannel.Green: return TextureChannel.Blue; case TextureChannel.Green: return TextureChannel.Blue;
case TextureChannel.Blue: return TextureChannel.Alpha; case TextureChannel.Blue: return TextureChannel.Alpha;
case TextureChannel.Alpha: return null; case TextureChannel.Alpha: return null;
default: return null; default: return null;
} }
} }
public Sprite Allocate(Size imageSize) public Sprite Allocate(Size imageSize)
{ {
if (current == null) if (current == null)
{ {
current = NewSheet(); current = NewSheet();
channel = NextChannel(null); channel = NextChannel(null);
} }
if (imageSize.Width + p.X > current.Size.Width) if (imageSize.Width + p.X > current.Size.Width)
{ {
p = new Point(0, p.Y + rowHeight); p = new Point(0, p.Y + rowHeight);
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
} }
if (imageSize.Height > rowHeight) if (imageSize.Height > rowHeight)
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
if (p.Y + imageSize.Height > current.Size.Height) if (p.Y + imageSize.Height > current.Size.Height)
{ {
if (null == (channel = NextChannel(channel))) if (null == (channel = NextChannel(channel)))
{ {
current = NewSheet(); current = NewSheet();
channel = NextChannel(channel); channel = NextChannel(channel);
} }
rowHeight = imageSize.Height; rowHeight = imageSize.Height;
p = new Point(0,0); p = new Point(0,0);
} }
Sprite rect = new Sprite(current, new Rectangle(p, imageSize), channel.Value); Sprite rect = new Sprite(current, new Rectangle(p, imageSize), channel.Value);
current.MakeDirty(); current.MakeDirty();
p.X += imageSize.Width; p.X += imageSize.Width;
return rect; return rect;
} }
} }
} }

View File

@@ -1,161 +1,161 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class ShroudRenderer public class ShroudRenderer
{ {
Traits.Shroud shroud; Traits.Shroud shroud;
Sprite[] shadowBits = Game.modData.SpriteLoader.LoadAllSprites("shadow"); Sprite[] shadowBits = Game.modData.SpriteLoader.LoadAllSprites("shadow");
Sprite[,] sprites, fogSprites; Sprite[,] sprites, fogSprites;
bool dirty = true; bool dirty = true;
Map map; Map map;
public ShroudRenderer(World world) public ShroudRenderer(World world)
{ {
this.shroud = world.LocalShroud; this.shroud = world.LocalShroud;
this.map = world.Map; this.map = world.Map;
sprites = new Sprite[map.MapSize.X, map.MapSize.Y]; sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y]; fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
shroud.Dirty += () => dirty = true; shroud.Dirty += () => dirty = true;
} }
static readonly byte[][] SpecialShroudTiles = static readonly byte[][] SpecialShroudTiles =
{ {
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
new byte[] { 32, 32, 25, 25, 19, 19, 20, 20 }, new byte[] { 32, 32, 25, 25, 19, 19, 20, 20 },
new byte[] { 33, 33, 33, 33, 26, 26, 26, 26, 21, 21, 21, 21, 23, 23, 23, 23 }, new byte[] { 33, 33, 33, 33, 26, 26, 26, 26, 21, 21, 21, 21, 23, 23, 23, 23 },
new byte[] { 36, 36, 36, 36, 30, 30, 30, 30 }, new byte[] { 36, 36, 36, 36, 30, 30, 30, 30 },
new byte[] { 34, 16, 34, 16, 34, 16, 34, 16, 27, 22, 27, 22, 27, 22, 27, 22 }, new byte[] { 34, 16, 34, 16, 34, 16, 34, 16, 27, 22, 27, 22, 27, 22, 27, 22 },
new byte[] { 44 }, new byte[] { 44 },
new byte[] { 37, 37, 37, 37, 37, 37, 37, 37, 31, 31, 31, 31, 31, 31, 31, 31 }, new byte[] { 37, 37, 37, 37, 37, 37, 37, 37, 31, 31, 31, 31, 31, 31, 31, 31 },
new byte[] { 40 }, new byte[] { 40 },
new byte[] { 35, 24, 17, 18 }, new byte[] { 35, 24, 17, 18 },
new byte[] { 39, 39, 29, 29 }, new byte[] { 39, 39, 29, 29 },
new byte[] { 45 }, new byte[] { 45 },
new byte[] { 43 }, new byte[] { 43 },
new byte[] { 38, 28 }, new byte[] { 38, 28 },
new byte[] { 42 }, new byte[] { 42 },
new byte[] { 41 }, new byte[] { 41 },
new byte[] { 46 }, new byte[] { 46 },
}; };
Sprite ChooseShroud(int i, int j) Sprite ChooseShroud(int i, int j)
{ {
if( !shroud.IsExplored( i, j ) ) return shadowBits[ 0xf ]; if( !shroud.IsExplored( i, j ) ) return shadowBits[ 0xf ];
// bits are for unexploredness: up, right, down, left // bits are for unexploredness: up, right, down, left
var v = 0; var v = 0;
// bits are for unexploredness: TL, TR, BR, BL // bits are for unexploredness: TL, TR, BR, BL
var u = 0; var u = 0;
if( !shroud.IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; } if( !shroud.IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
if( !shroud.IsExplored( i + 1, j ) ) { v |= 2; u |= 6; } if( !shroud.IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
if( !shroud.IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; } if( !shroud.IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
if( !shroud.IsExplored( i - 1, j ) ) { v |= 8; u |= 9; } if( !shroud.IsExplored( i - 1, j ) ) { v |= 8; u |= 9; }
var uSides = u; var uSides = u;
if( !shroud.IsExplored( i - 1, j - 1 ) ) u |= 1; if( !shroud.IsExplored( i - 1, j - 1 ) ) u |= 1;
if( !shroud.IsExplored( i + 1, j - 1 ) ) u |= 2; if( !shroud.IsExplored( i + 1, j - 1 ) ) u |= 2;
if( !shroud.IsExplored( i + 1, j + 1 ) ) u |= 4; if( !shroud.IsExplored( i + 1, j + 1 ) ) u |= 4;
if( !shroud.IsExplored( i - 1, j + 1 ) ) u |= 8; if( !shroud.IsExplored( i - 1, j + 1 ) ) u |= 8;
return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ]; return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
} }
Sprite ChooseFog(int i, int j) Sprite ChooseFog(int i, int j)
{ {
if (!shroud.IsVisible(i,j)) return shadowBits[0xf]; if (!shroud.IsVisible(i,j)) return shadowBits[0xf];
if (!shroud.IsExplored(i, j)) return shadowBits[0xf]; if (!shroud.IsExplored(i, j)) return shadowBits[0xf];
// bits are for unexploredness: up, right, down, left // bits are for unexploredness: up, right, down, left
var v = 0; var v = 0;
// bits are for unexploredness: TL, TR, BR, BL // bits are for unexploredness: TL, TR, BR, BL
var u = 0; var u = 0;
if (!shroud.IsVisible(i, j - 1)) { v |= 1; u |= 3; } if (!shroud.IsVisible(i, j - 1)) { v |= 1; u |= 3; }
if (!shroud.IsVisible(i + 1, j)) { v |= 2; u |= 6; } if (!shroud.IsVisible(i + 1, j)) { v |= 2; u |= 6; }
if (!shroud.IsVisible(i, j + 1)) { v |= 4; u |= 12; } if (!shroud.IsVisible(i, j + 1)) { v |= 4; u |= 12; }
if (!shroud.IsVisible(i - 1, j)) { v |= 8; u |= 9; } if (!shroud.IsVisible(i - 1, j)) { v |= 8; u |= 9; }
var uSides = u; var uSides = u;
if (!shroud.IsVisible(i - 1, j - 1)) u |= 1; if (!shroud.IsVisible(i - 1, j - 1)) u |= 1;
if (!shroud.IsVisible(i + 1, j - 1)) u |= 2; if (!shroud.IsVisible(i + 1, j - 1)) u |= 2;
if (!shroud.IsVisible(i + 1, j + 1)) u |= 4; if (!shroud.IsVisible(i + 1, j + 1)) u |= 4;
if (!shroud.IsVisible(i - 1, j + 1)) u |= 8; if (!shroud.IsVisible(i - 1, j + 1)) u |= 8;
return shadowBits[SpecialShroudTiles[u ^ uSides][v]]; return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
} }
internal void Draw( WorldRenderer wr ) internal void Draw( WorldRenderer wr )
{ {
if (dirty) if (dirty)
{ {
dirty = false; dirty = false;
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
sprites[i, j] = ChooseShroud(i, j); sprites[i, j] = ChooseShroud(i, j);
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
fogSprites[i, j] = ChooseFog(i, j); fogSprites[i, j] = ChooseFog(i, j);
} }
var clipRect = Game.viewport.WorldBounds(wr.world); var clipRect = Game.viewport.WorldBounds(wr.world);
DrawShroud( wr, clipRect, fogSprites, "fog" ); DrawShroud( wr, clipRect, fogSprites, "fog" );
DrawShroud( wr, clipRect, sprites, "shroud" ); DrawShroud( wr, clipRect, sprites, "shroud" );
} }
void DrawShroud( WorldRenderer wr, Rectangle clip, Sprite[,] s, string pal ) void DrawShroud( WorldRenderer wr, Rectangle clip, Sprite[,] s, string pal )
{ {
var shroudPalette = wr.GetPaletteIndex(pal); var shroudPalette = wr.GetPaletteIndex(pal);
for (var j = clip.Top; j < clip.Bottom; j++) for (var j = clip.Top; j < clip.Bottom; j++)
{ {
var starti = clip.Left; var starti = clip.Left;
var last = shadowBits[0x0f]; var last = shadowBits[0x0f];
for (var i = clip.Left; i < clip.Right; i++) for (var i = clip.Left; i < clip.Right; i++)
{ {
if ((s[i, j] == shadowBits[0x0f] && last == shadowBits[0x0f]) if ((s[i, j] == shadowBits[0x0f] && last == shadowBits[0x0f])
|| (s[i, j] == shadowBits[0] && last == shadowBits[0])) || (s[i, j] == shadowBits[0] && last == shadowBits[0]))
continue; continue;
if (starti != i) if (starti != i)
{ {
s[starti, j].DrawAt( s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j), Game.CellSize * new float2(starti, j),
shroudPalette, shroudPalette,
new float2(Game.CellSize * (i - starti), Game.CellSize)); new float2(Game.CellSize * (i - starti), Game.CellSize));
starti = i + 1; starti = i + 1;
} }
s[i, j].DrawAt( s[i, j].DrawAt(
Game.CellSize * new float2(i, j), Game.CellSize * new float2(i, j),
shroudPalette); shroudPalette);
starti = i + 1; starti = i + 1;
last = s[i, j]; last = s[i, j];
} }
if (starti < clip.Right) if (starti < clip.Right)
s[starti, j].DrawAt( s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j), Game.CellSize * new float2(starti, j),
shroudPalette, shroudPalette,
new float2(Game.CellSize * (clip.Right - starti), Game.CellSize)); new float2(Game.CellSize * (clip.Right - starti), Game.CellSize));
} }
} }
} }
} }

View File

@@ -1,81 +1,81 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Drawing; using System.Drawing;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Sprite public class Sprite
{ {
public readonly Rectangle bounds; public readonly Rectangle bounds;
public readonly Sheet sheet; public readonly Sheet sheet;
public readonly TextureChannel channel; public readonly TextureChannel channel;
public readonly RectangleF uv; public readonly RectangleF uv;
public readonly float2 size; public readonly float2 size;
readonly float2[] uvhax; readonly float2[] uvhax;
public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel) public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
{ {
this.bounds = bounds; this.bounds = bounds;
this.sheet = sheet; this.sheet = sheet;
this.channel = channel; this.channel = channel;
uv = new RectangleF( uv = new RectangleF(
(float)(bounds.Left) / sheet.Size.Width, (float)(bounds.Left) / sheet.Size.Width,
(float)(bounds.Top) / sheet.Size.Height, (float)(bounds.Top) / sheet.Size.Height,
(float)(bounds.Width) / sheet.Size.Width, (float)(bounds.Width) / sheet.Size.Width,
(float)(bounds.Height) / sheet.Size.Height); (float)(bounds.Height) / sheet.Size.Height);
uvhax = new float2[] uvhax = new float2[]
{ {
new float2( uv.Left, uv.Top ), new float2( uv.Left, uv.Top ),
new float2( uv.Right, uv.Top ), new float2( uv.Right, uv.Top ),
new float2( uv.Left, uv.Bottom ), new float2( uv.Left, uv.Bottom ),
new float2( uv.Right, uv.Bottom ), new float2( uv.Right, uv.Bottom ),
}; };
this.size = new float2(bounds.Size); this.size = new float2(bounds.Size);
} }
public float2 FastMapTextureCoords( int k ) public float2 FastMapTextureCoords( int k )
{ {
return uvhax[ k ]; return uvhax[ k ];
} }
public void DrawAt( WorldRenderer wr, float2 location, string palette ) public void DrawAt( WorldRenderer wr, float2 location, string palette )
{ {
Game.Renderer.SpriteRenderer.DrawSprite( this, location, wr, palette, this.size ); Game.Renderer.SpriteRenderer.DrawSprite( this, location, wr, palette, this.size );
} }
public void DrawAt( float2 location, int paletteIndex ) public void DrawAt( float2 location, int paletteIndex )
{ {
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size ); Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size );
} }
public void DrawAt(float2 location, int paletteIndex, float scale) public void DrawAt(float2 location, int paletteIndex, float scale)
{ {
Game.Renderer.SpriteRenderer.DrawSprite(this, location, paletteIndex, this.size * scale); Game.Renderer.SpriteRenderer.DrawSprite(this, location, paletteIndex, this.size * scale);
} }
public void DrawAt( float2 location, int paletteIndex, float2 size ) public void DrawAt( float2 location, int paletteIndex, float2 size )
{ {
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, size ); Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, size );
} }
} }
public enum TextureChannel public enum TextureChannel
{ {
Red = 0, Red = 0,
Green = 1, Green = 1,
Blue = 2, Blue = 2,
Alpha = 3, Alpha = 3,
} }
} }

View File

@@ -1,153 +1,153 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using Tao.FreeType; using Tao.FreeType;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class SpriteFont public class SpriteFont
{ {
int size; int size;
public SpriteFont(string name, int size) public SpriteFont(string name, int size)
{ {
this.size = size; this.size = size;
if (0 != FT.FT_New_Face(library, name, 0, out face)) if (0 != FT.FT_New_Face(library, name, 0, out face))
throw new InvalidOperationException("FT_New_Face failed"); throw new InvalidOperationException("FT_New_Face failed");
FT.FT_Set_Pixel_Sizes(face, 0, (uint)size); FT.FT_Set_Pixel_Sizes(face, 0, (uint)size);
glyphs = new Cache<Pair<char, Color>, GlyphInfo>(CreateGlyph); glyphs = new Cache<Pair<char, Color>, GlyphInfo>(CreateGlyph);
// setup a 1-channel SheetBuilder for our private use // setup a 1-channel SheetBuilder for our private use
if (builder == null) builder = new SheetBuilder(TextureChannel.Alpha); if (builder == null) builder = new SheetBuilder(TextureChannel.Alpha);
PrecacheColor(Color.White); PrecacheColor(Color.White);
PrecacheColor(Color.Red); PrecacheColor(Color.Red);
} }
void PrecacheColor(Color c) void PrecacheColor(Color c)
{ {
// precache glyphs for U+0020 - U+007f // precache glyphs for U+0020 - U+007f
for (var n = (char)0x20; n < (char)0x7f; n++) for (var n = (char)0x20; n < (char)0x7f; n++)
if (glyphs[Pair.New(n, c)] == null) if (glyphs[Pair.New(n, c)] == null)
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
public void DrawText( string text, float2 location, Color c ) public void DrawText( string text, float2 location, Color c )
{ {
location.Y += size; // baseline vs top location.Y += size; // baseline vs top
var p = location; var p = location;
foreach (var s in text) foreach (var s in text)
{ {
if (s == '\n') if (s == '\n')
{ {
location.Y += size; location.Y += size;
p = location; p = location;
continue; continue;
} }
var g = glyphs[Pair.New(s, c)]; var g = glyphs[Pair.New(s, c)];
Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite, Game.Renderer.RgbaSpriteRenderer.DrawSprite(g.Sprite,
new float2( new float2(
(int)Math.Round(p.X + g.Offset.X, 0), (int)Math.Round(p.X + g.Offset.X, 0),
p.Y + g.Offset.Y)); p.Y + g.Offset.Y));
p.X += g.Advance; p.X += g.Advance;
} }
} }
public void DrawTextWithContrast(string text, float2 location, Color fg, Color bg, int offset) public void DrawTextWithContrast(string text, float2 location, Color fg, Color bg, int offset)
{ {
if (offset > 0) if (offset > 0)
{ {
DrawText(text, location + new float2(-offset, 0), bg); DrawText(text, location + new float2(-offset, 0), bg);
DrawText(text, location + new float2(offset, 0), bg); DrawText(text, location + new float2(offset, 0), bg);
DrawText(text, location + new float2(0, -offset), bg); DrawText(text, location + new float2(0, -offset), bg);
DrawText(text, location + new float2(0, offset), bg); DrawText(text, location + new float2(0, offset), bg);
} }
DrawText(text, location, fg); DrawText(text, location, fg);
} }
public int2 Measure(string text) public int2 Measure(string text)
{ {
return new int2((int)text.Split( '\n' ).Max( s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance)), text.Split('\n').Count()*size); return new int2((int)text.Split( '\n' ).Max( s => s.Sum(a => glyphs[Pair.New(a, Color.White)].Advance)), text.Split('\n').Count()*size);
} }
Cache<Pair<char,Color>, GlyphInfo> glyphs; Cache<Pair<char,Color>, GlyphInfo> glyphs;
IntPtr face; IntPtr face;
GlyphInfo CreateGlyph(Pair<char,Color> c) GlyphInfo CreateGlyph(Pair<char,Color> c)
{ {
var index = FT.FT_Get_Char_Index(face, (uint)c.First); var index = FT.FT_Get_Char_Index(face, (uint)c.First);
if (0 != FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER)) if (0 != FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER))
throw new InvalidOperationException( "FT_Load_Glyph failed." ); throw new InvalidOperationException( "FT_Load_Glyph failed." );
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec)); var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec)); var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
var s = builder.Allocate( var s = builder.Allocate(
new Size(_glyph.metrics.width.ToInt32() >> 6, new Size(_glyph.metrics.width.ToInt32() >> 6,
_glyph.metrics.height.ToInt32() >> 6)); _glyph.metrics.height.ToInt32() >> 6));
var g = new GlyphInfo var g = new GlyphInfo
{ {
Sprite = s, Sprite = s,
Advance = _glyph.metrics.horiAdvance.ToInt32() / 64f, Advance = _glyph.metrics.horiAdvance.ToInt32() / 64f,
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top } Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
}; };
unsafe unsafe
{ {
var p = (byte*)_glyph.bitmap.buffer; var p = (byte*)_glyph.bitmap.buffer;
var dest = s.sheet.Data; var dest = s.sheet.Data;
var destStride = s.sheet.Size.Width * 4; var destStride = s.sheet.Size.Width * 4;
for (var j = 0; j < s.size.Y; j++) for (var j = 0; j < s.size.Y; j++)
{ {
for (var i = 0; i < s.size.X; i++) for (var i = 0; i < s.size.X; i++)
if (p[i] != 0) if (p[i] != 0)
{ {
var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left); var q = destStride * (j + s.bounds.Top) + 4 * (i + s.bounds.Left);
dest[q] = c.Second.B; dest[q] = c.Second.B;
dest[q + 1] = c.Second.G; dest[q + 1] = c.Second.G;
dest[q + 2] = c.Second.R; dest[q + 2] = c.Second.R;
dest[q + 3] = p[i]; dest[q + 3] = p[i];
} }
p += _glyph.bitmap.pitch; p += _glyph.bitmap.pitch;
} }
} }
return g; return g;
} }
static SpriteFont() static SpriteFont()
{ {
FT.FT_Init_FreeType(out library); FT.FT_Init_FreeType(out library);
} }
static IntPtr library; static IntPtr library;
static SheetBuilder builder; static SheetBuilder builder;
} }
class GlyphInfo class GlyphInfo
{ {
public float Advance; public float Advance;
public int2 Offset; public int2 Offset;
public Sprite Sprite; public Sprite Sprite;
} }
} }

View File

@@ -1,37 +1,37 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class SpriteLoader public class SpriteLoader
{ {
public SpriteLoader( string[] exts, SheetBuilder sheetBuilder ) public SpriteLoader( string[] exts, SheetBuilder sheetBuilder )
{ {
SheetBuilder = sheetBuilder; SheetBuilder = sheetBuilder;
this.exts = exts; this.exts = exts;
sprites = new Cache<string, Sprite[]>( LoadSprites ); sprites = new Cache<string, Sprite[]>( LoadSprites );
} }
readonly SheetBuilder SheetBuilder; readonly SheetBuilder SheetBuilder;
readonly Cache<string, Sprite[]> sprites; readonly Cache<string, Sprite[]> sprites;
readonly string[] exts; readonly string[] exts;
Sprite[] LoadSprites(string filename) Sprite[] LoadSprites(string filename)
{ {
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts)); var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray(); return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
} }
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; } public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
} }
} }

View File

@@ -1,96 +1,96 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class SpriteRenderer : Renderer.IBatchRenderer public class SpriteRenderer : Renderer.IBatchRenderer
{ {
Renderer renderer; Renderer renderer;
IShader shader; IShader shader;
Vertex[] vertices = new Vertex[Renderer.TempBufferSize]; Vertex[] vertices = new Vertex[Renderer.TempBufferSize];
ushort[] indices = new ushort[Renderer.TempBufferSize]; ushort[] indices = new ushort[Renderer.TempBufferSize];
Sheet currentSheet = null; Sheet currentSheet = null;
int nv = 0, ni = 0; int nv = 0, ni = 0;
public SpriteRenderer(Renderer renderer, IShader shader) public SpriteRenderer(Renderer renderer, IShader shader)
{ {
this.renderer = renderer; this.renderer = renderer;
this.shader = shader; this.shader = shader;
} }
public SpriteRenderer(Renderer renderer) public SpriteRenderer(Renderer renderer)
: this(renderer, renderer.SpriteShader) { } : this(renderer, renderer.SpriteShader) { }
public void Flush() public void Flush()
{ {
if (ni > 0) if (ni > 0)
{ {
shader.SetValue( "DiffuseTexture", currentSheet.Texture ); shader.SetValue( "DiffuseTexture", currentSheet.Texture );
shader.Render(() => shader.Render(() =>
{ {
var vb = renderer.GetTempVertexBuffer(); var vb = renderer.GetTempVertexBuffer();
var ib = renderer.GetTempIndexBuffer(); var ib = renderer.GetTempIndexBuffer();
vb.SetData(vertices, nv); vb.SetData(vertices, nv);
ib.SetData(indices, ni); ib.SetData(indices, ni);
renderer.DrawBatch(vb, ib, renderer.DrawBatch(vb, ib,
new Range<int>(0, nv), new Range<int>(0, nv),
new Range<int>(0, ni), new Range<int>(0, ni),
PrimitiveType.TriangleList, PrimitiveType.TriangleList,
shader); shader);
}); });
nv = 0; ni = 0; nv = 0; ni = 0;
currentSheet = null; currentSheet = null;
} }
} }
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette) public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette)
{ {
DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size); DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size);
} }
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size) public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size)
{ {
DrawSprite(s, location, wr.GetPaletteIndex(palette), size); DrawSprite(s, location, wr.GetPaletteIndex(palette), size);
} }
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size) public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
{ {
Renderer.CurrentBatchRenderer = this; Renderer.CurrentBatchRenderer = this;
if (s.sheet != currentSheet) if (s.sheet != currentSheet)
Flush(); Flush();
if( nv + 4 > Renderer.TempBufferSize ) if( nv + 4 > Renderer.TempBufferSize )
Flush(); Flush();
if( ni + 6 > Renderer.TempBufferSize ) if( ni + 6 > Renderer.TempBufferSize )
Flush(); Flush();
currentSheet = s.sheet; currentSheet = s.sheet;
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size); Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, paletteIndex, nv, ni, size);
nv += 4; ni += 6; nv += 4; ni += 6;
} }
// For RGBASpriteRenderer, which doesn't use palettes // For RGBASpriteRenderer, which doesn't use palettes
public void DrawSprite(Sprite s, float2 location) public void DrawSprite(Sprite s, float2 location)
{ {
DrawSprite(s, location, 0, s.size); DrawSprite(s, location, 0, s.size);
} }
public void DrawSprite(Sprite s, float2 location, float2 size) public void DrawSprite(Sprite s, float2 location, float2 size)
{ {
DrawSprite(s, location, 0, size); DrawSprite(s, location, 0, size);
} }
} }
} }

View File

@@ -1,105 +1,105 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Drawing; using System.Drawing;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
class TerrainRenderer class TerrainRenderer
{ {
IVertexBuffer<Vertex> vertexBuffer; IVertexBuffer<Vertex> vertexBuffer;
IIndexBuffer indexBuffer; IIndexBuffer indexBuffer;
Sheet terrainSheet; Sheet terrainSheet;
World world; World world;
Map map; Map map;
public TerrainRenderer(World world, WorldRenderer wr) public TerrainRenderer(World world, WorldRenderer wr)
{ {
this.world = world; this.world = world;
this.map = world.Map; this.map = world.Map;
Size tileSize = new Size( Game.CellSize, Game.CellSize ); Size tileSize = new Size( Game.CellSize, Game.CellSize );
var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>( var tileMapping = new Cache<TileReference<ushort,byte>, Sprite>(
x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize)); x => Game.modData.SheetBuilder.Add(world.TileSet.GetBytes(x), tileSize));
Vertex[] vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width]; Vertex[] vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
ushort[] indices = new ushort[6 * map.Bounds.Height * map.Bounds.Width]; ushort[] indices = new ushort[6 * map.Bounds.Height * map.Bounds.Width];
terrainSheet = tileMapping[map.MapTiles.Value[map.Bounds.Left, map.Bounds.Top]].sheet; terrainSheet = tileMapping[map.MapTiles.Value[map.Bounds.Left, map.Bounds.Top]].sheet;
int nv = 0; int nv = 0;
int ni = 0; int ni = 0;
for( int j = map.Bounds.Top; j < map.Bounds.Bottom; j++ ) for( int j = map.Bounds.Top; j < map.Bounds.Bottom; j++ )
for( int i = map.Bounds.Left; i < map.Bounds.Right; i++ ) for( int i = map.Bounds.Left; i < map.Bounds.Right; i++ )
{ {
Sprite tile = tileMapping[map.MapTiles.Value[i, j]]; Sprite tile = tileMapping[map.MapTiles.Value[i, j]];
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called // TODO: The zero below should explicitly refer to the terrain palette, but this code is called
// before the palettes are created. Therefore assumes that "terrain" is the first palette to be defined // before the palettes are created. Therefore assumes that "terrain" is the first palette to be defined
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, Game.modData.Palette.GetPaletteIndex("terrain"), nv, ni, tile.size); Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, Game.modData.Palette.GetPaletteIndex("terrain"), nv, ni, tile.size);
nv += 4; nv += 4;
ni += 6; ni += 6;
if (tileMapping[map.MapTiles.Value[i, j]].sheet != terrainSheet) if (tileMapping[map.MapTiles.Value[i, j]].sheet != terrainSheet)
throw new InvalidOperationException("Terrain sprites span multiple sheets"); throw new InvalidOperationException("Terrain sprites span multiple sheets");
} }
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer( vertices.Length ); vertexBuffer = Game.Renderer.Device.CreateVertexBuffer( vertices.Length );
vertexBuffer.SetData( vertices, nv ); vertexBuffer.SetData( vertices, nv );
indexBuffer = Game.Renderer.Device.CreateIndexBuffer( indices.Length ); indexBuffer = Game.Renderer.Device.CreateIndexBuffer( indices.Length );
indexBuffer.SetData( indices, ni ); indexBuffer.SetData( indices, ni );
} }
public void Draw( WorldRenderer wr, Viewport viewport ) public void Draw( WorldRenderer wr, Viewport viewport )
{ {
int indicesPerRow = map.Bounds.Width * 6; int indicesPerRow = map.Bounds.Width * 6;
int verticesPerRow = map.Bounds.Width * 4; int verticesPerRow = map.Bounds.Width * 4;
int visibleRows = (int)(viewport.Height * 1f / Game.CellSize + 2); int visibleRows = (int)(viewport.Height * 1f / Game.CellSize + 2);
int firstRow = (int)(viewport.Location.Y * 1f / Game.CellSize - map.Bounds.Top); int firstRow = (int)(viewport.Location.Y * 1f / Game.CellSize - map.Bounds.Top);
int lastRow = firstRow + visibleRows; int lastRow = firstRow + visibleRows;
if (lastRow < 0 || firstRow > map.Bounds.Height) if (lastRow < 0 || firstRow > map.Bounds.Height)
return; return;
if (firstRow < 0) firstRow = 0; if (firstRow < 0) firstRow = 0;
if (lastRow > map.Bounds.Height) lastRow = map.Bounds.Height; if (lastRow > map.Bounds.Height) lastRow = map.Bounds.Height;
if (world.LocalPlayer != null && !world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue) if (world.LocalPlayer != null && !world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue)
{ {
var r = world.LocalShroud.Bounds.Value; var r = world.LocalShroud.Bounds.Value;
if (firstRow < r.Top - map.Bounds.Top) if (firstRow < r.Top - map.Bounds.Top)
firstRow = r.Top - map.Bounds.Top; firstRow = r.Top - map.Bounds.Top;
if (firstRow > r.Bottom - map.Bounds.Top) if (firstRow > r.Bottom - map.Bounds.Top)
firstRow = r.Bottom - map.Bounds.Top; firstRow = r.Bottom - map.Bounds.Top;
} }
if( lastRow < firstRow ) lastRow = firstRow; if( lastRow < firstRow ) lastRow = firstRow;
Game.Renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture ); Game.Renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
Game.Renderer.SpriteShader.Render(() => Game.Renderer.SpriteShader.Render(() =>
Game.Renderer.DrawBatch(vertexBuffer, indexBuffer, Game.Renderer.DrawBatch(vertexBuffer, indexBuffer,
new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow), new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow),
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow), new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
PrimitiveType.TriangleList, Game.Renderer.SpriteShader)); PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>()) foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
r.Render( wr ); r.Render( wr );
} }
} }
} }

View File

@@ -1,122 +1,122 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using OpenRA.FileFormats.Graphics; using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public static class Util public static class Util
{ {
public static string[] ReadAllLines(Stream s) public static string[] ReadAllLines(Stream s)
{ {
List<string> result = new List<string>(); List<string> result = new List<string>();
using (StreamReader reader = new StreamReader(s)) using (StreamReader reader = new StreamReader(s))
while(!reader.EndOfStream) while(!reader.EndOfStream)
{ {
var line = reader.ReadLine(); var line = reader.ReadLine();
if( !string.IsNullOrEmpty( line ) && line[0] != '#' ) if( !string.IsNullOrEmpty( line ) && line[0] != '#' )
result.Add( line ); result.Add( line );
} }
return result.ToArray(); return result.ToArray();
} }
public static T[] MakeArray<T>(int count, Converter<int, T> f) public static T[] MakeArray<T>(int count, Converter<int, T> f)
{ {
T[] result = new T[count]; T[] result = new T[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
result[i] = f(i); result[i] = f(i);
return result; return result;
} }
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f }; static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size) public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
{ {
var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]); var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);
vertices[nv] = new Vertex(o, vertices[nv] = new Vertex(o,
r.FastMapTextureCoords(0), attrib); r.FastMapTextureCoords(0), attrib);
vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y), vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y),
r.FastMapTextureCoords(1), attrib); r.FastMapTextureCoords(1), attrib);
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y), vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
r.FastMapTextureCoords(2), attrib); r.FastMapTextureCoords(2), attrib);
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y), vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
r.FastMapTextureCoords(3), attrib); r.FastMapTextureCoords(3), attrib);
indices[ni] = (ushort)(nv); indices[ni] = (ushort)(nv);
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1); indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2); indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2);
indices[ni + 4] = (ushort)(nv + 3); indices[ni + 4] = (ushort)(nv + 3);
} }
public static void FastCopyIntoChannel(Sprite dest, byte[] src) public static void FastCopyIntoChannel(Sprite dest, byte[] src)
{ {
var masks = new int[] { 2, 1, 0, 3 }; // hack, our channel order is nuts. var masks = new int[] { 2, 1, 0, 3 }; // hack, our channel order is nuts.
var data = dest.sheet.Data; var data = dest.sheet.Data;
var srcStride = dest.bounds.Width; var srcStride = dest.bounds.Width;
var destStride = dest.sheet.Size.Width * 4; var destStride = dest.sheet.Size.Width * 4;
var destOffset = destStride * dest.bounds.Top + dest.bounds.Left * 4 + masks[(int)dest.channel]; var destOffset = destStride * dest.bounds.Top + dest.bounds.Left * 4 + masks[(int)dest.channel];
var destSkip = destStride - 4 * srcStride; var destSkip = destStride - 4 * srcStride;
var height = dest.bounds.Height; var height = dest.bounds.Height;
var srcOffset = 0; var srcOffset = 0;
for (var j = 0; j < height; j++) for (var j = 0; j < height; j++)
{ {
for (int i = 0; i < srcStride; i++, srcOffset++) for (int i = 0; i < srcStride; i++, srcOffset++)
{ {
data[destOffset] = src[srcOffset]; data[destOffset] = src[srcOffset];
destOffset += 4; destOffset += 4;
} }
destOffset += destSkip; destOffset += destSkip;
} }
} }
public static Color Lerp(float t, Color a, Color b) public static Color Lerp(float t, Color a, Color b)
{ {
return Color.FromArgb( return Color.FromArgb(
LerpChannel(t, a.A, b.A), LerpChannel(t, a.A, b.A),
LerpChannel(t, a.R, b.R), LerpChannel(t, a.R, b.R),
LerpChannel(t, a.G, b.G), LerpChannel(t, a.G, b.G),
LerpChannel(t, a.B, b.B)); LerpChannel(t, a.B, b.B));
} }
public static int LerpARGBColor(float t, int c1, int c2) public static int LerpARGBColor(float t, int c1, int c2)
{ {
int a = LerpChannel(t, (c1 >> 24) & 255, (c2 >> 24) & 255); int a = LerpChannel(t, (c1 >> 24) & 255, (c2 >> 24) & 255);
int r = LerpChannel(t, (c1 >> 16) & 255, (c2 >> 16) & 255); int r = LerpChannel(t, (c1 >> 16) & 255, (c2 >> 16) & 255);
int g = LerpChannel(t, (c1 >> 8) & 255, (c2 >> 8) & 255); int g = LerpChannel(t, (c1 >> 8) & 255, (c2 >> 8) & 255);
int b = LerpChannel(t, c1 & 255, c2 & 255); int b = LerpChannel(t, c1 & 255, c2 & 255);
return (a << 24) | (r << 16) | (g << 8) | b; return (a << 24) | (r << 16) | (g << 8) | b;
} }
public static int LerpChannel(float t, int a, int b) public static int LerpChannel(float t, int a, int b)
{ {
return (int)((1 - t) * a + t * b); return (int)((1 - t) * a + t * b);
} }
public static int NextPowerOf2(int v) public static int NextPowerOf2(int v)
{ {
--v; --v;
v |= v >> 1; v |= v >> 1;
v |= v >> 2; v |= v >> 2;
v |= v >> 4; v |= v >> 4;
v |= v >> 8; v |= v >> 8;
++v; ++v;
return v; return v;
} }
} }
} }

View File

@@ -1,157 +1,157 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using OpenRA.Widgets; using OpenRA.Widgets;
namespace OpenRA.Graphics namespace OpenRA.Graphics
{ {
public class Viewport public class Viewport
{ {
readonly int2 screenSize; readonly int2 screenSize;
int2 scrollPosition; int2 scrollPosition;
readonly Renderer renderer; readonly Renderer renderer;
readonly Rectangle adjustedMapBounds; readonly Rectangle adjustedMapBounds;
public float2 Location { get { return scrollPosition; } } public float2 Location { get { return scrollPosition; } }
public int Width { get { return screenSize.X; } } public int Width { get { return screenSize.X; } }
public int Height { get { return screenSize.Y; } } public int Height { get { return screenSize.Y; } }
float cursorFrame = 0f; float cursorFrame = 0f;
public static int TicksSinceLastMove = 0; public static int TicksSinceLastMove = 0;
public static int2 LastMousePos; public static int2 LastMousePos;
public void Scroll(float2 delta) public void Scroll(float2 delta)
{ {
this.Scroll(delta, false); this.Scroll(delta, false);
} }
public void Scroll(float2 delta, bool ignoreBorders) public void Scroll(float2 delta, bool ignoreBorders)
{ {
var d = delta.ToInt2(); var d = delta.ToInt2();
var newScrollPosition = scrollPosition + d; var newScrollPosition = scrollPosition + d;
if(!ignoreBorders) if(!ignoreBorders)
newScrollPosition = this.NormalizeScrollPosition(newScrollPosition); newScrollPosition = this.NormalizeScrollPosition(newScrollPosition);
scrollPosition = newScrollPosition; scrollPosition = newScrollPosition;
} }
private int2 NormalizeScrollPosition(int2 newScrollPosition) private int2 NormalizeScrollPosition(int2 newScrollPosition)
{ {
return newScrollPosition.Clamp(adjustedMapBounds); return newScrollPosition.Clamp(adjustedMapBounds);
} }
public ScrollDirection GetBlockedDirections() public ScrollDirection GetBlockedDirections()
{ {
ScrollDirection blockedDirections = ScrollDirection.None; ScrollDirection blockedDirections = ScrollDirection.None;
if(scrollPosition.Y <= adjustedMapBounds.Top) if(scrollPosition.Y <= adjustedMapBounds.Top)
blockedDirections = blockedDirections.Set(ScrollDirection.Up, true); blockedDirections = blockedDirections.Set(ScrollDirection.Up, true);
if(scrollPosition.X <= adjustedMapBounds.Left) if(scrollPosition.X <= adjustedMapBounds.Left)
blockedDirections = blockedDirections.Set(ScrollDirection.Left, true); blockedDirections = blockedDirections.Set(ScrollDirection.Left, true);
if(scrollPosition.Y >= adjustedMapBounds.Bottom) if(scrollPosition.Y >= adjustedMapBounds.Bottom)
blockedDirections = blockedDirections.Set(ScrollDirection.Down, true); blockedDirections = blockedDirections.Set(ScrollDirection.Down, true);
if(scrollPosition.X >= adjustedMapBounds.Right) if(scrollPosition.X >= adjustedMapBounds.Right)
blockedDirections = blockedDirections.Set(ScrollDirection.Right, true); blockedDirections = blockedDirections.Set(ScrollDirection.Right, true);
return blockedDirections; return blockedDirections;
} }
public Viewport(int2 screenSize, Rectangle mapBounds, Renderer renderer) public Viewport(int2 screenSize, Rectangle mapBounds, Renderer renderer)
{ {
this.screenSize = screenSize; this.screenSize = screenSize;
this.renderer = renderer; this.renderer = renderer;
this.adjustedMapBounds = new Rectangle(Game.CellSize*mapBounds.X - screenSize.X/2, this.adjustedMapBounds = new Rectangle(Game.CellSize*mapBounds.X - screenSize.X/2,
Game.CellSize*mapBounds.Y - screenSize.Y/2, Game.CellSize*mapBounds.Y - screenSize.Y/2,
Game.CellSize*mapBounds.Width, Game.CellSize*mapBounds.Width,
Game.CellSize*mapBounds.Height); Game.CellSize*mapBounds.Height);
this.scrollPosition = new int2(adjustedMapBounds.Location) + new int2(adjustedMapBounds.Size)/2; this.scrollPosition = new int2(adjustedMapBounds.Location) + new int2(adjustedMapBounds.Size)/2;
} }
public void DrawRegions( WorldRenderer wr, IInputHandler inputHandler ) public void DrawRegions( WorldRenderer wr, IInputHandler inputHandler )
{ {
renderer.BeginFrame(scrollPosition); renderer.BeginFrame(scrollPosition);
if (wr != null) if (wr != null)
wr.Draw(); wr.Draw();
Widget.DoDraw(); Widget.DoDraw();
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default"; var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
new Cursor(cursorName).Draw((int)cursorFrame, Viewport.LastMousePos + Location); new Cursor(cursorName).Draw((int)cursorFrame, Viewport.LastMousePos + Location);
renderer.EndFrame( inputHandler ); renderer.EndFrame( inputHandler );
} }
public void Tick() public void Tick()
{ {
cursorFrame += 0.5f; cursorFrame += 0.5f;
} }
public float2 ViewToWorld(int2 loc) public float2 ViewToWorld(int2 loc)
{ {
return (1f / Game.CellSize) * (loc.ToFloat2() + Location); return (1f / Game.CellSize) * (loc.ToFloat2() + Location);
} }
public float2 ViewToWorld(MouseInput mi) public float2 ViewToWorld(MouseInput mi)
{ {
return ViewToWorld(mi.Location); return ViewToWorld(mi.Location);
} }
public void Center(float2 loc) public void Center(float2 loc)
{ {
scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2()); scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2());
} }
public void Center(IEnumerable<Actor> actors) public void Center(IEnumerable<Actor> actors)
{ {
if (!actors.Any()) return; if (!actors.Any()) return;
var avgPos = actors var avgPos = actors
.Select(a => a.CenterLocation) .Select(a => a.CenterLocation)
.Aggregate((a, b) => a + b) / actors.Count(); .Aggregate((a, b) => a + b) / actors.Count();
scrollPosition = this.NormalizeScrollPosition((avgPos - screenSize / 2)); scrollPosition = this.NormalizeScrollPosition((avgPos - screenSize / 2));
} }
public Rectangle ViewBounds(World world) public Rectangle ViewBounds(World world)
{ {
var r = WorldBounds(world); var r = WorldBounds(world);
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X); var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y); var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
var right = left + (int)(Game.CellSize * r.Width); var right = left + (int)(Game.CellSize * r.Width);
var bottom = top + (int)(Game.CellSize * r.Height); var bottom = top + (int)(Game.CellSize * r.Height);
if (left < 0) left = 0; if (left < 0) left = 0;
if (top < 0) top = 0; if (top < 0) top = 0;
if (right > Game.viewport.Width) right = Game.viewport.Width; if (right > Game.viewport.Width) right = Game.viewport.Width;
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height; if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
return new Rectangle(left, top, right - left, bottom - top); return new Rectangle(left, top, right - left, bottom - top);
} }
int2 cachedScroll = new int2(int.MaxValue, int.MaxValue); int2 cachedScroll = new int2(int.MaxValue, int.MaxValue);
Rectangle cachedRect; Rectangle cachedRect;
public Rectangle WorldBounds(World world) public Rectangle WorldBounds(World world)
{ {
if (cachedScroll != scrollPosition) if (cachedScroll != scrollPosition)
{ {
int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
var tl = ViewToWorld(int2.Zero).ToInt2() - boundary; var tl = ViewToWorld(int2.Zero).ToInt2() - boundary;
var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary; var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary;
cachedRect = Rectangle.Intersect(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y), world.Map.Bounds); cachedRect = Rectangle.Intersect(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y), world.Map.Bounds);
cachedScroll = scrollPosition; cachedScroll = scrollPosition;
} }
var b = world.LocalShroud.Bounds; var b = world.LocalShroud.Bounds;
return (b.HasValue) ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect; return (b.HasValue) ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect;
} }
} }
} }

View File

@@ -1,184 +1,184 @@
#region Copyright & License Information #region Copyright & License Information
/* /*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS) * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made * 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 * available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information, * as published by the Free Software Foundation. For more information,
* see LICENSE. * see COPYING.
*/ */
#endregion #endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
public class WorldRenderer
{
public readonly World world;
internal readonly TerrainRenderer terrainRenderer;
internal readonly ShroudRenderer shroudRenderer;
public readonly UiOverlay uiOverlay;
internal readonly HardwarePalette palette;
internal WorldRenderer(World world)
{
this.world = world;
this.palette = Game.modData.Palette;
foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
pal.Trait.InitPalette( this );
terrainRenderer = new TerrainRenderer(world, this);
shroudRenderer = new ShroudRenderer(world);
uiOverlay = new UiOverlay();
}
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
public Palette GetPalette(string name) { return palette.GetPalette(name); }
public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
class SpriteComparer : IComparer<Renderable>
{
public int Compare(Renderable x, Renderable y)
{
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
}
}
IEnumerable<Renderable> SpritesToRender()
{
var bounds = Game.viewport.ViewBounds(world);
var comparer = new SpriteComparer();
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
var actors = world.FindUnits(
new float2(bounds.Left, bounds.Top),
new float2(bounds.Right, bounds.Bottom));
var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);
var effects = world.Effects.SelectMany(e => e.Render());
return renderables.Concat(effects);
}
public void Draw()
{
RefreshPalette();
var bounds = Game.viewport.ViewBounds(world);
Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
terrainRenderer.Draw(this, Game.viewport);
foreach (var a in world.traitDict.ActorsWithTraitMultiple<IRenderAsTerrain>(world))
foreach (var r in a.Trait.RenderAsTerrain(a.Actor))
r.Sprite.DrawAt(r.Pos, this.GetPaletteIndex(r.Palette), r.Scale);
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
t.RenderBeforeWorld(this, a);
Game.Renderer.Flush();
if (world.OrderGenerator != null)
world.OrderGenerator.RenderBeforeWorld(this, world);
foreach (var image in SpritesToRender() ) using System;
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale); using System.Collections.Generic;
uiOverlay.Draw(this, world); using System.Drawing;
using System.Linq;
// added for contrails using OpenRA.FileFormats;
foreach (var a in world.Actors) using OpenRA.Traits;
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRender>()) namespace OpenRA.Graphics
t.RenderAfterWorld(this, a); {
public class WorldRenderer
if (world.OrderGenerator != null) {
world.OrderGenerator.RenderAfterWorld(this, world); public readonly World world;
internal readonly TerrainRenderer terrainRenderer;
shroudRenderer.Draw( this ); internal readonly ShroudRenderer shroudRenderer;
Game.Renderer.DisableScissor();
public readonly UiOverlay uiOverlay;
foreach (var a in world.Selection.Actors) internal readonly HardwarePalette palette;
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRenderSelection>()) internal WorldRenderer(World world)
t.RenderAfterWorld(this, a); {
this.world = world;
Game.Renderer.Flush(); this.palette = Game.modData.Palette;
} foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
pal.Trait.InitPalette( this );
void DrawBox(RectangleF r, Color color)
{ terrainRenderer = new TerrainRenderer(world, this);
var a = new float2(r.Left, r.Top); shroudRenderer = new ShroudRenderer(world);
var b = new float2(r.Right - a.X, 0); uiOverlay = new UiOverlay();
var c = new float2(0, r.Bottom - a.Y); }
Game.Renderer.LineRenderer.DrawLine(a, a + b, color, color);
Game.Renderer.LineRenderer.DrawLine(a + b, a + b + c, color, color); public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
Game.Renderer.LineRenderer.DrawLine(a + b + c, a + c, color, color); public Palette GetPalette(string name) { return palette.GetPalette(name); }
Game.Renderer.LineRenderer.DrawLine(a, a + c, color, color); public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
}
class SpriteComparer : IComparer<Renderable>
public void DrawSelectionBox(Actor selectedUnit, Color c) {
{ public int Compare(Renderable x, Renderable y)
var bounds = selectedUnit.GetBounds(false); {
return (x.Z + x.ZOffset).CompareTo(y.Z + y.ZOffset);
var xy = new float2(bounds.Left, bounds.Top); }
var Xy = new float2(bounds.Right, bounds.Top); }
var xY = new float2(bounds.Left, bounds.Bottom);
var XY = new float2(bounds.Right, bounds.Bottom); IEnumerable<Renderable> SpritesToRender()
{
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c); var bounds = Game.viewport.ViewBounds(world);
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c); var comparer = new SpriteComparer();
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c); bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c); var actors = world.FindUnits(
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c); new float2(bounds.Left, bounds.Top),
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c); new float2(bounds.Right, bounds.Bottom));
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
} var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);
public void DrawLocus(Color c, int2[] cells)
{ var effects = world.Effects.SelectMany(e => e.Render());
var dict = cells.ToDictionary(a => a, a => 0);
foreach (var t in dict.Keys) return renderables.Concat(effects);
{ }
if (!dict.ContainsKey(t + new int2(-1, 0)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)), public void Draw()
c, c); {
if (!dict.ContainsKey(t + new int2(1, 0))) RefreshPalette();
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)), var bounds = Game.viewport.ViewBounds(world);
c, c); Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
if (!dict.ContainsKey(t + new int2(0, -1)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)), terrainRenderer.Draw(this, Game.viewport);
c, c); foreach (var a in world.traitDict.ActorsWithTraitMultiple<IRenderAsTerrain>(world))
if (!dict.ContainsKey(t + new int2(0, 1))) foreach (var r in a.Trait.RenderAsTerrain(a.Actor))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)), r.Sprite.DrawAt(r.Pos, this.GetPaletteIndex(r.Palette), r.Scale);
c, c);
} foreach (var a in world.Selection.Actors)
} if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
public void DrawRangeCircle(Color c, float2 location, float range) t.RenderBeforeWorld(this, a);
{
for (var i = 0; i < 32; i++) Game.Renderer.Flush();
{
var start = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * i) / 16); if (world.OrderGenerator != null)
var end = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * (i + 0.7)) / 16); world.OrderGenerator.RenderBeforeWorld(this, world);
Game.Renderer.LineRenderer.DrawLine(start, end, c, c); foreach (var image in SpritesToRender() )
} image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
} uiOverlay.Draw(this, world);
public void RefreshPalette() // added for contrails
{ foreach (var a in world.Actors)
palette.Update( world.WorldActor.TraitsImplementing<IPaletteModifier>() ); if (!a.Destroyed)
} foreach (var t in a.TraitsImplementing<IPostRender>())
} t.RenderAfterWorld(this, a);
}
if (world.OrderGenerator != null)
world.OrderGenerator.RenderAfterWorld(this, world);
shroudRenderer.Draw( this );
Game.Renderer.DisableScissor();
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
t.RenderAfterWorld(this, a);
Game.Renderer.Flush();
}
void DrawBox(RectangleF r, Color color)
{
var a = new float2(r.Left, r.Top);
var b = new float2(r.Right - a.X, 0);
var c = new float2(0, r.Bottom - a.Y);
Game.Renderer.LineRenderer.DrawLine(a, a + b, color, color);
Game.Renderer.LineRenderer.DrawLine(a + b, a + b + c, color, color);
Game.Renderer.LineRenderer.DrawLine(a + b + c, a + c, color, color);
Game.Renderer.LineRenderer.DrawLine(a, a + c, color, color);
}
public void DrawSelectionBox(Actor selectedUnit, Color c)
{
var bounds = selectedUnit.GetBounds(false);
var xy = new float2(bounds.Left, bounds.Top);
var Xy = new float2(bounds.Right, bounds.Top);
var xY = new float2(bounds.Left, bounds.Bottom);
var XY = new float2(bounds.Right, bounds.Bottom);
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
Game.Renderer.LineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
Game.Renderer.LineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
Game.Renderer.LineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
Game.Renderer.LineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
}
public void DrawLocus(Color c, int2[] cells)
{
var dict = cells.ToDictionary(a => a, a => 0);
foreach (var t in dict.Keys)
{
if (!dict.ContainsKey(t + new int2(-1, 0)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(1, 0)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(0, -1)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)),
c, c);
if (!dict.ContainsKey(t + new int2(0, 1)))
Game.Renderer.LineRenderer.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
c, c);
}
}
public void DrawRangeCircle(Color c, float2 location, float range)
{
for (var i = 0; i < 32; i++)
{
var start = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * i) / 16);
var end = location + Game.CellSize * range * float2.FromAngle((float)(Math.PI * (i + 0.7)) / 16);
Game.Renderer.LineRenderer.DrawLine(start, end, c, c);
}
}
public void RefreshPalette()
{
palette.Update( world.WorldActor.TraitsImplementing<IPaletteModifier>() );
}
}
}

Some files were not shown because too many files have changed in this diff Show More