Update copyright header. Normalize line endings to LF.
This commit is contained in:
206
INSTALL
206
INSTALL
@@ -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 won’t run on 64-bit operating
|
Unfortunately the installer is 16-bit and so won’t 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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 ) ); };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
132
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
132
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
Reference in New Issue
Block a user