Merge pull request #4185 from pchote/frame-rework
Rewrite sprite handling.
This commit is contained in:
15
CHANGELOG
15
CHANGELOG
@@ -16,8 +16,9 @@ NEW:
|
|||||||
Added a setting for team health bar colors.
|
Added a setting for team health bar colors.
|
||||||
Asset Browser:
|
Asset Browser:
|
||||||
Fixed crashes when trying to load invalid filenames or sprites with just 1 frame.
|
Fixed crashes when trying to load invalid filenames or sprites with just 1 frame.
|
||||||
Added support for browsing the folders for R8 files.
|
Added support for all sprite types.
|
||||||
Added palette chooser and colorpicker dropdown boxes.
|
Added palette chooser and colorpicker dropdown boxes.
|
||||||
|
Overhauled layout.
|
||||||
Red Alert:
|
Red Alert:
|
||||||
Added MAD Tank.
|
Added MAD Tank.
|
||||||
Fixed a crash in Monster Tank Madness.
|
Fixed a crash in Monster Tank Madness.
|
||||||
@@ -86,6 +87,10 @@ NEW:
|
|||||||
Fixed corrupted replays (which would immediately desync).
|
Fixed corrupted replays (which would immediately desync).
|
||||||
Removed runtime mod merging.
|
Removed runtime mod merging.
|
||||||
Added support for map scripting with Lua.
|
Added support for map scripting with Lua.
|
||||||
|
Overhauled sprite loading code.
|
||||||
|
Improved error message when loading corrupted sprites.
|
||||||
|
Rewritten shp(ts) parser makes more efficient use of texture space.
|
||||||
|
Added support for the dune 2 shp format.
|
||||||
Build system and packages:
|
Build system and packages:
|
||||||
Added GeoIP to Makefile so it is installed properly.
|
Added GeoIP to Makefile so it is installed properly.
|
||||||
Added desktop shortcut creation support to the Makefile and Windows installer.
|
Added desktop shortcut creation support to the Makefile and Windows installer.
|
||||||
@@ -113,7 +118,13 @@ NEW:
|
|||||||
Added InvalidTargets property to weapons.
|
Added InvalidTargets property to weapons.
|
||||||
Added modifier support for build palette hotkeys.
|
Added modifier support for build palette hotkeys.
|
||||||
The Requires: option for inheriting from a parent mod has been removed. Mods can directly reference the parent mod files instead.
|
The Requires: option for inheriting from a parent mod has been removed. Mods can directly reference the parent mod files instead.
|
||||||
Icons are now defined in Sequences not Rules.
|
Icons definitions have moved from the unit's rules to its sequence.
|
||||||
|
Mouse cursors (cursors.yaml) must now specify their file extension.
|
||||||
|
OpenRA.Utility --png will now generate a set of frames for any sprite type [shp(td)/shp(ts)/shp(d2)/r8/tmp(td)/tmp(ra)].
|
||||||
|
OpenRA.Utility --shp now requires a list of frames to be combined into a shp.
|
||||||
|
Removed Utility --tmp-png, --r8, --fromd2 commands (use --png instead).
|
||||||
|
Removed Asset Browser file extraction / conversion (use the Utility instead).
|
||||||
|
Unified sprite loading allows any sprite type to be used anywhere: shp can now be used for terrain, and tmp for units.
|
||||||
|
|
||||||
20130915:
|
20130915:
|
||||||
All mods:
|
All mods:
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -159,8 +159,8 @@ STD_MOD_DEPS = $(STD_MOD_LIBS) $(ralint_TARGET)
|
|||||||
mod_ra_SRCS := $(shell find OpenRA.Mods.RA/ -iname '*.cs')
|
mod_ra_SRCS := $(shell find OpenRA.Mods.RA/ -iname '*.cs')
|
||||||
mod_ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
|
mod_ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
|
||||||
mod_ra_KIND = library
|
mod_ra_KIND = library
|
||||||
mod_ra_DEPS = $(STD_MOD_DEPS) $(utility_TARGET) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
|
mod_ra_DEPS = $(STD_MOD_DEPS) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
|
||||||
mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(utility_TARGET) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
|
mod_ra_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(geoip_TARGET) $(irc_TARGET) $(lua_TARGET)
|
||||||
PROGRAMS += mod_ra
|
PROGRAMS += mod_ra
|
||||||
mod_ra: $(mod_ra_TARGET)
|
mod_ra: $(mod_ra_TARGET)
|
||||||
|
|
||||||
|
|||||||
@@ -165,6 +165,7 @@
|
|||||||
<Compile Include="Surface.cs">
|
<Compile Include="Surface.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="TileSetRenderer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
|
using System.Linq;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
@@ -17,11 +19,11 @@ namespace OpenRA.Editor
|
|||||||
{
|
{
|
||||||
static class RenderUtils
|
static class RenderUtils
|
||||||
{
|
{
|
||||||
static Bitmap RenderShp(ShpReader shp, Palette p)
|
static Bitmap RenderShp(ISpriteSource shp, Palette p)
|
||||||
{
|
{
|
||||||
var frame = shp[0];
|
var frame = shp.Frames.First();
|
||||||
|
|
||||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed);
|
||||||
|
|
||||||
bitmap.Palette = p.AsSystemPalette();
|
bitmap.Palette = p.AsSystemPalette();
|
||||||
|
|
||||||
@@ -33,9 +35,9 @@ namespace OpenRA.Editor
|
|||||||
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 < frame.Size.Width; i++)
|
||||||
for (var j = 0; j < shp.Height; j++)
|
for (var j = 0; j < frame.Size.Height; j++)
|
||||||
q[j * stride2 + i] = frame.Image[i + shp.Width * j];
|
q[j * stride2 + i] = frame.Data[i + frame.Size.Width * j];
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap.UnlockBits(data);
|
bitmap.UnlockBits(data);
|
||||||
@@ -78,10 +80,11 @@ namespace OpenRA.Editor
|
|||||||
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);
|
// TODO: Do this properly
|
||||||
var frame = shp[shp.ImageCount - 1];
|
var shp = new ShpReader(s) as ISpriteSource;
|
||||||
|
var frame = shp.Frames.Last();
|
||||||
|
|
||||||
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
|
var bitmap = new Bitmap(frame.Size.Width, frame.Size.Height, PixelFormat.Format8bppIndexed);
|
||||||
bitmap.Palette = p.AsSystemPalette();
|
bitmap.Palette = p.AsSystemPalette();
|
||||||
var data = bitmap.LockBits(bitmap.Bounds(),
|
var data = bitmap.LockBits(bitmap.Bounds(),
|
||||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||||
@@ -91,13 +94,13 @@ namespace OpenRA.Editor
|
|||||||
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 < frame.Size.Width; i++)
|
||||||
for (var j = 0; j < shp.Height; j++)
|
for (var j = 0; j < frame.Size.Height; j++)
|
||||||
q[j * stride + i] = frame.Image[i + shp.Width * j];
|
q[j * stride + i] = frame.Data[i + frame.Size.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.Frames.Count() - 1 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
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.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
namespace OpenRA.Editor
|
||||||
{
|
{
|
||||||
public class TileSetRenderer
|
public class TileSetRenderer
|
||||||
{
|
{
|
||||||
@@ -21,20 +23,31 @@ namespace OpenRA.FileFormats
|
|||||||
Dictionary<ushort, List<byte[]>> templates;
|
Dictionary<ushort, List<byte[]>> templates;
|
||||||
public Size TileSize;
|
public Size TileSize;
|
||||||
|
|
||||||
List<byte[]> LoadTemplate(string filename, string[] exts, Cache<string, R8Reader> r8cache, int[] frames)
|
List<byte[]> LoadTemplate(string filename, string[] exts, Dictionary<string, ISpriteSource> sourceCache, int[] frames)
|
||||||
{
|
{
|
||||||
if (exts.Contains(".R8") && FileSystem.Exists(filename + ".R8"))
|
ISpriteSource source;
|
||||||
|
if (!sourceCache.ContainsKey(filename))
|
||||||
{
|
{
|
||||||
var data = new List<byte[]>();
|
using (var s = FileSystem.OpenWithExts(filename, exts))
|
||||||
|
source = SpriteSource.LoadSpriteSource(s, filename);
|
||||||
|
|
||||||
foreach (var f in frames)
|
if (source.CacheWhenLoadingTileset)
|
||||||
data.Add(f >= 0 ? r8cache[filename][f].Image : null);
|
sourceCache.Add(filename, source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
source = sourceCache[filename];
|
||||||
|
|
||||||
return data;
|
if (frames != null)
|
||||||
|
{
|
||||||
|
var ret = new List<byte[]>();
|
||||||
|
var srcFrames = source.Frames.ToArray();
|
||||||
|
foreach (var i in frames)
|
||||||
|
ret.Add(srcFrames[i].Data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var s = FileSystem.OpenWithExts(filename, exts))
|
return source.Frames.Select(f => f.Data).ToList();
|
||||||
return new Terrain(s).TileBitmapBytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileSetRenderer(TileSet tileset, Size tileSize)
|
public TileSetRenderer(TileSet tileset, Size tileSize)
|
||||||
@@ -43,9 +56,9 @@ namespace OpenRA.FileFormats
|
|||||||
this.TileSize = tileSize;
|
this.TileSize = tileSize;
|
||||||
|
|
||||||
templates = new Dictionary<ushort, List<byte[]>>();
|
templates = new Dictionary<ushort, List<byte[]>>();
|
||||||
var r8cache = new Cache<string, R8Reader>(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
|
var sourceCache = new Dictionary<string, ISpriteSource>();
|
||||||
foreach (var t in TileSet.Templates)
|
foreach (var t in TileSet.Templates)
|
||||||
templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, r8cache, t.Value.Frames));
|
templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap RenderTemplate(ushort id, Palette p)
|
public Bitmap RenderTemplate(ushort id, Palette p)
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
#region Copyright & License Information
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
|
||||||
* available to you under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation. For more information,
|
|
||||||
* see COPYING.
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
|
||||||
{
|
|
||||||
public enum Dune2ImageFlags : int
|
|
||||||
{
|
|
||||||
F80_F2 = 0,
|
|
||||||
F2 = 2,
|
|
||||||
L16_F80_F2_1 = 1,
|
|
||||||
L16_F80_F2_2 = 3,
|
|
||||||
Ln_F80_F2 = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Dune2ImageHeader
|
|
||||||
{
|
|
||||||
public readonly Dune2ImageFlags Flags;
|
|
||||||
public readonly int Width;
|
|
||||||
public readonly int Height;
|
|
||||||
public readonly int Slices;
|
|
||||||
public readonly int FileSize;
|
|
||||||
public readonly int DataSize;
|
|
||||||
|
|
||||||
public readonly byte[] LookupTable;
|
|
||||||
public byte[] Image;
|
|
||||||
|
|
||||||
public Dune2ImageHeader(Stream s)
|
|
||||||
{
|
|
||||||
Flags = (Dune2ImageFlags)s.ReadUInt16();
|
|
||||||
Slices = s.ReadUInt8();
|
|
||||||
Width = s.ReadUInt16();
|
|
||||||
Height = s.ReadUInt8();
|
|
||||||
FileSize = s.ReadUInt16();
|
|
||||||
DataSize = s.ReadUInt16();
|
|
||||||
|
|
||||||
if (Flags == Dune2ImageFlags.L16_F80_F2_1 ||
|
|
||||||
Flags == Dune2ImageFlags.L16_F80_F2_2 ||
|
|
||||||
Flags == Dune2ImageFlags.Ln_F80_F2)
|
|
||||||
{
|
|
||||||
int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16;
|
|
||||||
LookupTable = new byte[n];
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
LookupTable[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LookupTable = new byte[256];
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
LookupTable[i] = (byte)i;
|
|
||||||
LookupTable[1] = 0x7f;
|
|
||||||
LookupTable[2] = 0x7e;
|
|
||||||
LookupTable[3] = 0x7d;
|
|
||||||
LookupTable[4] = 0x7c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size Size
|
|
||||||
{
|
|
||||||
get { return new Size(Width, Height); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Dune2ShpReader : IEnumerable<Dune2ImageHeader>
|
|
||||||
{
|
|
||||||
public readonly int ImageCount;
|
|
||||||
|
|
||||||
List<Dune2ImageHeader> headers = new List<Dune2ImageHeader>();
|
|
||||||
|
|
||||||
public Dune2ShpReader(Stream s)
|
|
||||||
{
|
|
||||||
ImageCount = s.ReadUInt16();
|
|
||||||
|
|
||||||
//Last offset is pointer to end of file.
|
|
||||||
uint[] offsets = new uint[ImageCount + 1];
|
|
||||||
|
|
||||||
uint temp = s.ReadUInt32();
|
|
||||||
|
|
||||||
//If fourth byte in file is non-zero, the offsets are two bytes each.
|
|
||||||
bool twoByteOffsets = (temp & 0xFF0000) > 0;
|
|
||||||
if (twoByteOffsets)
|
|
||||||
{
|
|
||||||
offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes
|
|
||||||
offsets[1] = (temp & 0xFFFF) + 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
offsets[0] = temp + 2;
|
|
||||||
|
|
||||||
for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++)
|
|
||||||
offsets[i] = (twoByteOffsets ? s.ReadUInt16() : s.ReadUInt32()) + 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < ImageCount; i++)
|
|
||||||
{
|
|
||||||
s.Seek(offsets[i], SeekOrigin.Begin);
|
|
||||||
Dune2ImageHeader header = new Dune2ImageHeader(s);
|
|
||||||
byte[] imgData = s.ReadBytes(header.FileSize);
|
|
||||||
header.Image = new byte[header.Height * header.Width];
|
|
||||||
|
|
||||||
//Decode image data
|
|
||||||
if (header.Flags != Dune2ImageFlags.F2)
|
|
||||||
{
|
|
||||||
byte[] tempData = new byte[header.DataSize];
|
|
||||||
Format80.DecodeInto(imgData, tempData);
|
|
||||||
Format2.DecodeInto(tempData, header.Image);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Format2.DecodeInto(imgData, header.Image);
|
|
||||||
|
|
||||||
//Lookup values in lookup table
|
|
||||||
if (header.LookupTable != null)
|
|
||||||
for (int j = 0; j < header.Image.Length; j++)
|
|
||||||
header.Image[j] = header.LookupTable[header.Image[j]];
|
|
||||||
|
|
||||||
headers.Add(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dune2ImageHeader this[int index]
|
|
||||||
{
|
|
||||||
get { return headers[index]; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<Dune2ImageHeader> GetEnumerator()
|
|
||||||
{
|
|
||||||
return headers.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,17 +12,16 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
namespace OpenRA.FileFormats
|
||||||
{
|
{
|
||||||
public class R8Image
|
class R8Image : ISpriteFrame
|
||||||
{
|
{
|
||||||
public readonly Size Size;
|
public Size Size { get; private set; }
|
||||||
public readonly int2 Offset;
|
public Size FrameSize { get; private set; }
|
||||||
public readonly byte[] Image;
|
public float2 Offset { get; private set; }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
// Legacy variable. Can be removed when the utility command is made sensible.
|
|
||||||
public readonly Size FrameSize;
|
|
||||||
|
|
||||||
public R8Image(Stream s)
|
public R8Image(Stream s)
|
||||||
{
|
{
|
||||||
@@ -52,7 +51,7 @@ namespace OpenRA.FileFormats
|
|||||||
// Skip alignment byte
|
// Skip alignment byte
|
||||||
s.ReadUInt8();
|
s.ReadUInt8();
|
||||||
|
|
||||||
Image = s.ReadBytes(width*height);
|
Data = s.ReadBytes(width*height);
|
||||||
|
|
||||||
// Ignore palette
|
// Ignore palette
|
||||||
if (type == 1 && paletteOffset != 0)
|
if (type == 1 && paletteOffset != 0)
|
||||||
@@ -60,33 +59,20 @@ namespace OpenRA.FileFormats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class R8Reader : IEnumerable<R8Image>
|
public class R8Reader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<R8Image> headers = new List<R8Image>();
|
readonly List<R8Image> frames = new List<R8Image>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return frames.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return true; } }
|
||||||
|
|
||||||
public readonly int Frames;
|
public readonly int ImageCount;
|
||||||
public R8Reader(Stream stream)
|
public R8Reader(Stream stream)
|
||||||
{
|
{
|
||||||
while (stream.Position < stream.Length)
|
while (stream.Position < stream.Length)
|
||||||
{
|
{
|
||||||
headers.Add(new R8Image(stream));
|
frames.Add(new R8Image(stream));
|
||||||
Frames++;
|
ImageCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public R8Image this[int index]
|
|
||||||
{
|
|
||||||
get { return headers[index]; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<R8Image> GetEnumerator()
|
|
||||||
{
|
|
||||||
return headers.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
115
OpenRA.FileFormats/Graphics/ShpD2Reader.cs
Normal file
115
OpenRA.FileFormats/Graphics/ShpD2Reader.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
enum Dune2ImageFlags : int
|
||||||
|
{
|
||||||
|
F80_F2 = 0,
|
||||||
|
F2 = 2,
|
||||||
|
L16_F80_F2_1 = 1,
|
||||||
|
L16_F80_F2_2 = 3,
|
||||||
|
Ln_F80_F2 = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
class Frame : ISpriteFrame
|
||||||
|
{
|
||||||
|
public Size Size { get; private set; }
|
||||||
|
public Size FrameSize { get { return Size; } }
|
||||||
|
public float2 Offset { get { return float2.Zero; } }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
|
public Frame(Stream s)
|
||||||
|
{
|
||||||
|
var flags = (Dune2ImageFlags)s.ReadUInt16();
|
||||||
|
s.Position += 1;
|
||||||
|
var width = s.ReadUInt16();
|
||||||
|
var height = s.ReadUInt8();
|
||||||
|
Size = new Size(width, height);
|
||||||
|
|
||||||
|
var frameSize = s.ReadUInt16();
|
||||||
|
var dataSize = s.ReadUInt16();
|
||||||
|
|
||||||
|
byte[] table;
|
||||||
|
if (flags == Dune2ImageFlags.L16_F80_F2_1 ||
|
||||||
|
flags == Dune2ImageFlags.L16_F80_F2_2 ||
|
||||||
|
flags == Dune2ImageFlags.Ln_F80_F2)
|
||||||
|
{
|
||||||
|
var n = flags == Dune2ImageFlags.Ln_F80_F2 ? s.ReadUInt8() : (byte)16;
|
||||||
|
table = new byte[n];
|
||||||
|
for (var i = 0; i < n; i++)
|
||||||
|
table[i] = s.ReadUInt8();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
table = new byte[256];
|
||||||
|
for (var i = 0; i < 256; i++)
|
||||||
|
table[i] = (byte)i;
|
||||||
|
table[1] = 0x7f;
|
||||||
|
table[2] = 0x7e;
|
||||||
|
table[3] = 0x7d;
|
||||||
|
table[4] = 0x7c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract header size
|
||||||
|
var imgData = s.ReadBytes(frameSize - 10);
|
||||||
|
Data = new byte[width * height];
|
||||||
|
|
||||||
|
// Decode image data
|
||||||
|
if (flags != Dune2ImageFlags.F2)
|
||||||
|
{
|
||||||
|
var tempData = new byte[dataSize];
|
||||||
|
Format80.DecodeInto(imgData, tempData);
|
||||||
|
Format2.DecodeInto(tempData, Data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Format2.DecodeInto(imgData, Data);
|
||||||
|
|
||||||
|
// Lookup values in lookup table
|
||||||
|
for (var j = 0; j < Data.Length; j++)
|
||||||
|
Data[j] = table[Data[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShpD2Reader : ISpriteSource
|
||||||
|
{
|
||||||
|
List<Frame> headers = new List<Frame>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return headers.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
|
public ShpD2Reader(Stream s)
|
||||||
|
{
|
||||||
|
var imageCount = s.ReadUInt16();
|
||||||
|
|
||||||
|
// Last offset is pointer to end of file.
|
||||||
|
var offsets = new uint[imageCount + 1];
|
||||||
|
var temp = s.ReadUInt32();
|
||||||
|
|
||||||
|
// If fourth byte in file is non-zero, the offsets are two bytes each.
|
||||||
|
var twoByteOffset = (temp & 0xFF0000) > 0;
|
||||||
|
s.Position = 2;
|
||||||
|
|
||||||
|
for (var i = 0; i < imageCount + 1; i++)
|
||||||
|
offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2;
|
||||||
|
|
||||||
|
for (var i = 0; i < imageCount; i++)
|
||||||
|
{
|
||||||
|
s.Position = offsets[i];
|
||||||
|
headers.Add(new Frame(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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,
|
||||||
@@ -15,153 +15,180 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace OpenRA.FileFormats
|
namespace OpenRA.FileFormats
|
||||||
{
|
{
|
||||||
public class ImageHeader
|
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
|
||||||
|
|
||||||
|
class ImageHeader : ISpriteFrame
|
||||||
{
|
{
|
||||||
public uint Offset;
|
public Size Size { get { return reader.Size; } }
|
||||||
|
public Size FrameSize { get { return reader.Size; } }
|
||||||
|
public float2 Offset { get { return float2.Zero; } }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
|
public uint FileOffset;
|
||||||
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;
|
ShpReader reader;
|
||||||
|
// Used by ShpWriter
|
||||||
public ImageHeader() { }
|
public ImageHeader() { }
|
||||||
|
|
||||||
public ImageHeader( BinaryReader reader )
|
public ImageHeader(Stream stream, ShpReader reader)
|
||||||
{
|
{
|
||||||
var data = reader.ReadUInt32();
|
this.reader = reader;
|
||||||
Offset = data & 0xffffff;
|
var data = stream.ReadUInt32();
|
||||||
|
FileOffset = data & 0xffffff;
|
||||||
Format = (Format)(data >> 24);
|
Format = (Format)(data >> 24);
|
||||||
|
|
||||||
RefOffset = reader.ReadUInt16();
|
RefOffset = stream.ReadUInt16();
|
||||||
RefFormat = (Format)reader.ReadUInt16();
|
RefFormat = (Format)stream.ReadUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly int SizeOnDisk = 8;
|
|
||||||
|
|
||||||
public void WriteTo(BinaryWriter writer)
|
public void WriteTo(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
writer.Write(Offset | ((uint)Format << 24));
|
writer.Write(FileOffset | ((uint)Format << 24));
|
||||||
writer.Write((ushort)RefOffset);
|
writer.Write((ushort)RefOffset);
|
||||||
writer.Write((ushort)RefFormat);
|
writer.Write((ushort)RefFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
|
public class ShpReader : ISpriteSource
|
||||||
|
|
||||||
public class ShpReader
|
|
||||||
{
|
{
|
||||||
public readonly int ImageCount;
|
|
||||||
public readonly ushort Width;
|
|
||||||
public readonly ushort Height;
|
|
||||||
|
|
||||||
public Size Size { get { return new Size(Width, Height); } }
|
|
||||||
|
|
||||||
readonly List<ImageHeader> headers = new List<ImageHeader>();
|
readonly List<ImageHeader> headers = new List<ImageHeader>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return headers.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
public readonly Size Size;
|
||||||
|
|
||||||
int recurseDepth = 0;
|
int recurseDepth = 0;
|
||||||
|
readonly int imageCount;
|
||||||
|
|
||||||
public ShpReader(Stream stream)
|
public ShpReader(Stream stream)
|
||||||
{
|
{
|
||||||
using (var reader = new BinaryReader(stream))
|
imageCount = stream.ReadUInt16();
|
||||||
|
stream.Position += 4;
|
||||||
|
var width = stream.ReadUInt16();
|
||||||
|
var height = stream.ReadUInt16();
|
||||||
|
Size = new Size(width, height);
|
||||||
|
|
||||||
|
stream.Position += 4;
|
||||||
|
for (var i = 0; i < imageCount; i++)
|
||||||
|
headers.Add(new ImageHeader(stream, this));
|
||||||
|
|
||||||
|
// Skip eof and zero headers
|
||||||
|
stream.Position += 16;
|
||||||
|
|
||||||
|
var offsets = headers.ToDictionary(h => h.FileOffset, h => h);
|
||||||
|
for (var i = 0; i < imageCount; i++)
|
||||||
{
|
{
|
||||||
ImageCount = reader.ReadUInt16();
|
var h = headers[i];
|
||||||
reader.ReadUInt16();
|
if (h.Format == Format.Format20)
|
||||||
reader.ReadUInt16();
|
h.RefImage = headers[i - 1];
|
||||||
Width = reader.ReadUInt16();
|
|
||||||
Height = reader.ReadUInt16();
|
|
||||||
reader.ReadUInt32();
|
|
||||||
|
|
||||||
for (int i = 0 ; i < ImageCount ; i++)
|
else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage))
|
||||||
headers.Add(new ImageHeader(reader));
|
throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset));
|
||||||
|
|
||||||
new ImageHeader(reader); // end-of-file header
|
|
||||||
new ImageHeader(reader); // all-zeroes header
|
|
||||||
|
|
||||||
var offsets = headers.ToDictionary(h => h.Offset, h =>h);
|
|
||||||
|
|
||||||
for (int i = 0 ; i < ImageCount ; i++)
|
|
||||||
{
|
|
||||||
var h = headers[ i ];
|
|
||||||
if (h.Format == Format.Format20)
|
|
||||||
h.RefImage = headers[i - 1];
|
|
||||||
|
|
||||||
else if (h.Format == Format.Format40)
|
|
||||||
if (!offsets.TryGetValue(h.RefOffset, out h.RefImage))
|
|
||||||
throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ImageHeader h in headers)
|
|
||||||
Decompress(stream, h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var h in headers)
|
||||||
|
Decompress(stream, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageHeader this[int index]
|
static byte[] ReadCompressedData(Stream stream, ImageHeader h)
|
||||||
{
|
{
|
||||||
get { return headers[index]; }
|
stream.Position = h.FileOffset;
|
||||||
|
|
||||||
|
// Actually, far too big. There's no length field with the correct length though :(
|
||||||
|
var compressedLength = (int)(stream.Length - stream.Position);
|
||||||
|
var compressedBytes = new byte[compressedLength];
|
||||||
|
stream.Read(compressedBytes, 0, compressedLength);
|
||||||
|
|
||||||
|
return compressedBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.Data == null)
|
||||||
{
|
{
|
||||||
if (h.RefImage.Image == null)
|
++recurseDepth;
|
||||||
{
|
Decompress(stream, h.RefImage);
|
||||||
++recurseDepth;
|
--recurseDepth;
|
||||||
Decompress(stream, h.RefImage);
|
}
|
||||||
--recurseDepth;
|
|
||||||
}
|
h.Data = CopyImageData(h.RefImage.Data);
|
||||||
|
Format40.DecodeInto(ReadCompressedData(stream, h), h.Data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
h.Image = CopyImageData(h.RefImage.Image);
|
|
||||||
Format40.DecodeInto(ReadCompressedData(stream, h), h.Image);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Format.Format80:
|
case Format.Format80:
|
||||||
{
|
{
|
||||||
var imageBytes = new byte[Width * Height];
|
var imageBytes = new byte[Size.Width * Size.Height];
|
||||||
Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
|
Format80.DecodeInto(ReadCompressedData(stream, h), imageBytes);
|
||||||
h.Image = imageBytes;
|
h.Data = imageBytes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidDataException();
|
throw new InvalidDataException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] ReadCompressedData(Stream stream, ImageHeader h)
|
|
||||||
{
|
|
||||||
stream.Position = h.Offset;
|
|
||||||
// TODO: Actually, far too big. There's no length field with the correct length though :(
|
|
||||||
var compressedLength = (int)(stream.Length - stream.Position);
|
|
||||||
|
|
||||||
var compressedBytes = new byte[ compressedLength ];
|
|
||||||
stream.Read( compressedBytes, 0, compressedLength );
|
|
||||||
|
|
||||||
return compressedBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] CopyImageData(byte[] baseImage)
|
byte[] CopyImageData(byte[] baseImage)
|
||||||
{
|
{
|
||||||
var imageData = new byte[Width * Height];
|
var imageData = new byte[Size.Width * Size.Height];
|
||||||
for (int i = 0 ; i < Width * Height ; i++)
|
for (var i = 0; i < Size.Width * Size.Height; i++)
|
||||||
imageData[i] = baseImage[i];
|
imageData[i] = baseImage[i];
|
||||||
|
|
||||||
return imageData;
|
return imageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ImageHeader> Frames { get { return headers; } }
|
|
||||||
|
|
||||||
public static ShpReader Load(string filename)
|
public static ShpReader Load(string filename)
|
||||||
{
|
{
|
||||||
using (var s = File.OpenRead(filename))
|
using (var s = File.OpenRead(filename))
|
||||||
return new ShpReader(s);
|
return new ShpReader(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Write(Stream s, Size size, IEnumerable<byte[]> frames)
|
||||||
|
{
|
||||||
|
var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray();
|
||||||
|
|
||||||
|
// note: end-of-file and all-zeroes headers
|
||||||
|
var dataOffset = 14 + (compressedFrames.Length + 2) * 8;
|
||||||
|
|
||||||
|
using (var bw = new BinaryWriter(s))
|
||||||
|
{
|
||||||
|
bw.Write((ushort)compressedFrames.Length);
|
||||||
|
bw.Write((ushort)0);
|
||||||
|
bw.Write((ushort)0);
|
||||||
|
bw.Write((ushort)size.Width);
|
||||||
|
bw.Write((ushort)size.Height);
|
||||||
|
bw.Write((uint)0);
|
||||||
|
|
||||||
|
foreach (var f in compressedFrames)
|
||||||
|
{
|
||||||
|
var ih = new ImageHeader { Format = Format.Format80, FileOffset = (uint)dataOffset };
|
||||||
|
dataOffset += f.Length;
|
||||||
|
|
||||||
|
ih.WriteTo(bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
var eof = new ImageHeader { FileOffset = (uint)dataOffset };
|
||||||
|
eof.WriteTo(bw);
|
||||||
|
|
||||||
|
var allZeroes = new ImageHeader { };
|
||||||
|
allZeroes.WriteTo(bw);
|
||||||
|
|
||||||
|
foreach (var f in compressedFrames)
|
||||||
|
bw.Write(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,615 +1,112 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* 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;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
namespace OpenRA.FileFormats
|
||||||
{
|
{
|
||||||
|
class FrameHeader : ISpriteFrame
|
||||||
public struct Header
|
|
||||||
{
|
{
|
||||||
public ushort A;
|
public Size Size { get; private set; }
|
||||||
// Unknown
|
public Size FrameSize { get; private set; }
|
||||||
// Width and Height of the images
|
public float2 Offset { get; private set; }
|
||||||
public ushort Width;
|
public byte[] Data { get; set; }
|
||||||
public ushort Height;
|
|
||||||
public ushort NumImages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HeaderImage
|
public readonly uint FileOffset;
|
||||||
{
|
public readonly byte Format;
|
||||||
public ushort x;
|
|
||||||
public ushort y;
|
|
||||||
public ushort cx;
|
|
||||||
public ushort cy;
|
|
||||||
// cx and cy are width n height of stored image
|
|
||||||
public byte compression;
|
|
||||||
public byte[] align;
|
|
||||||
public byte[] transparent;
|
|
||||||
public int zero;
|
|
||||||
public int offset;
|
|
||||||
public byte[] Image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SHPData
|
public FrameHeader(Stream stream, Size frameSize)
|
||||||
{
|
|
||||||
public HeaderImage HeaderImage;
|
|
||||||
public byte[] Databuffer;
|
|
||||||
public byte[] FrameImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SHP
|
|
||||||
{
|
|
||||||
public Header Header;
|
|
||||||
public SHPData[] Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ShpTSReader : IEnumerable<HeaderImage>
|
|
||||||
{
|
|
||||||
public readonly int ImageCount;
|
|
||||||
public readonly ushort Width;
|
|
||||||
public readonly ushort Height;
|
|
||||||
public readonly ushort Width2;
|
|
||||||
public readonly ushort Height2;
|
|
||||||
public int arroff = 0;
|
|
||||||
public int erri = 0;
|
|
||||||
public int errj = 0;
|
|
||||||
public int errk = 0;
|
|
||||||
public int errl = 0;
|
|
||||||
|
|
||||||
public static int FindNextOffsetFrom(SHP SHP, int Init, int Last)
|
|
||||||
{
|
{
|
||||||
int result;
|
var x = stream.ReadUInt16();
|
||||||
result = 0;
|
var y = stream.ReadUInt16();
|
||||||
Last++;
|
var width = stream.ReadUInt16();
|
||||||
while ((result == 0) && (Init < Last))
|
var height = stream.ReadUInt16();
|
||||||
{
|
|
||||||
result = SHP.Data[Init].HeaderImage.offset;
|
Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height));
|
||||||
Init++;
|
Size = new Size(width, height);
|
||||||
}
|
FrameSize = frameSize;
|
||||||
return result;
|
|
||||||
|
Format = stream.ReadUInt8();
|
||||||
|
stream.Position += 11;
|
||||||
|
FileOffset = stream.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly List<HeaderImage> headers = new List<HeaderImage>();
|
public class ShpTSReader : ISpriteSource
|
||||||
|
{
|
||||||
|
readonly List<FrameHeader> frames = new List<FrameHeader>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return frames.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public ShpTSReader(Stream s)
|
public ShpTSReader(Stream stream)
|
||||||
{
|
{
|
||||||
|
stream.ReadUInt16();
|
||||||
|
var width = stream.ReadUInt16();
|
||||||
|
var height = stream.ReadUInt16();
|
||||||
|
var size = new Size(width, height);
|
||||||
|
var frameCount = stream.ReadUInt16();
|
||||||
|
|
||||||
SHP SHP = new SHP();
|
for (var i = 0; i < frameCount; i++)
|
||||||
int FileSize;
|
frames.Add(new FrameHeader(stream, size));
|
||||||
int x;
|
|
||||||
int k = 0;
|
|
||||||
int l = 0;
|
|
||||||
|
|
||||||
int ImageSize;
|
for (var i = 0; i < frameCount; i++)
|
||||||
int NextOffset;
|
{
|
||||||
|
var f = frames[i];
|
||||||
|
if (f.FileOffset == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
byte[] FData;
|
stream.Position = f.FileOffset;
|
||||||
byte cp;
|
|
||||||
byte[] Databuffer;
|
|
||||||
|
|
||||||
FileSize = (int)s.Length;
|
// Uncompressed
|
||||||
// Get Header
|
if (f.Format == 1 || f.Format == 0)
|
||||||
SHP.Header.A = s.ReadUInt16();
|
f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height);
|
||||||
SHP.Header.Width = s.ReadUInt16();
|
|
||||||
SHP.Header.Height = s.ReadUInt16();
|
|
||||||
SHP.Header.NumImages = s.ReadUInt16();
|
|
||||||
|
|
||||||
SHP.Data = new SHPData[SHP.Header.NumImages + 1];
|
// Uncompressed scanlines
|
||||||
|
else if (f.Format == 2)
|
||||||
ImageCount = SHP.Header.NumImages;
|
|
||||||
|
|
||||||
for (x = 1; x <= SHP.Header.NumImages; x++)
|
|
||||||
{
|
{
|
||||||
SHP.Data[x].HeaderImage = new HeaderImage();
|
f.Data = new byte[f.Size.Width * f.Size.Height];
|
||||||
|
for (var j = 0; j < f.Size.Height; j++)
|
||||||
SHP.Data[x].HeaderImage.x = s.ReadUInt16();
|
|
||||||
SHP.Data[x].HeaderImage.y = s.ReadUInt16();
|
|
||||||
SHP.Data[x].HeaderImage.cx = s.ReadUInt16();
|
|
||||||
SHP.Data[x].HeaderImage.cy = s.ReadUInt16();
|
|
||||||
|
|
||||||
SHP.Data[x].HeaderImage.compression = s.ReadUInt8();
|
|
||||||
SHP.Data[x].HeaderImage.align = s.ReadBytes(3);
|
|
||||||
s.ReadInt32();
|
|
||||||
SHP.Data[x].HeaderImage.zero = s.ReadUInt8();
|
|
||||||
SHP.Data[x].HeaderImage.transparent = s.ReadBytes(3);
|
|
||||||
|
|
||||||
SHP.Data[x].HeaderImage.offset = s.ReadInt32();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Width = SHP.Header.Width;
|
|
||||||
Height = SHP.Header.Height;
|
|
||||||
|
|
||||||
for (int i = 0; i < ImageCount; i++)
|
|
||||||
{
|
|
||||||
headers.Add(SHP.Data[i+1].HeaderImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and decode each image from the file
|
|
||||||
for (x = 1; x <= SHP.Header.NumImages; x++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image = new byte[(Width * Height)];
|
|
||||||
for (int i = 0; i < headers[x - 1].Image.Length; i++)
|
|
||||||
headers[x - 1].Image[i] = 0;
|
|
||||||
|
|
||||||
FData = new byte[(Width * Height)];
|
|
||||||
|
|
||||||
// Does it really reads the frame?
|
|
||||||
if (SHP.Data[x].HeaderImage.offset != 0)
|
|
||||||
{
|
{
|
||||||
try
|
var length = stream.ReadUInt16() - 2;
|
||||||
|
stream.Read(f.Data, f.Size.Width * j, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RLE-zero compressed scanlines
|
||||||
|
else if (f.Format == 3)
|
||||||
|
{
|
||||||
|
f.Data = new byte[f.Size.Width * f.Size.Height];
|
||||||
|
|
||||||
|
for (var j = 0; j < f.Size.Height; j++)
|
||||||
|
{
|
||||||
|
var k = j * f.Size.Width;
|
||||||
|
var length = stream.ReadUInt16() - 2;
|
||||||
|
while (length > 0)
|
||||||
{
|
{
|
||||||
// Now it checks the compression:
|
var b = stream.ReadUInt8();
|
||||||
if ((SHP.Data[x].HeaderImage.compression == 3))
|
length--;
|
||||||
{
|
|
||||||
// decode it
|
if (b == 0)
|
||||||
// Compression 3
|
|
||||||
NextOffset = FindNextOffsetFrom(SHP, x + 1, SHP.Header.NumImages);
|
|
||||||
if (NextOffset != 0)
|
|
||||||
{
|
{
|
||||||
|
k += stream.ReadUInt8();
|
||||||
ImageSize = NextOffset - SHP.Data[x].HeaderImage.offset;
|
length--;
|
||||||
Databuffer = new byte[ImageSize];
|
|
||||||
for (int i = 0; i < ImageSize; i++)
|
|
||||||
{
|
|
||||||
s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
|
|
||||||
Databuffer[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
|
|
||||||
Decode3(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref FileSize);
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0; i < Height; i++)
|
|
||||||
{
|
|
||||||
erri = i;
|
|
||||||
for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
|
|
||||||
{
|
|
||||||
errj = j;
|
|
||||||
errl = l;
|
|
||||||
errk = k;
|
|
||||||
arroff = i + j + l;
|
|
||||||
|
|
||||||
if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
|
|
||||||
cp = 0;
|
|
||||||
else
|
|
||||||
cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
|
|
||||||
|
|
||||||
FData[i + j + k] = cp;
|
|
||||||
|
|
||||||
if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
|
|
||||||
l = l + (SHP.Data[x].HeaderImage.cx - 1);
|
|
||||||
|
|
||||||
if (j == (Width - 1))
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//FData = headers[x - 1].Image;
|
|
||||||
k = 0;
|
|
||||||
for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < Width; j++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
|
|
||||||
if (j == (Width - 1))
|
|
||||||
{
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
f.Data[k++] = b;
|
||||||
|
|
||||||
ImageSize = 0;
|
|
||||||
ImageSize = FileSize - SHP.Data[x].HeaderImage.offset;
|
|
||||||
Databuffer = new byte[ImageSize];
|
|
||||||
for (int i = 0; i < ImageSize; i++)
|
|
||||||
{
|
|
||||||
s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
|
|
||||||
Databuffer[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
SHP.Data[x].Databuffer = new byte[((SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy))];
|
|
||||||
|
|
||||||
Decode3(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0; i < Height; i++)
|
|
||||||
{
|
|
||||||
erri = i;
|
|
||||||
for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
|
|
||||||
{
|
|
||||||
errj = j;
|
|
||||||
errl = l;
|
|
||||||
errk = k;
|
|
||||||
arroff = i + j + l;
|
|
||||||
|
|
||||||
if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
|
|
||||||
cp = 0;
|
|
||||||
else
|
|
||||||
cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
|
|
||||||
|
|
||||||
FData[i + j + k] = cp;
|
|
||||||
|
|
||||||
if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
|
|
||||||
l = l + (SHP.Data[x].HeaderImage.cx - 1);
|
|
||||||
|
|
||||||
if (j == (Width - 1))
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//FData = headers[x - 1].Image;
|
|
||||||
k = 0;
|
|
||||||
for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < Width; j++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
|
|
||||||
if (j == (Width - 1))
|
|
||||||
{
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ((SHP.Data[x].HeaderImage.compression == 2))
|
|
||||||
{
|
|
||||||
NextOffset = FindNextOffsetFrom(SHP, x + 1, SHP.Header.NumImages);
|
|
||||||
if (NextOffset != 0)
|
|
||||||
{
|
|
||||||
ImageSize = NextOffset - SHP.Data[x].HeaderImage.offset;
|
|
||||||
SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
|
|
||||||
Databuffer = new byte[ImageSize];
|
|
||||||
for (int i = 0; i < ImageSize; i++)
|
|
||||||
{
|
|
||||||
s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
|
|
||||||
Databuffer[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
|
|
||||||
Decode2(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0; i < Height; i++)
|
|
||||||
{
|
|
||||||
erri = i;
|
|
||||||
for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
|
|
||||||
{
|
|
||||||
errj = j;
|
|
||||||
errl = l;
|
|
||||||
errk = k;
|
|
||||||
arroff = i + j + l;
|
|
||||||
|
|
||||||
if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
|
|
||||||
cp = 0;
|
|
||||||
else
|
|
||||||
cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
|
|
||||||
|
|
||||||
FData[i + j + k] = cp;
|
|
||||||
|
|
||||||
if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
|
|
||||||
l = l + (SHP.Data[x].HeaderImage.cx - 1);
|
|
||||||
|
|
||||||
if (j == (Width - 1))
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//FData = headers[x - 1].Image;
|
|
||||||
k = 0;
|
|
||||||
for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < Width; j++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
|
|
||||||
if (j == (Width - 1))
|
|
||||||
{
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compression 2
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ImageSize = 0;
|
|
||||||
ImageSize = FileSize - SHP.Data[x].HeaderImage.offset;
|
|
||||||
Databuffer = new byte[ImageSize];
|
|
||||||
for (int i = 0; i < ImageSize; i++)
|
|
||||||
{
|
|
||||||
s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
|
|
||||||
Databuffer[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
SHP.Data[x].Databuffer = new byte[((SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy))];
|
|
||||||
Decode2(Databuffer, ref SHP.Data[x].Databuffer, SHP.Data[x].HeaderImage.cx, SHP.Data[x].HeaderImage.cy, ref ImageSize);
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0; i < Height; i++)
|
|
||||||
{
|
|
||||||
erri = i;
|
|
||||||
for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
|
|
||||||
{
|
|
||||||
errj = j;
|
|
||||||
errl = l;
|
|
||||||
errk = k;
|
|
||||||
arroff = i + j + l;
|
|
||||||
|
|
||||||
if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
|
|
||||||
cp = 0;
|
|
||||||
else
|
|
||||||
cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
|
|
||||||
|
|
||||||
FData[i + j + k] = cp;
|
|
||||||
|
|
||||||
if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
|
|
||||||
l = l + (SHP.Data[x].HeaderImage.cx - 1);
|
|
||||||
|
|
||||||
if (j == (Width - 1))
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//FData = headers[x - 1].Image;
|
|
||||||
k = 0;
|
|
||||||
for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < Width; j++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
|
|
||||||
if (j == (Width - 1))
|
|
||||||
{
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Compression 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Compression 1
|
|
||||||
ImageSize = (int)(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy);
|
|
||||||
Databuffer = new byte[ImageSize];
|
|
||||||
for (int i = 0; i < ImageSize; i++)
|
|
||||||
{
|
|
||||||
s.Seek(SHP.Data[x].HeaderImage.offset + i, SeekOrigin.Begin);
|
|
||||||
Databuffer[i] = s.ReadUInt8();
|
|
||||||
}
|
|
||||||
SHP.Data[x].Databuffer = new byte[(SHP.Data[x].HeaderImage.cx * SHP.Data[x].HeaderImage.cy)];
|
|
||||||
SHP.Data[x].Databuffer = Databuffer;
|
|
||||||
|
|
||||||
k = 0;
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0; i < Height; i++)
|
|
||||||
{
|
|
||||||
erri = i;
|
|
||||||
for (int j = SHP.Data[x].HeaderImage.x; j < Width; j++)
|
|
||||||
{
|
|
||||||
errj = j;
|
|
||||||
errl = l;
|
|
||||||
errk = k;
|
|
||||||
arroff = i + j + l;
|
|
||||||
|
|
||||||
if (((j + 1) > (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x)) || ((i + 1) > (SHP.Data[x].HeaderImage.cy)))
|
|
||||||
cp = 0;
|
|
||||||
else
|
|
||||||
cp = SHP.Data[x].Databuffer[i + (j - SHP.Data[x].HeaderImage.x) + l];
|
|
||||||
|
|
||||||
FData[i + j + k] = cp;
|
|
||||||
|
|
||||||
if (j == (SHP.Data[x].HeaderImage.cx + SHP.Data[x].HeaderImage.x - 1))
|
|
||||||
l = l + (SHP.Data[x].HeaderImage.cx - 1);
|
|
||||||
|
|
||||||
if (j == (Width - 1))
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//FData = headers[x - 1].Image;
|
|
||||||
k = 0;
|
|
||||||
for (int i = 0; i < (Height - SHP.Data[x].HeaderImage.y); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < Width; j++)
|
|
||||||
{
|
|
||||||
headers[x - 1].Image[i + j + k + (Width * SHP.Data[x].HeaderImage.y)] = FData[i + j + k];
|
|
||||||
if (j == (Width - 1))
|
|
||||||
{
|
|
||||||
k = k + (Width - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set the shp's databuffer to the result after decompression
|
|
||||||
}
|
|
||||||
//Width = Width2;
|
|
||||||
//Height = Height2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HeaderImage this[int index]
|
|
||||||
{
|
|
||||||
get { return headers[index]; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReInterpretWordFromBytes(byte Byte1, byte Byte2, ref ushort FullValue)
|
|
||||||
{
|
|
||||||
FullValue = (ushort)((Byte2 * 256) + Byte1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReInterpretWordFromBytes(byte Byte1, byte Byte2, ref uint FullValue)
|
|
||||||
{
|
|
||||||
FullValue = (uint)((Byte2 * 256) + Byte1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compression 3:
|
|
||||||
public static void Decode3(byte[] Source, ref byte[] Dest, int cx, int cy, ref int max)
|
|
||||||
{
|
|
||||||
int SP;
|
|
||||||
int DP;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int Count;
|
|
||||||
int v;
|
|
||||||
int maxdp;
|
|
||||||
ushort Pos;
|
|
||||||
maxdp = cx * cy;
|
|
||||||
SP = 0;
|
|
||||||
DP = 0;
|
|
||||||
Pos = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (y = 1; y <= cy; y++)
|
|
||||||
{
|
|
||||||
ReInterpretWordFromBytes(Source[SP], Source[SP + 1], ref Pos);
|
|
||||||
|
|
||||||
Count = Pos - 2;
|
|
||||||
|
|
||||||
SP = SP + 2;
|
|
||||||
|
|
||||||
x = 0;
|
|
||||||
while (Count > 0)
|
|
||||||
{
|
|
||||||
Count = Count - 1;
|
|
||||||
if ((SP > max) || (DP > maxdp))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// SP has reached max value, exit
|
|
||||||
v = Source[SP];
|
|
||||||
SP++;
|
|
||||||
if (v != 0)
|
|
||||||
{
|
|
||||||
if ((SP > max) || (DP > maxdp))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x++;
|
|
||||||
Dest[DP] += (byte)v;
|
|
||||||
}
|
|
||||||
DP++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Count -= 1;
|
|
||||||
v = Source[SP];
|
|
||||||
|
|
||||||
SP++;
|
|
||||||
if ((x + v) > cx)
|
|
||||||
{
|
|
||||||
v = cx - x;
|
|
||||||
}
|
|
||||||
x = x + v;
|
|
||||||
while (v > 0)
|
|
||||||
{
|
|
||||||
if ((SP > max) || (DP > maxdp))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v -= 1;
|
|
||||||
Dest[DP] = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
DP++;
|
|
||||||
// SP has reached max value, exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((SP >= max) || (DP >= maxdp))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// SP has reached max value, exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Decode2(byte[] Source, ref byte[] Dest, int cx, int cy, ref int max)
|
|
||||||
{
|
|
||||||
int SP;
|
|
||||||
int DP;
|
|
||||||
int y;
|
|
||||||
int Count;
|
|
||||||
int maxdp;
|
|
||||||
ushort Pos;
|
|
||||||
maxdp = cx * cy;
|
|
||||||
SP = 0;
|
|
||||||
DP = 0;
|
|
||||||
Pos = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (y = 1; y <= cy; y++)
|
|
||||||
{
|
|
||||||
ReInterpretWordFromBytes(Source[SP], Source[SP + 1], ref Pos);
|
|
||||||
Count = Pos - 2;
|
|
||||||
SP += 2;
|
|
||||||
while (Count > 0)
|
|
||||||
{
|
|
||||||
Count -= 1;
|
|
||||||
if ((SP > max) || (DP > maxdp))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// SP has reached max value, exit
|
|
||||||
Dest[DP] = Source[SP];
|
|
||||||
SP++;
|
|
||||||
DP++;
|
|
||||||
}
|
|
||||||
if ((SP >= max) || (DP >= maxdp))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// SP has reached max value, exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<HeaderImage> GetEnumerator()
|
|
||||||
{
|
|
||||||
return headers.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size Size { get { return new Size(Width, Height); } }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
#region Copyright & License Information
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
|
||||||
* available to you under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation. For more information,
|
|
||||||
* see COPYING.
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace OpenRA.FileFormats.Graphics
|
|
||||||
{
|
|
||||||
// format80-only SHP writer
|
|
||||||
|
|
||||||
public static class ShpWriter
|
|
||||||
{
|
|
||||||
public static void Write(Stream s, int width, int height, IEnumerable<byte[]> frames)
|
|
||||||
{
|
|
||||||
var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray();
|
|
||||||
|
|
||||||
// note: end-of-file and all-zeroes headers
|
|
||||||
var dataOffset = 14 + (compressedFrames.Length + 2) * ImageHeader.SizeOnDisk;
|
|
||||||
|
|
||||||
using (var bw = new BinaryWriter(s))
|
|
||||||
{
|
|
||||||
bw.Write((ushort)compressedFrames.Length);
|
|
||||||
bw.Write((ushort)0); // unused
|
|
||||||
bw.Write((ushort)0); // unused
|
|
||||||
bw.Write((ushort)width);
|
|
||||||
bw.Write((ushort)height);
|
|
||||||
bw.Write((uint)0); // unused
|
|
||||||
|
|
||||||
foreach (var f in compressedFrames)
|
|
||||||
{
|
|
||||||
var ih = new ImageHeader { Format = Format.Format80, Offset = (uint)dataOffset };
|
|
||||||
dataOffset += f.Length;
|
|
||||||
|
|
||||||
ih.WriteTo(bw);
|
|
||||||
}
|
|
||||||
|
|
||||||
var eof = new ImageHeader { Offset = (uint)dataOffset };
|
|
||||||
eof.WriteTo(bw);
|
|
||||||
|
|
||||||
var allZeroes = new ImageHeader { };
|
|
||||||
allZeroes.WriteTo(bw);
|
|
||||||
|
|
||||||
foreach (var f in compressedFrames)
|
|
||||||
bw.Write(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
236
OpenRA.FileFormats/Graphics/SpriteSource.cs
Normal file
236
OpenRA.FileFormats/Graphics/SpriteSource.cs
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public interface ISpriteFrame
|
||||||
|
{
|
||||||
|
Size Size { get; }
|
||||||
|
Size FrameSize { get; }
|
||||||
|
float2 Offset { get; }
|
||||||
|
byte[] Data { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISpriteSource
|
||||||
|
{
|
||||||
|
IEnumerable<ISpriteFrame> Frames { get; }
|
||||||
|
bool CacheWhenLoadingTileset { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, R8 }
|
||||||
|
public static class SpriteSource
|
||||||
|
{
|
||||||
|
static bool IsTmpRA(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
s.Position += 20;
|
||||||
|
var a = s.ReadUInt32();
|
||||||
|
s.Position += 2;
|
||||||
|
var b = s.ReadUInt16();
|
||||||
|
|
||||||
|
s.Position = start;
|
||||||
|
return a == 0 && b == 0x2c73;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsTmpTD(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
s.Position += 16;
|
||||||
|
var a = s.ReadUInt32();
|
||||||
|
var b = s.ReadUInt32();
|
||||||
|
|
||||||
|
s.Position = start;
|
||||||
|
return a == 0 && b == 0x0D1AFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsShpTS(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
// First word is zero
|
||||||
|
if (s.ReadUInt16() != 0)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity Check the image count
|
||||||
|
s.Position += 4;
|
||||||
|
var imageCount = s.ReadUInt16();
|
||||||
|
if (s.Position + 24 * imageCount > s.Length)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the size and format flag
|
||||||
|
// Some files define bogus frames, so loop until we find a valid one
|
||||||
|
s.Position += 4;
|
||||||
|
ushort w, h, f = 0;
|
||||||
|
byte type;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
w = s.ReadUInt16();
|
||||||
|
h = s.ReadUInt16();
|
||||||
|
type = s.ReadUInt8();
|
||||||
|
}
|
||||||
|
while (w == 0 && h == 0 && f++ < imageCount);
|
||||||
|
|
||||||
|
s.Position = start;
|
||||||
|
return type < 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsShpTD(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
// First word is the image count
|
||||||
|
var imageCount = s.ReadUInt16();
|
||||||
|
if (imageCount == 0)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last offset should point to the end of file
|
||||||
|
var finalOffset = start + 14 + 8 * imageCount;
|
||||||
|
if (finalOffset > s.Length)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Position = finalOffset;
|
||||||
|
var eof = s.ReadUInt32();
|
||||||
|
if (eof != s.Length)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the format flag on the first frame
|
||||||
|
s.Position = start + 17;
|
||||||
|
var b = s.ReadUInt8();
|
||||||
|
|
||||||
|
s.Position = start;
|
||||||
|
return b == 0x20 || b == 0x40 || b == 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsShpD2(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
// First word is the image count
|
||||||
|
var imageCount = s.ReadUInt16();
|
||||||
|
if (imageCount == 0)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for two vs four byte offset
|
||||||
|
var testOffset = s.ReadUInt32();
|
||||||
|
var offsetSize = (testOffset & 0xFF0000) > 0 ? 2 : 4;
|
||||||
|
|
||||||
|
// Last offset should point to the end of file
|
||||||
|
var finalOffset = start + 2 + offsetSize * imageCount;
|
||||||
|
if (finalOffset > s.Length)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Position = finalOffset;
|
||||||
|
var eof = offsetSize == 2 ? s.ReadUInt16() : s.ReadUInt32();
|
||||||
|
if (eof + 2 != s.Length)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the format flag on the first frame
|
||||||
|
var b = s.ReadUInt16();
|
||||||
|
s.Position = start;
|
||||||
|
return b == 5 || b <= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsR8(Stream s)
|
||||||
|
{
|
||||||
|
var start = s.Position;
|
||||||
|
|
||||||
|
// First byte is nonzero
|
||||||
|
if (s.ReadUInt8() == 0)
|
||||||
|
{
|
||||||
|
s.Position = start;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the format of the first frame
|
||||||
|
s.Position = start + 25;
|
||||||
|
var d = s.ReadUInt8();
|
||||||
|
|
||||||
|
s.Position = start;
|
||||||
|
return d == 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpriteType DetectSpriteType(Stream s)
|
||||||
|
{
|
||||||
|
if (IsShpTD(s))
|
||||||
|
return SpriteType.ShpTD;
|
||||||
|
|
||||||
|
if (IsShpTS(s))
|
||||||
|
return SpriteType.ShpTS;
|
||||||
|
|
||||||
|
if (IsR8(s))
|
||||||
|
return SpriteType.R8;
|
||||||
|
|
||||||
|
if (IsTmpRA(s))
|
||||||
|
return SpriteType.TmpRA;
|
||||||
|
|
||||||
|
if (IsTmpTD(s))
|
||||||
|
return SpriteType.TmpTD;
|
||||||
|
|
||||||
|
if (IsShpD2(s))
|
||||||
|
return SpriteType.ShpD2;
|
||||||
|
|
||||||
|
return SpriteType.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ISpriteSource LoadSpriteSource(Stream s, string filename)
|
||||||
|
{
|
||||||
|
var type = DetectSpriteType(s);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SpriteType.ShpTD:
|
||||||
|
return new ShpReader(s);
|
||||||
|
case SpriteType.ShpTS:
|
||||||
|
return new ShpTSReader(s);
|
||||||
|
case SpriteType.R8:
|
||||||
|
return new R8Reader(s);
|
||||||
|
case SpriteType.TmpRA:
|
||||||
|
return new TmpRAReader(s);
|
||||||
|
case SpriteType.TmpTD:
|
||||||
|
return new TmpTDReader(s);
|
||||||
|
case SpriteType.ShpD2:
|
||||||
|
return new ShpD2Reader(s);
|
||||||
|
case SpriteType.Unknown:
|
||||||
|
default:
|
||||||
|
throw new InvalidDataException(filename + " is not a valid sprite file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.FileFormats/Graphics/TmpRAReader.cs
Normal file
50
OpenRA.FileFormats/Graphics/TmpRAReader.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class TmpRAReader : ISpriteSource
|
||||||
|
{
|
||||||
|
readonly List<TmpTile> tiles = new List<TmpTile>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return tiles.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
|
public TmpRAReader(Stream s)
|
||||||
|
{
|
||||||
|
var width = s.ReadUInt16();
|
||||||
|
var height = s.ReadUInt16();
|
||||||
|
var size = new Size(width, height);
|
||||||
|
|
||||||
|
s.Position += 12;
|
||||||
|
var imgStart = s.ReadUInt32();
|
||||||
|
s.Position += 8;
|
||||||
|
var indexEnd = s.ReadInt32();
|
||||||
|
s.Position += 4;
|
||||||
|
var indexStart = s.ReadInt32();
|
||||||
|
|
||||||
|
s.Position = indexStart;
|
||||||
|
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
|
||||||
|
{
|
||||||
|
if (b != 255)
|
||||||
|
{
|
||||||
|
s.Position = imgStart + b * width * height;
|
||||||
|
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tiles.Add(new TmpTile(null, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
OpenRA.FileFormats/Graphics/TmpTDReader.cs
Normal file
68
OpenRA.FileFormats/Graphics/TmpTDReader.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class TmpTile : ISpriteFrame
|
||||||
|
{
|
||||||
|
public Size Size { get; private set; }
|
||||||
|
public Size FrameSize { get; private set; }
|
||||||
|
public float2 Offset { get { return float2.Zero; } }
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
|
public TmpTile(byte[] data, Size size)
|
||||||
|
{
|
||||||
|
FrameSize = size;
|
||||||
|
Data = data;
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
Data = new byte[0];
|
||||||
|
else
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TmpTDReader : ISpriteSource
|
||||||
|
{
|
||||||
|
readonly List<TmpTile> tiles = new List<TmpTile>();
|
||||||
|
public IEnumerable<ISpriteFrame> Frames { get { return tiles.Cast<ISpriteFrame>(); } }
|
||||||
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
|
public TmpTDReader(Stream s)
|
||||||
|
{
|
||||||
|
var width = s.ReadUInt16();
|
||||||
|
var height = s.ReadUInt16();
|
||||||
|
var size = new Size(width, height);
|
||||||
|
|
||||||
|
s.Position += 8;
|
||||||
|
var imgStart = s.ReadUInt32();
|
||||||
|
s.Position += 8;
|
||||||
|
var indexEnd = s.ReadInt32();
|
||||||
|
var indexStart = s.ReadInt32();
|
||||||
|
|
||||||
|
s.Position = indexStart;
|
||||||
|
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
|
||||||
|
{
|
||||||
|
if (b != 255)
|
||||||
|
{
|
||||||
|
s.Position = imgStart + b * width * height;
|
||||||
|
tiles.Add(new TmpTile(s.ReadBytes(width * height), size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tiles.Add(new TmpTile(null, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#region Copyright & License Information
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
|
||||||
* available to you under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation. For more information,
|
|
||||||
* see COPYING.
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
|
||||||
{
|
|
||||||
public class Terrain
|
|
||||||
{
|
|
||||||
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
|
||||||
public readonly int Width;
|
|
||||||
public readonly int Height;
|
|
||||||
|
|
||||||
public Terrain(Stream s)
|
|
||||||
{
|
|
||||||
// Try loading as a cnc .tem
|
|
||||||
Width = s.ReadUInt16();
|
|
||||||
Height = s.ReadUInt16();
|
|
||||||
|
|
||||||
/*NumTiles = */s.ReadUInt16();
|
|
||||||
/*Zero1 = */s.ReadUInt16();
|
|
||||||
/*uint Size = */s.ReadUInt32();
|
|
||||||
var imgStart = s.ReadUInt32();
|
|
||||||
/*Zero2 = */s.ReadUInt32();
|
|
||||||
|
|
||||||
int indexEnd, indexStart;
|
|
||||||
|
|
||||||
// ID1 = FFFFh for cnc
|
|
||||||
if (s.ReadUInt16() == 65535)
|
|
||||||
{
|
|
||||||
/*ID2 = */s.ReadUInt16();
|
|
||||||
indexEnd = s.ReadInt32();
|
|
||||||
indexStart = s.ReadInt32();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Load as a ra .tem
|
|
||||||
s.Position = 0;
|
|
||||||
Width = s.ReadUInt16();
|
|
||||||
Height = s.ReadUInt16();
|
|
||||||
|
|
||||||
/*NumTiles = */s.ReadUInt16();
|
|
||||||
s.ReadUInt16();
|
|
||||||
/*XDim = */s.ReadUInt16();
|
|
||||||
/*YDim = */s.ReadUInt16();
|
|
||||||
/*uint FileSize = */s.ReadUInt32();
|
|
||||||
imgStart = s.ReadUInt32();
|
|
||||||
s.ReadUInt32();
|
|
||||||
s.ReadUInt32();
|
|
||||||
indexEnd = s.ReadInt32();
|
|
||||||
s.ReadUInt32();
|
|
||||||
indexStart = s.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Position = indexStart;
|
|
||||||
|
|
||||||
foreach (byte b in s.ReadBytes(indexEnd - indexStart))
|
|
||||||
{
|
|
||||||
if (b != 255)
|
|
||||||
{
|
|
||||||
s.Position = imgStart + b * Width * Height;
|
|
||||||
TileBitmapBytes.Add(s.ReadBytes(Width * Height));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
TileBitmapBytes.Add(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -90,19 +90,16 @@
|
|||||||
<Compile Include="FileFormats\Format40.cs" />
|
<Compile Include="FileFormats\Format40.cs" />
|
||||||
<Compile Include="FileFormats\Format80.cs" />
|
<Compile Include="FileFormats\Format80.cs" />
|
||||||
<Compile Include="FileFormats\IniFile.cs" />
|
<Compile Include="FileFormats\IniFile.cs" />
|
||||||
<Compile Include="Graphics\Dune2ShpReader.cs" />
|
|
||||||
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||||
<Compile Include="Graphics\IInputHandler.cs" />
|
<Compile Include="Graphics\IInputHandler.cs" />
|
||||||
<Compile Include="Graphics\PngLoader.cs" />
|
<Compile Include="Graphics\PngLoader.cs" />
|
||||||
<Compile Include="Graphics\ShpReader.cs" />
|
<Compile Include="Graphics\ShpReader.cs" />
|
||||||
<Compile Include="Graphics\ShpWriter.cs" />
|
|
||||||
<Compile Include="Graphics\Vertex.cs" />
|
<Compile Include="Graphics\Vertex.cs" />
|
||||||
<Compile Include="Graphics\VqaReader.cs" />
|
<Compile Include="Graphics\VqaReader.cs" />
|
||||||
<Compile Include="InstallUtils.cs" />
|
<Compile Include="InstallUtils.cs" />
|
||||||
<Compile Include="Manifest.cs" />
|
<Compile Include="Manifest.cs" />
|
||||||
<Compile Include="Map\PlayerReference.cs" />
|
<Compile Include="Map\PlayerReference.cs" />
|
||||||
<Compile Include="Map\SmudgeReference.cs" />
|
<Compile Include="Map\SmudgeReference.cs" />
|
||||||
<Compile Include="Map\Terrain.cs" />
|
|
||||||
<Compile Include="Map\TileReference.cs" />
|
<Compile Include="Map\TileReference.cs" />
|
||||||
<Compile Include="Map\TileSet.cs" />
|
<Compile Include="Map\TileSet.cs" />
|
||||||
<Compile Include="MiniYaml.cs" />
|
<Compile Include="MiniYaml.cs" />
|
||||||
@@ -144,7 +141,6 @@
|
|||||||
<Compile Include="StreamExts.cs" />
|
<Compile Include="StreamExts.cs" />
|
||||||
<Compile Include="FileFormats\WavLoader.cs" />
|
<Compile Include="FileFormats\WavLoader.cs" />
|
||||||
<Compile Include="Graphics\R8Reader.cs" />
|
<Compile Include="Graphics\R8Reader.cs" />
|
||||||
<Compile Include="Graphics\TileSetRenderer.cs" />
|
|
||||||
<Compile Include="Keycode.cs" />
|
<Compile Include="Keycode.cs" />
|
||||||
<Compile Include="Hotkey.cs" />
|
<Compile Include="Hotkey.cs" />
|
||||||
<Compile Include="FileSystem\FileSystem.cs" />
|
<Compile Include="FileSystem\FileSystem.cs" />
|
||||||
@@ -153,6 +149,10 @@
|
|||||||
<Compile Include="FileSystem\MixFile.cs" />
|
<Compile Include="FileSystem\MixFile.cs" />
|
||||||
<Compile Include="FileSystem\ZipFile.cs" />
|
<Compile Include="FileSystem\ZipFile.cs" />
|
||||||
<Compile Include="FileSystem\D2kSoundResources.cs" />
|
<Compile Include="FileSystem\D2kSoundResources.cs" />
|
||||||
|
<Compile Include="Graphics\SpriteSource.cs" />
|
||||||
|
<Compile Include="Graphics\TmpRAReader.cs" />
|
||||||
|
<Compile Include="Graphics\TmpTDReader.cs" />
|
||||||
|
<Compile Include="Graphics\ShpD2Reader.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.FileFormats.Graphics;
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
namespace OpenRA.Graphics
|
namespace OpenRA.Graphics
|
||||||
@@ -52,9 +53,14 @@ namespace OpenRA.Graphics
|
|||||||
this.allocateSheet = allocateSheet;
|
this.allocateSheet = allocateSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, frame.Offset); }
|
||||||
public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); }
|
public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); }
|
||||||
public Sprite Add(byte[] src, Size size, float2 spriteOffset)
|
public Sprite Add(byte[] src, Size size, float2 spriteOffset)
|
||||||
{
|
{
|
||||||
|
// Don't bother allocating empty sprites
|
||||||
|
if (size.Width == 0 || size.Height == 0)
|
||||||
|
return new Sprite(current, Rectangle.Empty, spriteOffset, channel, BlendMode.Alpha);
|
||||||
|
|
||||||
var rect = Allocate(size, spriteOffset);
|
var rect = Allocate(size, spriteOffset);
|
||||||
Util.FastCopyIntoChannel(rect, src);
|
Util.FastCopyIntoChannel(rect, src);
|
||||||
current.CommitData();
|
current.CommitData();
|
||||||
|
|||||||
@@ -16,39 +16,25 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
public class SpriteLoader
|
public class SpriteLoader
|
||||||
{
|
{
|
||||||
public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
|
|
||||||
{
|
|
||||||
SheetBuilder = sheetBuilder;
|
|
||||||
this.exts = exts;
|
|
||||||
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)
|
public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
|
||||||
{
|
{
|
||||||
// TODO: Cleanly abstract file type detection
|
SheetBuilder = sheetBuilder;
|
||||||
if (filename.ToLower().EndsWith("r8"))
|
|
||||||
{
|
|
||||||
var r8 = new R8Reader(FileSystem.Open(filename));
|
|
||||||
return r8.Select(a => SheetBuilder.Add(a.Image, a.Size, a.Offset)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
BinaryReader reader = new BinaryReader(FileSystem.OpenWithExts(filename, exts));
|
// Include extension-less version
|
||||||
|
this.exts = exts.Append("").ToArray();
|
||||||
|
sprites = new Cache<string, Sprite[]>(CacheSpriteFrames);
|
||||||
|
}
|
||||||
|
|
||||||
var ImageCount = reader.ReadUInt16();
|
Sprite[] CacheSpriteFrames(string filename)
|
||||||
if (ImageCount == 0)
|
{
|
||||||
{
|
var stream = FileSystem.OpenWithExts(filename, exts);
|
||||||
var shp = new ShpTSReader(FileSystem.OpenWithExts(filename, exts));
|
return SpriteSource.LoadSpriteSource(stream, filename).Frames
|
||||||
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
|
.Select(a => SheetBuilder.Add(a))
|
||||||
}
|
.ToArray();
|
||||||
else
|
|
||||||
{
|
|
||||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
|
||||||
return shp.Frames.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]; }
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
@@ -22,27 +23,31 @@ namespace OpenRA.Graphics
|
|||||||
Dictionary<ushort, Sprite[]> templates;
|
Dictionary<ushort, Sprite[]> templates;
|
||||||
Sprite missingTile;
|
Sprite missingTile;
|
||||||
|
|
||||||
Sprite[] LoadTemplate(string filename, string[] exts, Cache<string, R8Reader> r8Cache, int[] frames)
|
Sprite[] LoadTemplate(string filename, string[] exts, Dictionary<string, ISpriteSource> sourceCache, int[] frames)
|
||||||
{
|
{
|
||||||
if (exts.Contains(".R8") && FileSystem.Exists(filename+".R8"))
|
ISpriteSource source;
|
||||||
|
if (!sourceCache.ContainsKey(filename))
|
||||||
{
|
{
|
||||||
return frames.Select(f =>
|
using (var s = FileSystem.OpenWithExts(filename, exts))
|
||||||
{
|
source = SpriteSource.LoadSpriteSource(s, filename);
|
||||||
if (f < 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var image = r8Cache[filename][f];
|
if (source.CacheWhenLoadingTileset)
|
||||||
return sheetBuilder.Add(image.Image, new Size(image.Size.Width, image.Size.Height));
|
sourceCache.Add(filename, source);
|
||||||
}).ToArray();
|
}
|
||||||
|
else
|
||||||
|
source = sourceCache[filename];
|
||||||
|
|
||||||
|
if (frames != null)
|
||||||
|
{
|
||||||
|
var ret = new List<Sprite>();
|
||||||
|
var srcFrames = source.Frames.ToArray();
|
||||||
|
foreach (var i in frames)
|
||||||
|
ret.Add(sheetBuilder.Add(srcFrames[i]));
|
||||||
|
|
||||||
|
return ret.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var s = FileSystem.OpenWithExts(filename, exts))
|
return source.Frames.Select(f => sheetBuilder.Add(f)).ToArray();
|
||||||
{
|
|
||||||
var t = new Terrain(s);
|
|
||||||
return t.TileBitmapBytes
|
|
||||||
.Select(b => b != null ? sheetBuilder.Add(b, new Size(t.Width, t.Height)) : null)
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Theater(TileSet tileset)
|
public Theater(TileSet tileset)
|
||||||
@@ -57,11 +62,11 @@ namespace OpenRA.Graphics
|
|||||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
|
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
|
||||||
};
|
};
|
||||||
|
|
||||||
var r8Cache = new Cache<string, R8Reader>(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
|
var sourceCache = new Dictionary<string, ISpriteSource>();
|
||||||
templates = new Dictionary<ushort, Sprite[]>();
|
templates = new Dictionary<ushort, Sprite[]>();
|
||||||
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
||||||
foreach (var t in tileset.Templates)
|
foreach (var t in tileset.Templates)
|
||||||
templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, r8Cache, t.Value.Frames));
|
templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames));
|
||||||
|
|
||||||
// 1x1px transparent tile
|
// 1x1px transparent tile
|
||||||
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
|
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
|
||||||
@@ -70,11 +75,13 @@ namespace OpenRA.Graphics
|
|||||||
public Sprite TileSprite(TileReference<ushort, byte> r)
|
public Sprite TileSprite(TileReference<ushort, byte> r)
|
||||||
{
|
{
|
||||||
Sprite[] template;
|
Sprite[] template;
|
||||||
if (templates.TryGetValue(r.Type, out template))
|
if (!templates.TryGetValue(r.Type, out template))
|
||||||
if (template.Length > r.Index && template[r.Index] != null)
|
return missingTile;
|
||||||
return template[r.Index];
|
|
||||||
|
|
||||||
return missingTile;
|
if (r.Index >= template.Length)
|
||||||
|
return missingTile;
|
||||||
|
|
||||||
|
return template[r.Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sheet Sheet { get { return sheetBuilder.Current; } }
|
public Sheet Sheet { get { return sheetBuilder.Current; } }
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace OpenRA
|
|||||||
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
|
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
|
||||||
ChromeProvider.Initialize(Manifest.Chrome);
|
ChromeProvider.Initialize(Manifest.Chrome);
|
||||||
SheetBuilder = new SheetBuilder(SheetType.Indexed);
|
SheetBuilder = new SheetBuilder(SheetType.Indexed);
|
||||||
SpriteLoader = new SpriteLoader(new string[] { ".shp" }, SheetBuilder);
|
SpriteLoader = new SpriteLoader(new string[0], SheetBuilder);
|
||||||
VoxelLoader = new VoxelLoader();
|
VoxelLoader = new VoxelLoader();
|
||||||
CursorProvider.Initialize(Manifest.Cursors);
|
CursorProvider.Initialize(Manifest.Cursors);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace OpenRA.Widgets
|
|||||||
Sprite sprite = null;
|
Sprite sprite = null;
|
||||||
string cachedImage = null;
|
string cachedImage = null;
|
||||||
int cachedFrame = -1;
|
int cachedFrame = -1;
|
||||||
|
float2 cachedOffset = float2.Zero;
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
@@ -68,9 +69,10 @@ namespace OpenRA.Widgets
|
|||||||
sprite = Game.modData.SpriteLoader.LoadAllSprites(image)[frame];
|
sprite = Game.modData.SpriteLoader.LoadAllSprites(image)[frame];
|
||||||
cachedImage = image;
|
cachedImage = image;
|
||||||
cachedFrame = frame;
|
cachedFrame = frame;
|
||||||
|
cachedOffset = 0.5f * (new float2(RenderBounds.Size) - sprite.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin, worldRenderer.Palette(palette));
|
Game.Renderer.SpriteRenderer.DrawSprite(sprite, RenderOrigin + cachedOffset, worldRenderer.Palette(palette));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int FrameCount
|
public int FrameCount
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ namespace OpenRA.Widgets
|
|||||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(s,pos);
|
Game.Renderer.RgbaSpriteRenderer.DrawSprite(s,pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr)
|
public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"));
|
Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * s.size, wr.Palette("chrome"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr, float2 size)
|
public static void DrawSHPCentered(Sprite s, float2 pos, WorldRenderer wr, float scale)
|
||||||
{
|
{
|
||||||
Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr.Palette("chrome"), size);
|
Game.Renderer.SpriteRenderer.DrawSprite(s, pos - 0.5f * scale * s.size, wr.Palette("chrome"), scale * s.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawPanel(string collection, Rectangle Bounds)
|
public static void DrawPanel(string collection, Rectangle Bounds)
|
||||||
|
|||||||
@@ -197,11 +197,14 @@ namespace OpenRA.Mods.Cnc.Widgets
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
|
var iconSize = new float2(64, 48);
|
||||||
|
var iconOffset = 0.5f * iconSize;
|
||||||
|
|
||||||
overlayFont = Game.Renderer.Fonts["TinyBold"];
|
overlayFont = Game.Renderer.Fonts["TinyBold"];
|
||||||
timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
|
timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
|
||||||
queuedOffset = new float2(4, 2);
|
queuedOffset = new float2(4, 2);
|
||||||
holdOffset = new float2(32, 24) - overlayFont.Measure(HoldText) / 2;
|
holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
|
||||||
readyOffset = new float2(32, 24) - overlayFont.Measure(ReadyText) / 2;
|
readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
|
||||||
|
|
||||||
if (CurrentQueue == null)
|
if (CurrentQueue == null)
|
||||||
return;
|
return;
|
||||||
@@ -215,7 +218,7 @@ namespace OpenRA.Mods.Cnc.Widgets
|
|||||||
// Icons
|
// Icons
|
||||||
foreach (var icon in icons.Values)
|
foreach (var icon in icons.Values)
|
||||||
{
|
{
|
||||||
WidgetUtils.DrawSHP(icon.Sprite, icon.Pos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, worldRenderer);
|
||||||
|
|
||||||
// Build progress
|
// Build progress
|
||||||
if (icon.Queued.Count > 0)
|
if (icon.Queued.Count > 0)
|
||||||
@@ -225,10 +228,10 @@ namespace OpenRA.Mods.Cnc.Widgets
|
|||||||
() => (first.TotalTime - first.RemainingTime)
|
() => (first.TotalTime - first.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / first.TotalTime);
|
* (clock.CurrentSequence.Length - 1) / first.TotalTime);
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
WidgetUtils.DrawSHP(clock.Image, icon.Pos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(clock.Image, icon.Pos + iconOffset, worldRenderer);
|
||||||
}
|
}
|
||||||
else if (!buildableItems.Any(a => a.Name == icon.Name))
|
else if (!buildableItems.Any(a => a.Name == icon.Name))
|
||||||
WidgetUtils.DrawSHP(cantBuild.Image, icon.Pos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, worldRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlays
|
// Overlays
|
||||||
|
|||||||
@@ -89,10 +89,13 @@ namespace OpenRA.Mods.Cnc.Widgets
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
|
var iconSize = new float2(64, 48);
|
||||||
|
var iconOffset = 0.5f * iconSize;
|
||||||
|
|
||||||
overlayFont = Game.Renderer.Fonts["TinyBold"];
|
overlayFont = Game.Renderer.Fonts["TinyBold"];
|
||||||
holdOffset = new float2(32, 24) - overlayFont.Measure(HoldText) / 2;
|
holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
|
||||||
readyOffset = new float2(32, 24) - overlayFont.Measure(ReadyText) / 2;
|
readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
|
||||||
timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
|
timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
foreach (var rect in icons.Keys)
|
foreach (var rect in icons.Keys)
|
||||||
@@ -101,14 +104,14 @@ namespace OpenRA.Mods.Cnc.Widgets
|
|||||||
// Icons
|
// Icons
|
||||||
foreach (var p in icons.Values)
|
foreach (var p in icons.Values)
|
||||||
{
|
{
|
||||||
WidgetUtils.DrawSHP(p.Sprite, p.Pos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, worldRenderer);
|
||||||
|
|
||||||
// Charge progress
|
// Charge progress
|
||||||
clock.PlayFetchIndex("idle",
|
clock.PlayFetchIndex("idle",
|
||||||
() => (p.Power.TotalTime - p.Power.RemainingTime)
|
() => (p.Power.TotalTime - p.Power.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / p.Power.TotalTime);
|
* (clock.CurrentSequence.Length - 1) / p.Power.TotalTime);
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
WidgetUtils.DrawSHP(clock.Image, p.Pos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, worldRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
|
|||||||
@@ -33,9 +33,9 @@
|
|||||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>False</Optimize>
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
@@ -47,17 +47,17 @@
|
|||||||
</CustomCommands>
|
</CustomCommands>
|
||||||
</CustomCommands>
|
</CustomCommands>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>True</Optimize>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="FuzzyLogicLibrary">
|
<Reference Include="FuzzyLogicLibrary">
|
||||||
@@ -70,14 +70,13 @@
|
|||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
<HintPath>..\thirdparty\ICSharpCode.SharpZipLib.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Mono.Nat">
|
<Reference Include="Mono.Nat">
|
||||||
<HintPath>..\thirdparty\Mono.Nat.dll</HintPath>
|
<HintPath>..\thirdparty\Mono.Nat.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="ICSharpCode.SharpZipLib">
|
||||||
|
<HintPath>..\thirdparty\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Activities\CaptureActor.cs" />
|
<Compile Include="Activities\CaptureActor.cs" />
|
||||||
@@ -444,7 +443,6 @@
|
|||||||
<Compile Include="Widgets\HueSliderWidget.cs" />
|
<Compile Include="Widgets\HueSliderWidget.cs" />
|
||||||
<Compile Include="Render\WithTurret.cs" />
|
<Compile Include="Render\WithTurret.cs" />
|
||||||
<Compile Include="Widgets\Logic\AssetBrowserLogic.cs" />
|
<Compile Include="Widgets\Logic\AssetBrowserLogic.cs" />
|
||||||
<Compile Include="Widgets\Logic\ConvertGameFilesLogic.cs" />
|
|
||||||
<Compile Include="VoxelNormalsPalette.cs" />
|
<Compile Include="VoxelNormalsPalette.cs" />
|
||||||
<Compile Include="Render\RenderVoxels.cs" />
|
<Compile Include="Render\RenderVoxels.cs" />
|
||||||
<Compile Include="Render\WithVoxelTurret.cs" />
|
<Compile Include="Render\WithVoxelTurret.cs" />
|
||||||
@@ -481,7 +479,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\LuaInterface\LuaInterface.csproj">
|
<ProjectReference Include="..\LuaInterface\LuaInterface.csproj">
|
||||||
<Project>{e915a0a4-2641-4f7e-8a88-8f123fa88bf1}</Project>
|
<Project>{E915A0A4-2641-4F7E-8A88-8F123FA88BF1}</Project>
|
||||||
<Name>LuaInterface</Name>
|
<Name>LuaInterface</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||||
@@ -495,13 +493,9 @@
|
|||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\OpenRA.Irc\OpenRA.Irc.csproj">
|
<ProjectReference Include="..\OpenRA.Irc\OpenRA.Irc.csproj">
|
||||||
<Project>{85b48234-8b31-4be6-af9c-665cc6866841}</Project>
|
<Project>{85B48234-8B31-4BE6-AF9C-665CC6866841}</Project>
|
||||||
<Name>OpenRA.Irc</Name>
|
<Name>OpenRA.Irc</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\OpenRA.Utility\OpenRA.Utility.csproj">
|
|
||||||
<Project>{F33337BE-CB69-4B24-850F-07D23E408DDF}</Project>
|
|
||||||
<Name>OpenRA.Utility</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\GeoIP\GeoIP.csproj">
|
<ProjectReference Include="..\GeoIP\GeoIP.csproj">
|
||||||
<Project>{021DDD6A-A608-424C-9A9A-252D8A9989E0}</Project>
|
<Project>{021DDD6A-A608-424C-9A9A-252D8A9989E0}</Project>
|
||||||
<Name>GeoIP</Name>
|
<Name>GeoIP</Name>
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
|
|
||||||
string paletteCollection = "palette-" + world.LocalPlayer.Country.Race;
|
string paletteCollection = "palette-" + world.LocalPlayer.Country.Race;
|
||||||
float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9);
|
float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9);
|
||||||
|
var iconOffset = 0.5f * new float2(IconWidth, IconHeight);
|
||||||
var x = 0;
|
var x = 0;
|
||||||
var y = 0;
|
var y = 0;
|
||||||
|
|
||||||
@@ -233,7 +234,7 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
var drawPos = new float2(rect.Location);
|
var drawPos = new float2(rect.Location);
|
||||||
var icon = new Animation(RenderSimple.GetImage(item));
|
var icon = new Animation(RenderSimple.GetImage(item));
|
||||||
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
|
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
|
||||||
WidgetUtils.DrawSHP(icon.Image, drawPos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(icon.Image, drawPos + iconOffset, worldRenderer);
|
||||||
|
|
||||||
var firstOfThis = queue.AllQueued().FirstOrDefault(a => a.Item == item.Name);
|
var firstOfThis = queue.AllQueued().FirstOrDefault(a => a.Item == item.Name);
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
() => (firstOfThis.TotalTime - firstOfThis.RemainingTime)
|
() => (firstOfThis.TotalTime - firstOfThis.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / firstOfThis.TotalTime);
|
* (clock.CurrentSequence.Length - 1) / firstOfThis.TotalTime);
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(clock.Image, drawPos + iconOffset, worldRenderer);
|
||||||
|
|
||||||
if (queue.CurrentItem() == firstOfThis)
|
if (queue.CurrentItem() == firstOfThis)
|
||||||
textBits.Add(Pair.New(overlayPos, GetOverlayForItem(firstOfThis)));
|
textBits.Add(Pair.New(overlayPos, GetOverlayForItem(firstOfThis)));
|
||||||
@@ -269,7 +270,7 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
if (x != 0) y++;
|
if (x != 0) y++;
|
||||||
|
|
||||||
foreach (var ob in overlayBits)
|
foreach (var ob in overlayBits)
|
||||||
WidgetUtils.DrawSHP(ob.First, ob.Second, worldRenderer);
|
WidgetUtils.DrawSHPCentered(ob.First, ob.Second + iconOffset, worldRenderer);
|
||||||
|
|
||||||
var font = Game.Renderer.Fonts["TinyBold"];
|
var font = Game.Renderer.Fonts["TinyBold"];
|
||||||
foreach (var tb in textBits)
|
foreach (var tb in textBits)
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
|
|
||||||
PaletteFromFile currentPalette;
|
PaletteFromFile currentPalette;
|
||||||
|
|
||||||
|
static readonly string[] AllowedExtensions = { ".shp", ".r8", ".tem", ".des", ".sno", ".int" };
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public AssetBrowserLogic(Widget widget, Action onExit, World world)
|
public AssetBrowserLogic(Widget widget, Action onExit, World world)
|
||||||
{
|
{
|
||||||
@@ -60,6 +62,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
|
|
||||||
var paletteDropDown = panel.Get<DropDownButtonWidget>("PALETTE_SELECTOR");
|
var paletteDropDown = panel.Get<DropDownButtonWidget>("PALETTE_SELECTOR");
|
||||||
paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
|
paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
|
||||||
|
paletteDropDown.GetText = () => currentPalette.Name;
|
||||||
|
|
||||||
var colorPreview = panel.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
|
var colorPreview = panel.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
|
||||||
colorPreview.Color = Game.Settings.Player.Color;
|
colorPreview.Color = Game.Settings.Player.Color;
|
||||||
@@ -80,7 +83,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
frameSlider.OnChange += x => { spriteWidget.Frame = (int)Math.Round(x); };
|
frameSlider.OnChange += x => { spriteWidget.Frame = (int)Math.Round(x); };
|
||||||
frameSlider.GetValue = () => spriteWidget.Frame;
|
frameSlider.GetValue = () => spriteWidget.Frame;
|
||||||
|
|
||||||
panel.Get<LabelWidget>("FRAME_COUNT").GetText = () => "{0}/{1}".F(spriteWidget.Frame, spriteWidget.FrameCount);
|
panel.Get<LabelWidget>("FRAME_COUNT").GetText = () => "{0} / {1}".F(spriteWidget.Frame + 1, spriteWidget.FrameCount + 1);
|
||||||
|
|
||||||
playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
|
playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
|
||||||
playButton.OnClick = () =>
|
playButton.OnClick = () =>
|
||||||
@@ -118,96 +121,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
template = panel.Get<ScrollItemWidget>("ASSET_TEMPLATE");
|
template = panel.Get<ScrollItemWidget>("ASSET_TEMPLATE");
|
||||||
PopulateAssetList();
|
PopulateAssetList();
|
||||||
|
|
||||||
var modID = Game.modData.Manifest.Mod.Id;
|
|
||||||
|
|
||||||
// TODO: This should not invoke the OpenRA.Utility.exe, but use it's functions directly.
|
|
||||||
// TODO: Does not work with SHP(TS) yet?!
|
|
||||||
panel.Get<ButtonWidget>("EXPORT_BUTTON").OnClick = () =>
|
|
||||||
{
|
|
||||||
var ExtractGameFiles = new string[][]
|
|
||||||
{
|
|
||||||
new string[] { "--extract", modID, currentPalette.Filename, "--userdir" },
|
|
||||||
new string[] { "--extract", modID, "{0}.shp".F(spriteWidget.Image), "--userdir" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var ExportToPng = new string[][]
|
|
||||||
{
|
|
||||||
new string[] { "--png", Platform.SupportDir + "{0}.shp".F(spriteWidget.Image), Platform.SupportDir + currentPalette.Filename },
|
|
||||||
};
|
|
||||||
|
|
||||||
var ImportFromPng = new string[][] { };
|
|
||||||
|
|
||||||
var args = new WidgetArgs()
|
|
||||||
{
|
|
||||||
{ "ExtractGameFiles", ExtractGameFiles },
|
|
||||||
{ "ExportToPng", ExportToPng },
|
|
||||||
{ "ImportFromPng", ImportFromPng }
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
|
|
||||||
};
|
|
||||||
|
|
||||||
panel.Get<ButtonWidget>("EXTRACT_BUTTON").OnClick = () =>
|
|
||||||
{
|
|
||||||
var ExtractGameFilesList = new List<string[]>();
|
|
||||||
var ExportToPngList = new List<string[]>();
|
|
||||||
|
|
||||||
ExtractGameFilesList.Add(new string[] { "--extract", modID, currentPalette.Filename, "--userdir" });
|
|
||||||
|
|
||||||
foreach (var shp in availableShps)
|
|
||||||
{
|
|
||||||
ExtractGameFilesList.Add(new string[] { "--extract", modID, shp, "--userdir" });
|
|
||||||
ExportToPngList.Add(new string[] { "--png", Platform.SupportDir + shp, Platform.SupportDir + currentPalette.Filename });
|
|
||||||
Console.WriteLine(Platform.SupportDir + shp);
|
|
||||||
}
|
|
||||||
|
|
||||||
var ExtractGameFiles = ExtractGameFilesList.ToArray();
|
|
||||||
var ExportToPng = ExportToPngList.ToArray();
|
|
||||||
var ImportFromPng = new string[][] { };
|
|
||||||
|
|
||||||
var args = new WidgetArgs()
|
|
||||||
{
|
|
||||||
{ "ExtractGameFiles", ExtractGameFiles },
|
|
||||||
{ "ExportToPng", ExportToPng },
|
|
||||||
{ "ImportFromPng", ImportFromPng }
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
|
|
||||||
};
|
|
||||||
|
|
||||||
panel.Get<ButtonWidget>("IMPORT_BUTTON").OnClick = () =>
|
|
||||||
{
|
|
||||||
var imageSizeInput = panel.Get<TextFieldWidget>("IMAGE_SIZE_INPUT");
|
|
||||||
var imageFilename = panel.Get<TextFieldWidget>("IMAGE_FILENAME_INPUT");
|
|
||||||
|
|
||||||
var ExtractGameFiles = new string[][] { };
|
|
||||||
var ExportToPng = new string[][] { };
|
|
||||||
var ImportFromPng = new string[][]
|
|
||||||
{
|
|
||||||
new string[] { "--shp", Platform.SupportDir + imageFilename.Text, imageSizeInput.Text },
|
|
||||||
};
|
|
||||||
|
|
||||||
var args = new WidgetArgs()
|
|
||||||
{
|
|
||||||
{ "ExtractGameFiles", ExtractGameFiles },
|
|
||||||
{ "ExportToPng", ExportToPng },
|
|
||||||
{ "ImportFromPng", ImportFromPng }
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui.OpenWindow("CONVERT_ASSETS_PANEL", args);
|
|
||||||
};
|
|
||||||
|
|
||||||
panel.Get<ButtonWidget>("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
|
panel.Get<ButtonWidget>("CLOSE_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template)
|
void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template)
|
||||||
{
|
{
|
||||||
var r8 = filepath.EndsWith(".r8", true, CultureInfo.InvariantCulture);
|
var filename = Path.GetFileName(filepath);
|
||||||
var filename = Path.GetFileName(filepath);
|
|
||||||
var sprite = r8 ? filename : Path.GetFileNameWithoutExtension(filepath);
|
|
||||||
var item = ScrollItemWidget.Setup(template,
|
var item = ScrollItemWidget.Setup(template,
|
||||||
() => spriteWidget.Image == sprite,
|
() => spriteWidget.Image == filename,
|
||||||
() => {filenameInput.Text = filename; LoadAsset(filename); });
|
() => { filenameInput.Text = filename; LoadAsset(filename); });
|
||||||
item.Get<LabelWidget>("TITLE").GetText = () => filepath;
|
item.Get<LabelWidget>("TITLE").GetText = () => filepath;
|
||||||
|
|
||||||
list.AddChild(item);
|
list.AddChild(item);
|
||||||
@@ -221,11 +143,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
if (!FileSystem.Exists(filename))
|
if (!FileSystem.Exists(filename))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var r8 = filename.EndsWith(".r8", true, CultureInfo.InvariantCulture);
|
|
||||||
var sprite = r8 ? filename : Path.GetFileNameWithoutExtension(filename);
|
|
||||||
|
|
||||||
spriteWidget.Frame = 0;
|
spriteWidget.Frame = 0;
|
||||||
spriteWidget.Image = sprite;
|
spriteWidget.Image = filename;
|
||||||
frameSlider.MaximumValue = (float)spriteWidget.FrameCount;
|
frameSlider.MaximumValue = (float)spriteWidget.FrameCount;
|
||||||
frameSlider.Ticks = spriteWidget.FrameCount + 1;
|
frameSlider.Ticks = spriteWidget.FrameCount + 1;
|
||||||
return true;
|
return true;
|
||||||
@@ -265,7 +184,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var files = assetSource.AllFileNames();
|
var files = assetSource.AllFileNames();
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
if (file.EndsWith(".shp", true, CultureInfo.InvariantCulture) || file.EndsWith(".r8", true, CultureInfo.InvariantCulture))
|
if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))
|
||||||
{
|
{
|
||||||
AddAsset(assetList, file, template);
|
AddAsset(assetList, file, template);
|
||||||
availableShps.Add(file);
|
availableShps.Add(file);
|
||||||
@@ -278,8 +197,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
Func<PaletteFromFile, ScrollItemWidget, ScrollItemWidget> setupItem = (palette, itemTemplate) =>
|
Func<PaletteFromFile, ScrollItemWidget, ScrollItemWidget> setupItem = (palette, itemTemplate) =>
|
||||||
{
|
{
|
||||||
var item = ScrollItemWidget.Setup(itemTemplate,
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
() => currentPalette.Name == palette.Name,
|
() => currentPalette.Name == palette.Name,
|
||||||
() => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; });
|
() => { currentPalette = palette; spriteWidget.Palette = currentPalette.Name; });
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => palette.Name;
|
item.Get<LabelWidget>("LABEL").GetText = () => palette.Name;
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
#region Copyright & License Information
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
|
||||||
* available to you under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation. For more information,
|
|
||||||
* see COPYING.
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using OpenRA.Utility;
|
|
||||||
using OpenRA.Widgets;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
|
||||||
{
|
|
||||||
public class ConvertGameFilesLogic
|
|
||||||
{
|
|
||||||
Widget panel;
|
|
||||||
ProgressBarWidget progressBar;
|
|
||||||
LabelWidget statusLabel;
|
|
||||||
ButtonWidget retryButton, backButton;
|
|
||||||
Widget extractingContainer;
|
|
||||||
|
|
||||||
string[][] ExtractGameFiles, ExportToPng, ImportFromPng;
|
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
|
||||||
public ConvertGameFilesLogic(Widget widget, string[][] ExtractGameFiles, string[][] ExportToPng, string[][] ImportFromPng)
|
|
||||||
{
|
|
||||||
panel = widget.Get("CONVERT_ASSETS_PANEL");
|
|
||||||
progressBar = panel.Get<ProgressBarWidget>("PROGRESS_BAR");
|
|
||||||
statusLabel = panel.Get<LabelWidget>("STATUS_LABEL");
|
|
||||||
|
|
||||||
backButton = panel.Get<ButtonWidget>("BACK_BUTTON");
|
|
||||||
backButton.OnClick = Ui.CloseWindow;
|
|
||||||
|
|
||||||
retryButton = panel.Get<ButtonWidget>("RETRY_BUTTON");
|
|
||||||
retryButton.OnClick = Extract;
|
|
||||||
|
|
||||||
extractingContainer = panel.Get("EXTRACTING");
|
|
||||||
|
|
||||||
this.ExtractGameFiles = ExtractGameFiles;
|
|
||||||
this.ExportToPng = ExportToPng;
|
|
||||||
this.ImportFromPng = ImportFromPng;
|
|
||||||
|
|
||||||
Extract();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Extract()
|
|
||||||
{
|
|
||||||
backButton.IsDisabled = () => true;
|
|
||||||
retryButton.IsDisabled = () => true;
|
|
||||||
extractingContainer.IsVisible = () => true;
|
|
||||||
|
|
||||||
var onError = (Action<string>)(s => Game.RunAfterTick(() =>
|
|
||||||
{
|
|
||||||
statusLabel.GetText = () => "Error: "+s;
|
|
||||||
backButton.IsDisabled = () => false;
|
|
||||||
retryButton.IsDisabled = () => false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
var t = new Thread( _ =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ExtractGameFiles.Length; i++)
|
|
||||||
{
|
|
||||||
progressBar.Percentage = i*100/ExtractGameFiles.Count();
|
|
||||||
statusLabel.GetText = () => "Extracting...";
|
|
||||||
Command.ExtractFiles(ExtractGameFiles[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ExportToPng.Length; i++)
|
|
||||||
{
|
|
||||||
progressBar.Percentage = i*100/ExportToPng.Count();
|
|
||||||
statusLabel.GetText = () => "Exporting SHP to PNG...";
|
|
||||||
Command.ConvertShpToPng(ExportToPng[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ImportFromPng.Length; i++)
|
|
||||||
{
|
|
||||||
progressBar.Percentage = i*100/ImportFromPng.Count();
|
|
||||||
statusLabel.GetText = () => "Converting PNG to SHP...";
|
|
||||||
Command.ConvertPngToShp(ImportFromPng[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Game.RunAfterTick(() =>
|
|
||||||
{
|
|
||||||
progressBar.Percentage = 100;
|
|
||||||
statusLabel.GetText = () => "Done. Check {0}".F(Platform.SupportDir);
|
|
||||||
backButton.IsDisabled = () => false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException f)
|
|
||||||
{
|
|
||||||
onError(f.FileName+" not found.");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
onError(e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}) { IsBackground = true };
|
|
||||||
t.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,10 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
WorldRenderer worldRenderer;
|
WorldRenderer worldRenderer;
|
||||||
Dictionary<ProductionQueue, Animation> clocks;
|
Dictionary<ProductionQueue, Animation> clocks;
|
||||||
|
|
||||||
|
public int IconWidth = 32;
|
||||||
|
public int IconHeight = 24;
|
||||||
|
public int IconSpacing = 8;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public ObserverProductionIconsWidget(World world, WorldRenderer worldRenderer)
|
public ObserverProductionIconsWidget(World world, WorldRenderer worldRenderer)
|
||||||
{
|
{
|
||||||
@@ -59,6 +63,8 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
clocks.Add(queue.Trait, new Animation("clock"));
|
clocks.Add(queue.Trait, new Animation("clock"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iconSize = new float2(IconWidth, IconHeight);
|
||||||
foreach (var queue in queues)
|
foreach (var queue in queues)
|
||||||
{
|
{
|
||||||
var current = queue.Trait.CurrentItem();
|
var current = queue.Trait.CurrentItem();
|
||||||
@@ -71,16 +77,15 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
|
|
||||||
var icon = new Animation(RenderSimple.GetImage(actor));
|
var icon = new Animation(RenderSimple.GetImage(actor));
|
||||||
icon.Play(actor.Traits.Get<TooltipInfo>().Icon);
|
icon.Play(actor.Traits.Get<TooltipInfo>().Icon);
|
||||||
var size = icon.Image.size / new float2(2, 2);
|
var location = new float2(RenderBounds.Location) + new float2(queue.i * (IconWidth + IconSpacing), 0);
|
||||||
var location = new float2(RenderBounds.Location) + new float2(queue.i * (int)size.Length, 0);
|
WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
|
||||||
WidgetUtils.DrawSHP(icon.Image, location, worldRenderer, size);
|
|
||||||
|
|
||||||
var clock = clocks[queue.Trait];
|
var clock = clocks[queue.Trait];
|
||||||
clock.PlayFetchIndex("idle",
|
clock.PlayFetchIndex("idle",
|
||||||
() => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime)
|
() => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / current.TotalTime));
|
* (clock.CurrentSequence.Length - 1) / current.TotalTime));
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
WidgetUtils.DrawSHP(clock.Image, location, worldRenderer, size);
|
WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
|
||||||
|
|
||||||
var tiny = Game.Renderer.Fonts["Tiny"];
|
var tiny = Game.Renderer.Fonts["Tiny"];
|
||||||
var text = GetOverlayForItem(current);
|
var text = GetOverlayForItem(current);
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
WorldRenderer worldRenderer;
|
WorldRenderer worldRenderer;
|
||||||
Dictionary<string, Animation> clocks;
|
Dictionary<string, Animation> clocks;
|
||||||
|
|
||||||
|
public int IconWidth = 32;
|
||||||
|
public int IconHeight = 24;
|
||||||
|
public int IconSpacing = 8;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer)
|
public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer)
|
||||||
{
|
{
|
||||||
@@ -61,22 +65,24 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
clocks.Add(power.a.Key, new Animation("clock"));
|
clocks.Add(power.a.Key, new Animation("clock"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iconSize = new float2(IconWidth, IconHeight);
|
||||||
foreach (var power in powers)
|
foreach (var power in powers)
|
||||||
{
|
{
|
||||||
var item = power.a.Value;
|
var item = power.a.Value;
|
||||||
if (item == null || item.Info == null || item.Info.Icon == null)
|
if (item == null || item.Info == null || item.Info.Icon == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
icon.Play(item.Info.Icon);
|
icon.Play(item.Info.Icon);
|
||||||
var size = icon.Image.size / new float2(2, 2);
|
var location = new float2(RenderBounds.Location) + new float2(power.i * (IconWidth + IconSpacing), 0);
|
||||||
var location = new float2(RenderBounds.Location) + new float2(power.i * (int)size.Length, 0);
|
WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
|
||||||
WidgetUtils.DrawSHP(icon.Image, location, worldRenderer, size);
|
|
||||||
|
|
||||||
var clock = clocks[power.a.Key];
|
var clock = clocks[power.a.Key];
|
||||||
clock.PlayFetchIndex("idle",
|
clock.PlayFetchIndex("idle",
|
||||||
() => item.TotalTime == 0 ? 0 : ((item.TotalTime - item.RemainingTime)
|
() => item.TotalTime == 0 ? 0 : ((item.TotalTime - item.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / item.TotalTime));
|
* (clock.CurrentSequence.Length - 1) / item.TotalTime));
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
WidgetUtils.DrawSHP(clock.Image, location, worldRenderer, size);
|
WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f);
|
||||||
|
|
||||||
var tiny = Game.Renderer.Fonts["Tiny"];
|
var tiny = Game.Renderer.Fonts["Tiny"];
|
||||||
var text = GetOverlayForItem(item);
|
var text = GetOverlayForItem(item);
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
[Translate] public string ReadyText = "";
|
[Translate] public string ReadyText = "";
|
||||||
[Translate] public string HoldText = "";
|
[Translate] public string HoldText = "";
|
||||||
|
|
||||||
|
public int IconWidth = 64;
|
||||||
|
public int IconHeight = 48;
|
||||||
|
|
||||||
Animation icon;
|
Animation icon;
|
||||||
Animation clock;
|
Animation clock;
|
||||||
readonly List<Pair<Rectangle, Action<MouseInput>>> buttons = new List<Pair<Rectangle,Action<MouseInput>>>();
|
readonly List<Pair<Rectangle, Action<MouseInput>>> buttons = new List<Pair<Rectangle,Action<MouseInput>>>();
|
||||||
@@ -84,10 +87,11 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-bottom"), new float2(rectBounds.X, rectBounds.Y + numPowers * 51));
|
WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-bottom"), new float2(rectBounds.X, rectBounds.Y + numPowers * 51));
|
||||||
|
|
||||||
// HACK: Hack Hack Hack
|
// HACK: Hack Hack Hack
|
||||||
rectBounds.Width = 69;
|
rectBounds.Width = IconWidth + 5;
|
||||||
rectBounds.Height = 10 + numPowers * 51 + 21;
|
rectBounds.Height = 31 + numPowers * (IconHeight + 3);
|
||||||
|
|
||||||
var y = rectBounds.Y + 10;
|
var y = rectBounds.Y + 10;
|
||||||
|
var iconSize = new float2(IconWidth, IconHeight);
|
||||||
foreach (var kv in powers)
|
foreach (var kv in powers)
|
||||||
{
|
{
|
||||||
var sp = kv.Value;
|
var sp = kv.Value;
|
||||||
@@ -137,14 +141,14 @@ namespace OpenRA.Mods.RA.Widgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetUtils.DrawSHP(icon.Image, drawPos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(icon.Image, drawPos + 0.5f * iconSize, worldRenderer);
|
||||||
|
|
||||||
clock.PlayFetchIndex("idle",
|
clock.PlayFetchIndex("idle",
|
||||||
() => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime)
|
() => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime)
|
||||||
* (clock.CurrentSequence.Length - 1) / sp.TotalTime);
|
* (clock.CurrentSequence.Length - 1) / sp.TotalTime);
|
||||||
clock.Tick();
|
clock.Tick();
|
||||||
|
|
||||||
WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer);
|
WidgetUtils.DrawSHPCentered(clock.Image, drawPos + 0.5f * iconSize, worldRenderer);
|
||||||
|
|
||||||
var overlay = sp.Ready ? ReadyText : sp.Active ? null : HoldText;
|
var overlay = sp.Ready ? ReadyText : sp.Active ? null : HoldText;
|
||||||
var font = Game.Renderer.Fonts["TinyBold"];
|
var font = Game.Renderer.Fonts["TinyBold"];
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using System.Runtime.InteropServices;
|
|||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.FileFormats.Graphics;
|
using OpenRA.FileFormats.Graphics;
|
||||||
using OpenRA.GameRules;
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Utility
|
namespace OpenRA.Utility
|
||||||
@@ -42,46 +43,37 @@ namespace OpenRA.Utility
|
|||||||
|
|
||||||
public static void ConvertPngToShp(string[] args)
|
public static void ConvertPngToShp(string[] args)
|
||||||
{
|
{
|
||||||
var src = args[1];
|
var dest = args[1].Split('-').First() + ".shp";
|
||||||
var dest = Path.ChangeExtension(src, ".shp");
|
var frames = args.Skip(1).Select(a => PngLoader.Load(a));
|
||||||
var width = int.Parse(args[2]);
|
|
||||||
|
|
||||||
var srcImage = PngLoader.Load(src);
|
var size = frames.First().Size;
|
||||||
|
if (frames.Any(f => f.Size != size))
|
||||||
if (srcImage.Width % width != 0)
|
throw new InvalidOperationException("All frames must be the same size");
|
||||||
throw new InvalidOperationException("Bogus width; not a whole number of frames");
|
|
||||||
|
|
||||||
using (var destStream = File.Create(dest))
|
using (var destStream = File.Create(dest))
|
||||||
ShpWriter.Write(destStream, width, srcImage.Height,
|
ShpReader.Write(destStream, size, frames.Select(f => f.ToBytes()));
|
||||||
srcImage.ToFrames(width));
|
|
||||||
|
|
||||||
Console.WriteLine(dest + " saved.");
|
Console.WriteLine(dest + " saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<byte[]> ToFrames(this Bitmap bitmap, int width)
|
static byte[] ToBytes(this Bitmap bitmap)
|
||||||
{
|
{
|
||||||
for (var x = 0; x < bitmap.Width; x += width)
|
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
|
||||||
{
|
PixelFormat.Format8bppIndexed);
|
||||||
var data = bitmap.LockBits(new Rectangle(x, 0, width, bitmap.Height), ImageLockMode.ReadOnly,
|
|
||||||
PixelFormat.Format8bppIndexed);
|
|
||||||
|
|
||||||
var bytes = new byte[width * bitmap.Height];
|
var bytes = new byte[bitmap.Width * bitmap.Height];
|
||||||
for (var i = 0; i < bitmap.Height; i++)
|
for (var i = 0; i < bitmap.Height; i++)
|
||||||
Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + i * data.Stride),
|
Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + i * data.Stride),
|
||||||
bytes, i * width, width);
|
bytes, i * bitmap.Width, bitmap.Width);
|
||||||
|
|
||||||
bitmap.UnlockBits(data);
|
bitmap.UnlockBits(data);
|
||||||
|
|
||||||
yield return bytes;
|
return bytes;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConvertShpToPng(string[] args)
|
public static void ConvertShpToPng(string[] args)
|
||||||
{
|
{
|
||||||
var src = args[1];
|
var src = args[1];
|
||||||
var dest = Path.ChangeExtension(src, ".png");
|
|
||||||
|
|
||||||
var srcImage = ShpReader.Load(src);
|
|
||||||
var shadowIndex = new int[] { };
|
var shadowIndex = new int[] { };
|
||||||
if (args.Contains("--noshadow"))
|
if (args.Contains("--noshadow"))
|
||||||
{
|
{
|
||||||
@@ -93,134 +85,55 @@ namespace OpenRA.Utility
|
|||||||
|
|
||||||
var palette = Palette.Load(args[2], shadowIndex);
|
var palette = Palette.Load(args[2], shadowIndex);
|
||||||
|
|
||||||
using (var bitmap = new Bitmap(srcImage.ImageCount * srcImage.Width, srcImage.Height, PixelFormat.Format8bppIndexed))
|
ISpriteSource source;
|
||||||
|
using (var stream = File.OpenRead(src))
|
||||||
|
source = SpriteSource.LoadSpriteSource(stream, src);
|
||||||
|
|
||||||
|
// The r8 padding requires external information that we can't access here.
|
||||||
|
var usePadding = !(args.Contains("--nopadding") || source is R8Reader);
|
||||||
|
var count = 0;
|
||||||
|
var prefix = Path.GetFileNameWithoutExtension(src);
|
||||||
|
|
||||||
|
foreach (var frame in source.Frames)
|
||||||
{
|
{
|
||||||
var x = 0;
|
var frameSize = usePadding ? frame.FrameSize : frame.Size;
|
||||||
bitmap.Palette = palette.AsSystemPalette();
|
var offset = usePadding ? (frame.Offset - 0.5f * new float2(frame.Size - frame.FrameSize)).ToInt2() : int2.Zero;
|
||||||
|
|
||||||
foreach (var frame in srcImage.Frames)
|
// shp(ts) may define empty frames
|
||||||
|
if (frameSize.Width == 0 && frameSize.Height == 0)
|
||||||
{
|
{
|
||||||
var data = bitmap.LockBits(new Rectangle(x, 0, srcImage.Width, srcImage.Height), ImageLockMode.WriteOnly,
|
count++;
|
||||||
PixelFormat.Format8bppIndexed);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < bitmap.Height; i++)
|
using (var bitmap = new Bitmap(frameSize.Width, frameSize.Height, PixelFormat.Format8bppIndexed))
|
||||||
Marshal.Copy(frame.Image, i * srcImage.Width,
|
{
|
||||||
new IntPtr(data.Scan0.ToInt64() + i * data.Stride), srcImage.Width);
|
bitmap.Palette = palette.AsSystemPalette();
|
||||||
|
var data = bitmap.LockBits(new Rectangle(0, 0, frameSize.Width, frameSize.Height),
|
||||||
|
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
||||||
|
|
||||||
x += srcImage.Width;
|
// Clear the frame
|
||||||
|
if (usePadding)
|
||||||
|
{
|
||||||
|
var clearRow = new byte[data.Stride];
|
||||||
|
for (var i = 0; i < frameSize.Height; i++)
|
||||||
|
Marshal.Copy(clearRow, 0, new IntPtr(data.Scan0.ToInt64() + i * data.Stride), data.Stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < frame.Size.Height; i++)
|
||||||
|
{
|
||||||
|
var destIndex = new IntPtr(data.Scan0.ToInt64() + (i + offset.Y) * data.Stride + offset.X);
|
||||||
|
Marshal.Copy(frame.Data, i * frame.Size.Width, destIndex, frame.Size.Width);
|
||||||
|
}
|
||||||
|
|
||||||
bitmap.UnlockBits(data);
|
bitmap.UnlockBits(data);
|
||||||
|
|
||||||
|
var filename = "{0}-{1:D4}.png".F(prefix, count++);
|
||||||
|
bitmap.Save(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap.Save(dest);
|
|
||||||
Console.WriteLine(dest + " saved");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConvertR8ToPng(string[] args)
|
|
||||||
{
|
|
||||||
var srcImage = new R8Reader(File.OpenRead(args[1]));
|
|
||||||
var shadowIndex = new int[] { };
|
|
||||||
if (args.Contains("--noshadow"))
|
|
||||||
{
|
|
||||||
Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
|
|
||||||
shadowIndex[shadowIndex.Length - 1] = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var palette = Palette.Load(args[2], shadowIndex);
|
Console.WriteLine("Saved {0}-[0..{1}].png", prefix, count - 1);
|
||||||
var startFrame = int.Parse(args[3]);
|
|
||||||
var endFrame = int.Parse(args[4]) + 1;
|
|
||||||
var filename = args[5];
|
|
||||||
var frameCount = endFrame - startFrame;
|
|
||||||
|
|
||||||
var frame = srcImage[startFrame];
|
|
||||||
var bitmap = new Bitmap(frame.FrameSize.Width * frameCount, frame.FrameSize.Height, PixelFormat.Format8bppIndexed);
|
|
||||||
bitmap.Palette = palette.AsSystemPalette();
|
|
||||||
|
|
||||||
frame = srcImage[startFrame];
|
|
||||||
|
|
||||||
if (args.Contains("--tileset"))
|
|
||||||
{
|
|
||||||
int f = 0;
|
|
||||||
var tileset = new Bitmap(frame.FrameSize.Width * 20, frame.FrameSize.Height * 40, PixelFormat.Format8bppIndexed);
|
|
||||||
tileset.Palette = palette.AsSystemPalette();
|
|
||||||
|
|
||||||
for (int h = 0; h < 40; h++)
|
|
||||||
{
|
|
||||||
for (int w = 0; w < 20; w++)
|
|
||||||
{
|
|
||||||
if (h * 20 + w < frameCount)
|
|
||||||
{
|
|
||||||
Console.WriteLine(f);
|
|
||||||
frame = srcImage[f];
|
|
||||||
|
|
||||||
var data = tileset.LockBits(new Rectangle(w * frame.Size.Width, h * frame.Size.Height, frame.Size.Width, frame.Size.Height),
|
|
||||||
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
|
|
||||||
|
|
||||||
for (var i = 0; i < frame.Size.Height; i++)
|
|
||||||
Marshal.Copy(frame.Image, i * frame.Size.Width,
|
|
||||||
new IntPtr(data.Scan0.ToInt64() + i * data.Stride), frame.Size.Width);
|
|
||||||
|
|
||||||
tileset.UnlockBits(data);
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap = tileset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap.Save(filename + ".png");
|
|
||||||
Console.WriteLine(filename + ".png saved");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConvertTmpToPng(string[] args)
|
|
||||||
{
|
|
||||||
var mod = args[1];
|
|
||||||
var theater = args[2];
|
|
||||||
var templateNames = args.Skip(3);
|
|
||||||
var shadowIndex = new int[] { 3, 4 };
|
|
||||||
|
|
||||||
var manifest = new Manifest(mod);
|
|
||||||
FileSystem.LoadFromManifest(manifest);
|
|
||||||
|
|
||||||
var tileset = manifest.TileSets.Select(a => new TileSet(a))
|
|
||||||
.FirstOrDefault(ts => ts.Name == theater);
|
|
||||||
|
|
||||||
if (tileset == null)
|
|
||||||
throw new InvalidOperationException("No theater named '{0}'".F(theater));
|
|
||||||
|
|
||||||
var renderer = new TileSetRenderer(tileset, new Size(manifest.TileSize, manifest.TileSize));
|
|
||||||
var palette = new Palette(FileSystem.Open(tileset.Palette), shadowIndex);
|
|
||||||
|
|
||||||
foreach (var templateName in templateNames)
|
|
||||||
{
|
|
||||||
var template = tileset.Templates.FirstOrDefault(tt => tt.Value.Image == templateName);
|
|
||||||
if (template.Value == null)
|
|
||||||
throw new InvalidOperationException("No such template '{0}'".F(templateName));
|
|
||||||
|
|
||||||
using (var image = renderer.RenderTemplate(template.Value.Id, palette))
|
|
||||||
image.Save(Path.ChangeExtension(templateName, ".png"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConvertFormat2ToFormat80(string[] args)
|
|
||||||
{
|
|
||||||
var src = args[1];
|
|
||||||
var dest = args[2];
|
|
||||||
|
|
||||||
Dune2ShpReader srcImage = null;
|
|
||||||
using (var s = File.OpenRead(src))
|
|
||||||
srcImage = new Dune2ShpReader(s);
|
|
||||||
|
|
||||||
var size = srcImage.First().Size;
|
|
||||||
|
|
||||||
if (!srcImage.All(im => im.Size == size))
|
|
||||||
throw new InvalidOperationException("All the frames must be the same size to convert from Dune2 to RA");
|
|
||||||
|
|
||||||
using (var destStream = File.Create(dest))
|
|
||||||
ShpWriter.Write(destStream, size.Width, size.Height,
|
|
||||||
srcImage.Select(im => im.Image));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ExtractFiles(string[] args)
|
public static void ExtractFiles(string[] args)
|
||||||
@@ -233,16 +146,12 @@ namespace OpenRA.Utility
|
|||||||
|
|
||||||
foreach (var f in files)
|
foreach (var f in files)
|
||||||
{
|
{
|
||||||
if (f == "--userdir")
|
|
||||||
break;
|
|
||||||
|
|
||||||
var src = FileSystem.Open(f);
|
var src = FileSystem.Open(f);
|
||||||
if (src == null)
|
if (src == null)
|
||||||
throw new InvalidOperationException("File not found: {0}".F(f));
|
throw new InvalidOperationException("File not found: {0}".F(f));
|
||||||
var data = src.ReadAllBytes();
|
var data = src.ReadAllBytes();
|
||||||
var output = args.Contains("--userdir") ? Platform.SupportDir + f : f;
|
File.WriteAllBytes(f, data);
|
||||||
File.WriteAllBytes(output, data);
|
Console.WriteLine(f + " saved.");
|
||||||
Console.WriteLine(output + " saved.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,8 +209,8 @@ namespace OpenRA.Utility
|
|||||||
var srcImage = ShpReader.Load(args[3]);
|
var srcImage = ShpReader.Load(args[3]);
|
||||||
|
|
||||||
using (var destStream = File.Create(args[4]))
|
using (var destStream = File.Create(args[4]))
|
||||||
ShpWriter.Write(destStream, srcImage.Width, srcImage.Height,
|
ShpReader.Write(destStream, srcImage.Size,
|
||||||
srcImage.Frames.Select(im => im.Image.Select(px => (byte)remap[px]).ToArray()));
|
srcImage.Frames.Select(im => im.Data.Select(px => (byte)remap[px]).ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TransposeShp(string[] args)
|
public static void TransposeShp(string[] args)
|
||||||
@@ -323,8 +232,7 @@ namespace OpenRA.Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
using (var destStream = File.Create(args[2]))
|
using (var destStream = File.Create(args[2]))
|
||||||
ShpWriter.Write(destStream, srcImage.Width, srcImage.Height,
|
ShpReader.Write(destStream, srcImage.Size, destFrames.Select(f => f.Data));
|
||||||
destFrames.Select(f => f.Image));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static string FriendlyTypeName(Type t)
|
static string FriendlyTypeName(Type t)
|
||||||
|
|||||||
@@ -23,11 +23,8 @@ namespace OpenRA.Utility
|
|||||||
{ "--settings-value", Command.Settings },
|
{ "--settings-value", Command.Settings },
|
||||||
{ "--shp", Command.ConvertPngToShp },
|
{ "--shp", Command.ConvertPngToShp },
|
||||||
{ "--png", Command.ConvertShpToPng },
|
{ "--png", Command.ConvertShpToPng },
|
||||||
{ "--fromd2", Command.ConvertFormat2ToFormat80 },
|
|
||||||
{ "--extract", Command.ExtractFiles },
|
{ "--extract", Command.ExtractFiles },
|
||||||
{ "--tmp-png", Command.ConvertTmpToPng },
|
|
||||||
{ "--remap", Command.RemapShp },
|
{ "--remap", Command.RemapShp },
|
||||||
{ "--r8", Command.ConvertR8ToPng },
|
|
||||||
{ "--transpose", Command.TransposeShp },
|
{ "--transpose", Command.TransposeShp },
|
||||||
{ "--docs", Command.ExtractTraitDocs },
|
{ "--docs", Command.ExtractTraitDocs },
|
||||||
{ "--map-hash", Command.GetMapHash },
|
{ "--map-hash", Command.GetMapHash },
|
||||||
@@ -58,13 +55,10 @@ namespace OpenRA.Utility
|
|||||||
Console.WriteLine("Usage: OpenRA.Utility.exe [OPTION] [ARGS]");
|
Console.WriteLine("Usage: OpenRA.Utility.exe [OPTION] [ARGS]");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine(" --settings-value KEY Get value of KEY from settings.yaml");
|
Console.WriteLine(" --settings-value KEY Get value of KEY from settings.yaml");
|
||||||
Console.WriteLine(" --shp PNGFILE FRAMEWIDTH Convert a single PNG with multiple frames appended after another to a SHP");
|
Console.WriteLine(" --shp PNGFILE [PNGFILE ...] Combine a list of PNG images into a SHP");
|
||||||
Console.WriteLine(" --png SHPFILE PALETTE [--noshadow] Convert a SHP to a PNG containing all of its frames, optionally removing the shadow");
|
Console.WriteLine(" --png SPRITEFILE PALETTE [--noshadow] [--nopadding] Convert a shp/tmp/R8 to a series of PNGs, optionally removing shadow");
|
||||||
Console.WriteLine(" --fromd2 DUNE2SHP C&CSHP Convert a Dune II SHP (C&C mouse cursor) to C&C SHP format.");
|
Console.WriteLine(" --extract MOD[,MOD]* FILES Extract files from mod packages to the current directory");
|
||||||
Console.WriteLine(" --extract MOD[,MOD]* FILES [--userdir] Extract files from mod packages to the current (or user) directory");
|
|
||||||
Console.WriteLine(" --tmp-png MOD[,MOD]* THEATER FILES Extract terrain tiles to PNG");
|
|
||||||
Console.WriteLine(" --remap SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP Remap SHPs to another palette");
|
Console.WriteLine(" --remap SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP Remap SHPs to another palette");
|
||||||
Console.WriteLine(" --r8 R8FILE PALETTE START END FILENAME [--noshadow] [--tileset] Convert Dune 2000 DATA.R8 to PNGs choosing start- and endframe as well as type to append multiple frames to one PNG named by filename optionally removing the shadow.");
|
|
||||||
Console.WriteLine(" --transpose SRCSHP DESTSHP START N M [START N M ...] Transpose the N*M block of frames starting at START.");
|
Console.WriteLine(" --transpose SRCSHP DESTSHP START N M [START N M ...] Transpose the N*M block of frames starting at START.");
|
||||||
Console.WriteLine(" --docs MOD Generate trait documentation in MarkDown format.");
|
Console.WriteLine(" --docs MOD Generate trait documentation in MarkDown format.");
|
||||||
Console.WriteLine(" --map-hash MAPFILE Generate hash of specified oramap file.");
|
Console.WriteLine(" --map-hash MAPFILE Generate hash of specified oramap file.");
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
|
|||||||
Width:144
|
Width:144
|
||||||
Height:72
|
Height:72
|
||||||
ShpImage@FACT:
|
ShpImage@FACT:
|
||||||
X:160
|
X:153
|
||||||
Y:13
|
Y:1
|
||||||
|
Width:80
|
||||||
|
Height:73
|
||||||
Image:fact
|
Image:fact
|
||||||
Palette:colorpicker
|
Palette:colorpicker
|
||||||
Button@RANDOM_BUTTON:
|
Button@RANDOM_BUTTON:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
Cursors:
|
Cursors:
|
||||||
mouse2: cursor
|
mouse2.shp: cursor
|
||||||
scroll-t:
|
scroll-t:
|
||||||
start:1
|
start:1
|
||||||
scroll-tr:
|
scroll-tr:
|
||||||
@@ -114,7 +114,7 @@ Cursors:
|
|||||||
start:154
|
start:154
|
||||||
length:24
|
length:24
|
||||||
|
|
||||||
mouse4:cursor
|
mouse4.shp:cursor
|
||||||
move:
|
move:
|
||||||
start:0
|
start:0
|
||||||
length:8
|
length:8
|
||||||
@@ -125,7 +125,7 @@ Cursors:
|
|||||||
start:0
|
start:0
|
||||||
length: 8
|
length: 8
|
||||||
|
|
||||||
attackmove:cursor
|
attackmove.shp:cursor
|
||||||
attackmove:
|
attackmove:
|
||||||
start:0
|
start:0
|
||||||
length:8
|
length:8
|
||||||
@@ -138,7 +138,7 @@ Cursors:
|
|||||||
start:13
|
start:13
|
||||||
length:1
|
length:1
|
||||||
|
|
||||||
mouse3: cursor2
|
mouse3.shp: cursor2
|
||||||
enter-blocked:
|
enter-blocked:
|
||||||
start:212
|
start:212
|
||||||
length:1
|
length:1
|
||||||
@@ -170,7 +170,7 @@ Cursors:
|
|||||||
start:213
|
start:213
|
||||||
length:1
|
length:1
|
||||||
|
|
||||||
nopower: cursor
|
nopower.shp: cursor
|
||||||
powerdown-blocked:
|
powerdown-blocked:
|
||||||
start:0
|
start:0
|
||||||
length: 1
|
length: 1
|
||||||
|
|||||||
@@ -1,215 +0,0 @@
|
|||||||
Background@ASSETBROWSER_BG:
|
|
||||||
Logic:AssetBrowserLogic
|
|
||||||
X:(WINDOW_RIGHT - WIDTH)/2
|
|
||||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
|
||||||
Width:700
|
|
||||||
Height:410
|
|
||||||
Children:
|
|
||||||
ColorPreviewManager@COLOR_MANAGER:
|
|
||||||
Label@ASSETBROWSER_TITLE:
|
|
||||||
X:0
|
|
||||||
Y:10
|
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Height:25
|
|
||||||
Text:Game Asset Viewer & Converter
|
|
||||||
Align:Center
|
|
||||||
Font:Bold
|
|
||||||
DropDownButton@SOURCE_SELECTOR:
|
|
||||||
X:40
|
|
||||||
Y:45
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Font:Bold
|
|
||||||
Text:Folders
|
|
||||||
ScrollPanel@ASSET_LIST:
|
|
||||||
X:40
|
|
||||||
Y:80
|
|
||||||
Width:160
|
|
||||||
Height:190
|
|
||||||
Children:
|
|
||||||
ScrollItem@ASSET_TEMPLATE:
|
|
||||||
Width:PARENT_RIGHT-27
|
|
||||||
Height:25
|
|
||||||
X:2
|
|
||||||
Y:0
|
|
||||||
Visible:false
|
|
||||||
Children:
|
|
||||||
Label@TITLE:
|
|
||||||
X:10
|
|
||||||
Width:PARENT_RIGHT-20
|
|
||||||
Height:25
|
|
||||||
TextField@FILENAME_INPUT:
|
|
||||||
X:40
|
|
||||||
Y:280
|
|
||||||
Width:140
|
|
||||||
Height:25
|
|
||||||
Text:mouse.r8
|
|
||||||
Button@LOAD_BUTTON:
|
|
||||||
X:40
|
|
||||||
Y:310
|
|
||||||
Width:140
|
|
||||||
Height:25
|
|
||||||
Text:Load
|
|
||||||
Font:Bold
|
|
||||||
Key:return
|
|
||||||
DropDownButton@PALETTE_SELECTOR:
|
|
||||||
X:230
|
|
||||||
Y:45
|
|
||||||
Width:150
|
|
||||||
Height:25
|
|
||||||
Font:Bold
|
|
||||||
Text:Palette
|
|
||||||
DropDownButton@COLOR:
|
|
||||||
X:380
|
|
||||||
Y:45
|
|
||||||
Width:80
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
ColorBlock@COLORBLOCK:
|
|
||||||
X:5
|
|
||||||
Y:6
|
|
||||||
Width:PARENT_RIGHT-35
|
|
||||||
Height:PARENT_BOTTOM-12
|
|
||||||
Background@SPRITE_BG:
|
|
||||||
X:220
|
|
||||||
Y:80
|
|
||||||
Width:250
|
|
||||||
Height:250
|
|
||||||
Background:dialog4
|
|
||||||
Children:
|
|
||||||
ShpImage@SPRITE:
|
|
||||||
X:4
|
|
||||||
Y:4
|
|
||||||
Width:246
|
|
||||||
Height:246
|
|
||||||
Image:mouse.r8
|
|
||||||
Label@ACTIONS_TITLE:
|
|
||||||
X:PARENT_RIGHT - 150
|
|
||||||
Y:45
|
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Height:25
|
|
||||||
Text:Actions
|
|
||||||
Font:Bold
|
|
||||||
Button@EXPORT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:80
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Selected to PNG
|
|
||||||
Font:Bold
|
|
||||||
Button@EXTRACT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:115
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Extract all to PNG
|
|
||||||
Font:Bold
|
|
||||||
TextField@IMAGE_FILENAME_INPUT:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 235
|
|
||||||
Width:100
|
|
||||||
Height:25
|
|
||||||
Text:pixelart.png
|
|
||||||
TextField@IMAGE_SIZE_INPUT:
|
|
||||||
X:PARENT_RIGHT - 90
|
|
||||||
Y:PARENT_BOTTOM - 235
|
|
||||||
Width:50
|
|
||||||
Height:25
|
|
||||||
Text:width
|
|
||||||
Button@IMPORT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 200
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Import from PNG
|
|
||||||
Font:Bold
|
|
||||||
Button@CLOSE_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 115
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Close
|
|
||||||
Font:Bold
|
|
||||||
Key:escape
|
|
||||||
Container@FRAME_SELECTOR:
|
|
||||||
X:45
|
|
||||||
Y:360
|
|
||||||
Children:
|
|
||||||
Button@BUTTON_PREV:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_PREV:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
ImageCollection:music
|
|
||||||
ImageName:prev
|
|
||||||
Button@BUTTON_PLAY:
|
|
||||||
X:35
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_PLAY:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
ImageCollection:music
|
|
||||||
ImageName:play
|
|
||||||
Button@BUTTON_PAUSE:
|
|
||||||
Visible: no
|
|
||||||
X:35
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_PAUSE:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
ImageCollection:music
|
|
||||||
ImageName:pause
|
|
||||||
Button@BUTTON_STOP:
|
|
||||||
X:70
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_STOP:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
ImageCollection:music
|
|
||||||
ImageName:stop
|
|
||||||
Button@BUTTON_NEXT:
|
|
||||||
X:105
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_NEXT:
|
|
||||||
X:0
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
ImageCollection:music
|
|
||||||
ImageName:next
|
|
||||||
Slider@FRAME_SLIDER:
|
|
||||||
X:160
|
|
||||||
Y:0
|
|
||||||
Width:410
|
|
||||||
Height:20
|
|
||||||
MinimumValue: 0
|
|
||||||
Label@FRAME_COUNT:
|
|
||||||
X:585
|
|
||||||
Y:0
|
|
||||||
Width:25
|
|
||||||
Height:25
|
|
||||||
Font:Bold
|
|
||||||
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
|
|||||||
Width:144
|
Width:144
|
||||||
Height:72
|
Height:72
|
||||||
ShpImage@FACT:
|
ShpImage@FACT:
|
||||||
X:160
|
X:153
|
||||||
Y:8
|
Y:1
|
||||||
|
Width:80
|
||||||
|
Height:73
|
||||||
Image:DATA.R8
|
Image:DATA.R8
|
||||||
Frame:1936
|
Frame:1936
|
||||||
Palette:colorpicker
|
Palette:colorpicker
|
||||||
|
|||||||
@@ -150,6 +150,8 @@ Container@PLAYER_WIDGETS:
|
|||||||
SupportPowerBin@INGAME_POWERS_BIN:
|
SupportPowerBin@INGAME_POWERS_BIN:
|
||||||
X:0
|
X:0
|
||||||
Y:25
|
Y:25
|
||||||
|
IconWidth: 60
|
||||||
|
IconHeight: 48
|
||||||
ReadyText: READY
|
ReadyText: READY
|
||||||
HoldText: ON HOLD
|
HoldText: ON HOLD
|
||||||
BuildPalette@INGAME_BUILD_PALETTE:
|
BuildPalette@INGAME_BUILD_PALETTE:
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ ShadowIndex: 1
|
|||||||
|
|
||||||
Palettes:
|
Palettes:
|
||||||
cursor: cursor.pal
|
cursor: cursor.pal
|
||||||
mouse.r8: d2k.pal
|
mouse: d2k.pal
|
||||||
|
|
||||||
Cursors:
|
Cursors:
|
||||||
mouse.r8: mouse.r8
|
mouse.r8: mouse
|
||||||
scroll-t:
|
scroll-t:
|
||||||
start:112
|
start:112
|
||||||
x: 24
|
x: 24
|
||||||
@@ -252,7 +252,7 @@ Cursors:
|
|||||||
x: 24
|
x: 24
|
||||||
y: 24
|
y: 24
|
||||||
|
|
||||||
nopower: cursor
|
nopower.shp: cursor
|
||||||
powerdown-blocked:
|
powerdown-blocked:
|
||||||
start:0
|
start:0
|
||||||
length: 1
|
length: 1
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ ChromeLayout:
|
|||||||
mods/ra/chrome/cheats.yaml
|
mods/ra/chrome/cheats.yaml
|
||||||
mods/ra/chrome/musicplayer.yaml
|
mods/ra/chrome/musicplayer.yaml
|
||||||
mods/d2k/chrome/tooltips.yaml
|
mods/d2k/chrome/tooltips.yaml
|
||||||
mods/d2k/chrome/assetbrowser.yaml
|
mods/ra/chrome/assetbrowser.yaml
|
||||||
mods/ra/chrome/convertassets.yaml
|
|
||||||
mods/ra/chrome/irc.yaml
|
mods/ra/chrome/irc.yaml
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
carryall:
|
carryall:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1923
|
Start: 1923
|
||||||
Facings: -32
|
Facings: -32
|
||||||
unload: DATA.R8
|
unload: DATA
|
||||||
Start: 1923
|
Start: 1923
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4029
|
Start: 4029
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
|
|
||||||
orni:
|
orni:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1955
|
Start: 1955
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 3
|
Length: 3
|
||||||
Tick: 120
|
Tick: 120
|
||||||
Transpose: true
|
Transpose: true
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4031
|
Start: 4031
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
frigate:
|
frigate:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2517
|
Start: 2517
|
||||||
Facings: 1
|
Facings: 1
|
||||||
@@ -1,441 +1,441 @@
|
|||||||
rifle:
|
rifle:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 206
|
Start: 206
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 206
|
Start: 206
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand3: DATA.R8
|
stand3: DATA
|
||||||
Start: 206
|
Start: 206
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 214
|
Start: 214
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Tick: 110
|
Tick: 110
|
||||||
Transpose: true
|
Transpose: true
|
||||||
shoot: DATA.R8
|
shoot: DATA
|
||||||
Start: 254
|
Start: 254
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-stand: DATA.R8
|
prone-stand: DATA
|
||||||
Start: 302
|
Start: 302
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-run: DATA.R8
|
prone-run: DATA
|
||||||
Start: 310
|
Start: 310
|
||||||
Length: 3
|
Length: 3
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 110
|
Tick: 110
|
||||||
standup-0: DATA.R8
|
standup-0: DATA
|
||||||
Start: 302
|
Start: 302
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
prone-shoot: DATA.R8
|
prone-shoot: DATA
|
||||||
Start: 334
|
Start: 334
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 382
|
Start: 382
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 387
|
Start: 387
|
||||||
Length: 7
|
Length: 7
|
||||||
Tick: 80
|
Tick: 80
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 394
|
Start: 394
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 401
|
Start: 401
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 408
|
Start: 408
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 415
|
Start: 415
|
||||||
Length: 12
|
Length: 12
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 430
|
Start: 430
|
||||||
Length: 12
|
Length: 12
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4011
|
Start: 4011
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
bazooka:
|
bazooka:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 458
|
Start: 458
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 458
|
Start: 458
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand3: DATA.R8
|
stand3: DATA
|
||||||
Start: 458
|
Start: 458
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 466
|
Start: 466
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Tick: 120
|
Tick: 120
|
||||||
Transpose: true
|
Transpose: true
|
||||||
shoot: DATA.R8
|
shoot: DATA
|
||||||
Start: 506
|
Start: 506
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-stand: DATA.R8
|
prone-stand: DATA
|
||||||
Start: 562
|
Start: 562
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-run: DATA.R8
|
prone-run: DATA
|
||||||
Start: 570
|
Start: 570
|
||||||
Length: 3
|
Length: 3
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
standup-0: DATA.R8
|
standup-0: DATA
|
||||||
Start: 554
|
Start: 554
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-shoot: DATA.R8
|
prone-shoot: DATA
|
||||||
Start: 586
|
Start: 586
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 634
|
Start: 634
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 639
|
Start: 639
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 646
|
Start: 646
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 653
|
Start: 653
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 660
|
Start: 660
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 660
|
Start: 660
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 668
|
Start: 668
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4012
|
Start: 4012
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
engineer:
|
engineer:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 1166
|
Start: 1166
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 1166
|
Start: 1166
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 1174
|
Start: 1174
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 1342
|
Start: 1342
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 1347
|
Start: 1347
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 1354
|
Start: 1354
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 1361
|
Start: 1361
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 1368
|
Start: 1368
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 1368
|
Start: 1368
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 1376
|
Start: 1376
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4013
|
Start: 4013
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
medic: # actually thumper
|
medic: # actually thumper
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 1402
|
Start: 1402
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 1402
|
Start: 1402
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 1410
|
Start: 1410
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
heal: DATA.R8
|
heal: DATA
|
||||||
Start: 1458
|
Start: 1458
|
||||||
Length: 5
|
Length: 5
|
||||||
Tick: 480
|
Tick: 480
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 1543
|
Start: 1543
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 1548
|
Start: 1548
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 1555
|
Start: 1555
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 1562
|
Start: 1562
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 1569
|
Start: 1569
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 1569
|
Start: 1569
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 1577
|
Start: 1577
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4014
|
Start: 4014
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
thumping:
|
thumping:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1458
|
Start: 1458
|
||||||
Length: 5
|
Length: 5
|
||||||
Tick: 150
|
Tick: 150
|
||||||
make: DATA.R8
|
make: DATA
|
||||||
Start: 1458
|
Start: 1458
|
||||||
Length: 5
|
Length: 5
|
||||||
damaged-idle: DATA.R8
|
damaged-idle: DATA
|
||||||
Start: 1458
|
Start: 1458
|
||||||
Length: 5
|
Length: 5
|
||||||
Tick: 150
|
Tick: 150
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Frames: 4014
|
Frames: 4014
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
fremen:
|
fremen:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 694
|
Start: 694
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 694
|
Start: 694
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 702
|
Start: 702
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
shoot: DATA.R8
|
shoot: DATA
|
||||||
Start: 742
|
Start: 742
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-stand: DATA.R8
|
prone-stand: DATA
|
||||||
Start: 798
|
Start: 798
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-run: DATA.R8
|
prone-run: DATA
|
||||||
Start: 806
|
Start: 806
|
||||||
Length: 3
|
Length: 3
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
standup-0: DATA.R8
|
standup-0: DATA
|
||||||
Start: 790
|
Start: 790
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
prone-shoot: DATA.R8
|
prone-shoot: DATA
|
||||||
Start: 822
|
Start: 822
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 870
|
Start: 870
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 875
|
Start: 875
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 882
|
Start: 882
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 889
|
Start: 889
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 896
|
Start: 896
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 896
|
Start: 896
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 904
|
Start: 904
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4032
|
Start: 4032
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
saboteur:
|
saboteur:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 2149
|
Start: 2149
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 2149
|
Start: 2149
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand3: DATA.R8
|
stand3: DATA
|
||||||
Start: 2149
|
Start: 2149
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 2157
|
Start: 2157
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
prone-stand: DATA.R8
|
prone-stand: DATA
|
||||||
Start: 2253
|
Start: 2253
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-run: DATA.R8
|
prone-run: DATA
|
||||||
Start: 2261
|
Start: 2261
|
||||||
Length: 3
|
Length: 3
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
standup-0: DATA.R8
|
standup-0: DATA
|
||||||
Start: 2245
|
Start: 2245
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 2325
|
Start: 2325
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 2330
|
Start: 2330
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 2337
|
Start: 2337
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 2344
|
Start: 2344
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 2351
|
Start: 2351
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 2351
|
Start: 2351
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 2359
|
Start: 2359
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4034
|
Start: 4034
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
sardaukar:
|
sardaukar:
|
||||||
stand: DATA.R8
|
stand: DATA
|
||||||
Start: 930
|
Start: 930
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
stand2: DATA.R8
|
stand2: DATA
|
||||||
Start: 930
|
Start: 930
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
run: DATA.R8
|
run: DATA
|
||||||
Start: 938
|
Start: 938
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
shoot: DATA.R8
|
shoot: DATA
|
||||||
Start: 978
|
Start: 978
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-stand: DATA.R8
|
prone-stand: DATA
|
||||||
Start: 1034
|
Start: 1034
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
prone-run: DATA.R8
|
prone-run: DATA
|
||||||
Start: 1042
|
Start: 1042
|
||||||
Length: 3
|
Length: 3
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
standup-0: DATA.R8
|
standup-0: DATA
|
||||||
Start: 1026
|
Start: 1026
|
||||||
Length: 1
|
Length: 1
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
Tick: 120
|
Tick: 120
|
||||||
prone-shoot: DATA.R8
|
prone-shoot: DATA
|
||||||
Start: 1058
|
Start: 1058
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: 8
|
Facings: 8
|
||||||
Transpose: true
|
Transpose: true
|
||||||
die1: DATA.R8
|
die1: DATA
|
||||||
Start: 1106
|
Start: 1106
|
||||||
Length: 5
|
Length: 5
|
||||||
die2: DATA.R8
|
die2: DATA
|
||||||
Start: 1111
|
Start: 1111
|
||||||
Length: 7
|
Length: 7
|
||||||
die3: DATA.R8
|
die3: DATA
|
||||||
Start: 1118
|
Start: 1118
|
||||||
Length: 7
|
Length: 7
|
||||||
die4: DATA.R8
|
die4: DATA
|
||||||
Start: 1125
|
Start: 1125
|
||||||
Length: 7
|
Length: 7
|
||||||
die5: DATA.R8
|
die5: DATA
|
||||||
Start: 1132
|
Start: 1132
|
||||||
Length: 7
|
Length: 7
|
||||||
die6: DATA.R8
|
die6: DATA
|
||||||
Start: 1132
|
Start: 1132
|
||||||
Length: 7
|
Length: 7
|
||||||
die-crushed: DATA.R8
|
die-crushed: DATA
|
||||||
Start: 1140
|
Start: 1140
|
||||||
Length: 26
|
Length: 26
|
||||||
Tick: 1600
|
Tick: 1600
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4015
|
Start: 4015
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|||||||
@@ -1,87 +1,87 @@
|
|||||||
explosion:
|
explosion:
|
||||||
piff: DATA.R8
|
piff: DATA
|
||||||
Start: 3626
|
Start: 3626
|
||||||
Length: 5
|
Length: 5
|
||||||
piffs: DATA.R8
|
piffs: DATA
|
||||||
Start: 3429
|
Start: 3429
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
small_explosion: DATA.R8
|
small_explosion: DATA
|
||||||
Start: 3403
|
Start: 3403
|
||||||
Length: 15
|
Length: 15
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
med_explosion: DATA.R8
|
med_explosion: DATA
|
||||||
Start: 3390
|
Start: 3390
|
||||||
Length: 12
|
Length: 12
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
tiny_explosion: DATA.R8
|
tiny_explosion: DATA
|
||||||
Start: 3386
|
Start: 3386
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
nuke: DATA.R8
|
nuke: DATA
|
||||||
Start: 3965
|
Start: 3965
|
||||||
Length: 14
|
Length: 14
|
||||||
Tick: 60
|
Tick: 60
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
mini_explosion: DATA.R8
|
mini_explosion: DATA
|
||||||
Start: 3403
|
Start: 3403
|
||||||
Length: 15
|
Length: 15
|
||||||
Tick: 60
|
Tick: 60
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
self_destruct: DATA.R8
|
self_destruct: DATA
|
||||||
Start: 3433
|
Start: 3433
|
||||||
Length: 15
|
Length: 15
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
building: DATA.R8
|
building: DATA
|
||||||
Start: 3448
|
Start: 3448
|
||||||
Length: 22
|
Length: 22
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
large_explosion: DATA.R8
|
large_explosion: DATA
|
||||||
Start: 3988
|
Start: 3988
|
||||||
Length: 22
|
Length: 22
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
artillery: DATA.R8
|
artillery: DATA
|
||||||
Start: 3988
|
Start: 3988
|
||||||
Length: 22
|
Length: 22
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
small_artillery: DATA.R8
|
small_artillery: DATA
|
||||||
Start: 3390
|
Start: 3390
|
||||||
Length: 12
|
Length: 12
|
||||||
Tick: 60
|
Tick: 60
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
small_napalm: DATA.R8
|
small_napalm: DATA
|
||||||
Start: 3421
|
Start: 3421
|
||||||
Length: 8
|
Length: 8
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
shockwave: DATA.R8
|
shockwave: DATA
|
||||||
Start: 3687
|
Start: 3687
|
||||||
Length: 6
|
Length: 6
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
Tick: 120
|
Tick: 120
|
||||||
deviator: DATA.R8
|
deviator: DATA
|
||||||
Start: 3512
|
Start: 3512
|
||||||
Length: 23
|
Length: 23
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
Tick: 60
|
Tick: 60
|
||||||
|
|
||||||
laserfire:
|
laserfire:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3386
|
Start: 3386
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
pips:
|
pips:
|
||||||
groups: DATA.R8
|
groups: DATA
|
||||||
Start: 17
|
Start: 17
|
||||||
Length: 10
|
Length: 10
|
||||||
tag-primary: DATA.R8
|
tag-primary: DATA
|
||||||
Start: 110
|
Start: 110
|
||||||
pip-empty: DATA.R8
|
pip-empty: DATA
|
||||||
Start: 15
|
Start: 15
|
||||||
pip-green: DATA.R8
|
pip-green: DATA
|
||||||
Start: 16
|
Start: 16
|
||||||
|
|
||||||
clock:
|
clock:
|
||||||
@@ -105,19 +105,19 @@ rank:
|
|||||||
Length: *
|
Length: *
|
||||||
|
|
||||||
overlay:
|
overlay:
|
||||||
build-valid-arrakis: DATA.R8
|
build-valid-arrakis: DATA
|
||||||
Start: 0
|
Start: 0
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
build-invalid: DATA.R8
|
build-invalid: DATA
|
||||||
Start: 1
|
Start: 1
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
target-select: DATA.R8
|
target-select: DATA
|
||||||
Start: 2
|
Start: 2
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
target-valid-arrakis: DATA.R8
|
target-valid-arrakis: DATA
|
||||||
Start: 0
|
Start: 0
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
target-invalid: DATA.R8
|
target-invalid: DATA
|
||||||
Start: 1
|
Start: 1
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
|
|
||||||
@@ -131,29 +131,29 @@ rallypoint:
|
|||||||
Length: *
|
Length: *
|
||||||
|
|
||||||
rpg:
|
rpg:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3015
|
Start: 3015
|
||||||
Facings: -32
|
Facings: -32
|
||||||
|
|
||||||
120mm:
|
120mm:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3014
|
Start: 3014
|
||||||
Length: 1
|
Length: 1
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
155mm:
|
155mm:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3081
|
Start: 3081
|
||||||
Length: 1
|
Length: 1
|
||||||
|
|
||||||
crate-effects:
|
crate-effects:
|
||||||
dollar: DATA.R8
|
dollar: DATA
|
||||||
Start: 3679
|
Start: 3679
|
||||||
Length: 8
|
Length: 8
|
||||||
reveal-map: DATA.R8
|
reveal-map: DATA
|
||||||
Start: 3947
|
Start: 3947
|
||||||
Length: 18
|
Length: 18
|
||||||
hide-map: DATA.R8
|
hide-map: DATA
|
||||||
Start: 3911
|
Start: 3911
|
||||||
Length: 36
|
Length: 36
|
||||||
levelup: levelup
|
levelup: levelup
|
||||||
@@ -162,70 +162,70 @@ crate-effects:
|
|||||||
Tick: 200
|
Tick: 200
|
||||||
|
|
||||||
allyrepair:
|
allyrepair:
|
||||||
repair: DATA.R8
|
repair: DATA
|
||||||
Frames: 3, 39
|
Frames: 3, 39
|
||||||
Length: 2
|
Length: 2
|
||||||
Tick: 300
|
Tick: 300
|
||||||
|
|
||||||
missile:
|
missile:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3088
|
Start: 3088
|
||||||
Facings: -32
|
Facings: -32
|
||||||
|
|
||||||
missile2:
|
missile2:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3306
|
Start: 3306
|
||||||
Facings: -32
|
Facings: -32
|
||||||
|
|
||||||
atomic:
|
atomic:
|
||||||
up: DATA.R8
|
up: DATA
|
||||||
Start: 2147
|
Start: 2147
|
||||||
Length: 1
|
Length: 1
|
||||||
down: DATA.R8
|
down: DATA
|
||||||
Start: 2148
|
Start: 2148
|
||||||
Length: 1
|
Length: 1
|
||||||
|
|
||||||
fire:
|
fire:
|
||||||
1: DATA.R8
|
1: DATA
|
||||||
Start: 3712
|
Start: 3712
|
||||||
Length: 10
|
Length: 10
|
||||||
Offset: 0,-3
|
Offset: 0,-3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
2: DATA.R8
|
2: DATA
|
||||||
Start: 3723
|
Start: 3723
|
||||||
Length: 11
|
Length: 11
|
||||||
Offset: 0,-3
|
Offset: 0,-3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
3: DATA.R8
|
3: DATA
|
||||||
Start: 3885
|
Start: 3885
|
||||||
Length: 13
|
Length: 13
|
||||||
Offset: 0,-3
|
Offset: 0,-3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
4: DATA.R8
|
4: DATA
|
||||||
Start: 3712
|
Start: 3712
|
||||||
Length: 10
|
Length: 10
|
||||||
Offset: 0,-3
|
Offset: 0,-3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
smoke_m:
|
smoke_m:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3418
|
Start: 3418
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
loop: DATA.R8
|
loop: DATA
|
||||||
Start: 3418
|
Start: 3418
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
end: DATA.R8
|
end: DATA
|
||||||
Start: 3418
|
Start: 3418
|
||||||
Length: 3
|
Length: 3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
bombs:
|
bombs:
|
||||||
open: DATA.R8
|
open: DATA
|
||||||
Start: 3280
|
Start: 3280
|
||||||
Length: 4
|
Length: 4
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3280
|
Start: 3280
|
||||||
Length: 4
|
Length: 4
|
||||||
|
|
||||||
@@ -248,59 +248,59 @@ waypoint:
|
|||||||
Length: *
|
Length: *
|
||||||
|
|
||||||
sietch:
|
sietch:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2998
|
Start: 2998
|
||||||
|
|
||||||
doubleblast:
|
doubleblast:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3279
|
Start: 3279
|
||||||
Facings: -16
|
Facings: -16
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
doubleblastbullet:
|
doubleblastbullet:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3248
|
Start: 3248
|
||||||
Facings: -16
|
Facings: -16
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
|
|
||||||
icon:
|
icon:
|
||||||
paratroopers: DATA.R8
|
paratroopers: DATA
|
||||||
Start: 4029
|
Start: 4029
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
ornistrike: DATA.R8
|
ornistrike: DATA
|
||||||
Start: 4031
|
Start: 4031
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
deathhand: DATA.R8
|
deathhand: DATA
|
||||||
Start: 4035
|
Start: 4035
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
crate:
|
crate:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 102
|
Start: 102
|
||||||
ZOffset: -511
|
ZOffset: -511
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
land: DATA.R8
|
land: DATA
|
||||||
Start: 102
|
Start: 102
|
||||||
ZOffset: -511
|
ZOffset: -511
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
|
|
||||||
spicebloom:
|
spicebloom:
|
||||||
make: DATA.R8
|
make: DATA
|
||||||
Start: 107
|
Start: 107
|
||||||
Length: 3
|
Length: 3
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
active: DATA.R8
|
active: DATA
|
||||||
Start: 109
|
Start: 109
|
||||||
Length: 1
|
Length: 1
|
||||||
ZOffset: -511
|
ZOffset: -511
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 109
|
Start: 109
|
||||||
ZOffset: -511
|
ZOffset: -511
|
||||||
Offset: -16,-16
|
Offset: -16,-16
|
||||||
|
|
||||||
moveflsh:
|
moveflsh:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 3621
|
Start: 3621
|
||||||
Length: 5
|
Length: 5
|
||||||
Tick: 80
|
Tick: 80
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,174 +1,174 @@
|
|||||||
dmcv:
|
dmcv:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1795
|
Start: 1795
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4023
|
Start: 4023
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
harvester:
|
harvester:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1699
|
Start: 1699
|
||||||
Facings: -32
|
Facings: -32
|
||||||
harvest: DATA.R8
|
harvest: DATA
|
||||||
Start: 3631
|
Start: 3631
|
||||||
Length: 6
|
Length: 6
|
||||||
Facings: -8
|
Facings: -8
|
||||||
Tick: 80
|
Tick: 80
|
||||||
ZOffset: 1
|
ZOffset: 1
|
||||||
dock: DATA.R8
|
dock: DATA
|
||||||
Start: 3370
|
Start: 3370
|
||||||
Length: 10
|
Length: 10
|
||||||
dock-loop: DATA.R8
|
dock-loop: DATA
|
||||||
Start: 3380
|
Start: 3380
|
||||||
Length: 1
|
Length: 1
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4019
|
Start: 4019
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
trike:
|
trike:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1635
|
Start: 1635
|
||||||
Facings: -32
|
Facings: -32
|
||||||
unload: DATA.R8
|
unload: DATA
|
||||||
Start: 1635
|
Start: 1635
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3839, 3839, 3840, 3840, 3841, 3841, 3842, 3842, 3843, 3843, 3844, 3844, 3845, 3845, 3846, 3846, 3847, 3847, 3848, 3848, 3849, 3849, 3850, 3850, 3851, 3851, 3852, 3852, 3853, 3853, 3854, 3854, 3855, 3855, 3856, 3856, 3857, 3857, 3858, 3858, 3859, 3859, 3860, 3860, 3861, 3861, 3862, 3862, 3863, 3863, 3864, 3864, 3865, 3865, 3866, 3866, 3867, 3867, 3868, 3868, 3869, 3869, 3870, 3870
|
Frames: 3839, 3839, 3840, 3840, 3841, 3841, 3842, 3842, 3843, 3843, 3844, 3844, 3845, 3845, 3846, 3846, 3847, 3847, 3848, 3848, 3849, 3849, 3850, 3850, 3851, 3851, 3852, 3852, 3853, 3853, 3854, 3854, 3855, 3855, 3856, 3856, 3857, 3857, 3858, 3858, 3859, 3859, 3860, 3860, 3861, 3861, 3862, 3862, 3863, 3863, 3864, 3864, 3865, 3865, 3866, 3866, 3867, 3867, 3868, 3868, 3869, 3869, 3870, 3870
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4041
|
Start: 4041
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
quad:
|
quad:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1667
|
Start: 1667
|
||||||
Facings: -32
|
Facings: -32
|
||||||
unload: DATA.R8
|
unload: DATA
|
||||||
Start: 1667
|
Start: 1667
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4018
|
Start: 4018
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
siegetank:
|
siegetank:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1763
|
Start: 1763
|
||||||
Facings: -32
|
Facings: -32
|
||||||
turret: DATA.R8
|
turret: DATA
|
||||||
Start: 1891
|
Start: 1891
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Start: 3418
|
Start: 3418
|
||||||
Length: 3
|
Length: 3
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4026
|
Start: 4026
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
missiletank:
|
missiletank:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1603
|
Start: 1603
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4024
|
Start: 4024
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
sonictank:
|
sonictank:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1827
|
Start: 1827
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4027
|
Start: 4027
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
combata:
|
combata:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 1731
|
Start: 1731
|
||||||
Facings: -32
|
Facings: -32
|
||||||
turret: DATA.R8
|
turret: DATA
|
||||||
Start: 1859
|
Start: 1859
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4020
|
Start: 4020
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
combath:
|
combath:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2051
|
Start: 2051
|
||||||
Facings: -32
|
Facings: -32
|
||||||
turret: DATA.R8
|
turret: DATA
|
||||||
Start: 2115
|
Start: 2115
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4021
|
Start: 4021
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
devast:
|
devast:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2083
|
Start: 2083
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3807, 3807, 3808, 3808, 3809, 3809, 3810, 3810, 3810, 3811, 3811, 3812, 3812, 3813, 3813, 3814, 3814, 3815, 3816, 3816, 3817, 3817, 3818, 3819, 3819, 3820, 3820, 3821, 3821, 3822, 3822, 3823, 3823, 3824, 3824, 3825, 3825, 3826, 3826, 3827, 3827, 3828, 3828, 3829, 3829, 3830, 3830, 3831, 3831, 3832, 3832, 3832, 3833, 3833, 3834, 3834, 3835, 3835, 3836, 3836, 3837, 3837, 3838, 3838
|
Frames: 3807, 3807, 3808, 3808, 3809, 3809, 3810, 3810, 3810, 3811, 3811, 3812, 3812, 3813, 3813, 3814, 3814, 3815, 3816, 3816, 3817, 3817, 3818, 3819, 3819, 3820, 3820, 3821, 3821, 3822, 3822, 3823, 3823, 3824, 3824, 3825, 3825, 3826, 3826, 3827, 3827, 3828, 3828, 3829, 3829, 3830, 3830, 3831, 3831, 3832, 3832, 3832, 3833, 3833, 3834, 3834, 3835, 3835, 3836, 3836, 3837, 3837, 3838, 3838
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4028
|
Start: 4028
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
combato:
|
combato:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2453
|
Start: 2453
|
||||||
Facings: -32
|
Facings: -32
|
||||||
turret: DATA.R8
|
turret: DATA
|
||||||
Start: 2485
|
Start: 2485
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
Frames: 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3780, 3781, 3781, 3782, 3782, 3783, 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3788, 3789, 3789, 3790, 3790, 3791, 3791, 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800, 3800, 3801, 3801, 3802, 3802, 3803, 3803, 3804, 3804, 3805, 3805, 3806, 3806
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4022
|
Start: 4022
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
raider:
|
raider:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2421
|
Start: 2421
|
||||||
Facings: -32
|
Facings: -32
|
||||||
unload: DATA.R8
|
unload: DATA
|
||||||
Start: 2421
|
Start: 2421
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
|
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
BlendMode: Additive
|
BlendMode: Additive
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4017
|
Start: 4017
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
|
|
||||||
stealthraider:
|
stealthraider:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2421
|
Start: 2421
|
||||||
Facings: -32
|
Facings: -32
|
||||||
unload: DATA.R8
|
unload: DATA
|
||||||
Start: 2421
|
Start: 2421
|
||||||
Facings: -32
|
Facings: -32
|
||||||
muzzle: DATA.R8
|
muzzle: DATA
|
||||||
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
|
Frames: 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3747, 3748, 3748, 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3754, 3755, 3755, 3756, 3756, 3757, 3757, 3758, 3758, 3759, 3759, 3760, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765, 3766, 3766, 3767, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774, 3774
|
||||||
Facings: -32
|
Facings: -32
|
||||||
Length: 2
|
Length: 2
|
||||||
@@ -177,9 +177,9 @@ stealthraider:
|
|||||||
Start: 0
|
Start: 0
|
||||||
|
|
||||||
deviatortank:
|
deviatortank:
|
||||||
idle: DATA.R8
|
idle: DATA
|
||||||
Start: 2389
|
Start: 2389
|
||||||
Facings: -32
|
Facings: -32
|
||||||
icon: DATA.R8
|
icon: DATA
|
||||||
Start: 4025
|
Start: 4025
|
||||||
Offset: -30,-24
|
Offset: -30,-24
|
||||||
@@ -3,7 +3,7 @@ General:
|
|||||||
Id: ARRAKIS
|
Id: ARRAKIS
|
||||||
SheetSize: 1024
|
SheetSize: 1024
|
||||||
Palette: d2k.pal
|
Palette: d2k.pal
|
||||||
Extensions: .R8, .shp
|
Extensions: .R8, .r8, .shp
|
||||||
|
|
||||||
Terrain:
|
Terrain:
|
||||||
TerrainType@Sand:
|
TerrainType@Sand:
|
||||||
|
|||||||
@@ -3,29 +3,36 @@ Background@ASSETBROWSER_BG:
|
|||||||
X:(WINDOW_RIGHT - WIDTH)/2
|
X:(WINDOW_RIGHT - WIDTH)/2
|
||||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||||
Width:700
|
Width:700
|
||||||
Height:410
|
Height:500
|
||||||
Children:
|
Children:
|
||||||
ColorPreviewManager@COLOR_MANAGER:
|
ColorPreviewManager@COLOR_MANAGER:
|
||||||
Label@ASSETBROWSER_TITLE:
|
Label@ASSETBROWSER_TITLE:
|
||||||
X:0
|
Y:20
|
||||||
Y:10
|
|
||||||
Width:PARENT_RIGHT
|
Width:PARENT_RIGHT
|
||||||
Height:25
|
Height:25
|
||||||
Text:Game Asset Viewer & Converter
|
|
||||||
Align:Center
|
|
||||||
Font:Bold
|
Font:Bold
|
||||||
|
Align:Center
|
||||||
|
Text:Asset Browser
|
||||||
|
Label@SOURCE_SELECTOR_DESC:
|
||||||
|
X:20
|
||||||
|
Y:35
|
||||||
|
Width:160
|
||||||
|
Height:25
|
||||||
|
Font:TinyBold
|
||||||
|
Align:Center
|
||||||
|
Text:Select asset source
|
||||||
DropDownButton@SOURCE_SELECTOR:
|
DropDownButton@SOURCE_SELECTOR:
|
||||||
X:40
|
X:20
|
||||||
Y:45
|
Y:60
|
||||||
Width:160
|
Width:160
|
||||||
Height:25
|
Height:25
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Text:Folders
|
Text:Folders
|
||||||
ScrollPanel@ASSET_LIST:
|
ScrollPanel@ASSET_LIST:
|
||||||
X:40
|
X:20
|
||||||
Y:80
|
Y:90
|
||||||
Width:160
|
Width:160
|
||||||
Height:190
|
Height:275
|
||||||
Children:
|
Children:
|
||||||
ScrollItem@ASSET_TEMPLATE:
|
ScrollItem@ASSET_TEMPLATE:
|
||||||
Width:PARENT_RIGHT-27
|
Width:PARENT_RIGHT-27
|
||||||
@@ -38,30 +45,45 @@ Background@ASSETBROWSER_BG:
|
|||||||
X:10
|
X:10
|
||||||
Width:PARENT_RIGHT-20
|
Width:PARENT_RIGHT-20
|
||||||
Height:25
|
Height:25
|
||||||
|
Label@FILENAME_DESC:
|
||||||
|
X:20
|
||||||
|
Y:370
|
||||||
|
Width:160
|
||||||
|
Height:25
|
||||||
|
Font:TinyBold
|
||||||
|
Align:Center
|
||||||
|
Text:Search for file
|
||||||
TextField@FILENAME_INPUT:
|
TextField@FILENAME_INPUT:
|
||||||
X:40
|
X:20
|
||||||
Y:280
|
Y:395
|
||||||
Width:140
|
Width:160
|
||||||
Height:25
|
Height:25
|
||||||
Text:mouse.shp
|
Text:mouse.shp
|
||||||
Button@LOAD_BUTTON:
|
Button@LOAD_BUTTON:
|
||||||
X:40
|
X:20
|
||||||
Y:310
|
Y:425
|
||||||
Width:140
|
Width:160
|
||||||
Height:25
|
Height:25
|
||||||
Text:Load
|
Text:Load
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Key:return
|
Key:return
|
||||||
DropDownButton@PALETTE_SELECTOR:
|
Label@PALETTE_DESC:
|
||||||
X:230
|
X:PARENT_RIGHT-WIDTH-270
|
||||||
Y:45
|
Y:60
|
||||||
|
Width:150
|
||||||
|
Height:25
|
||||||
|
Font:Bold
|
||||||
|
Align:Right
|
||||||
|
Text:Palette:
|
||||||
|
DropDownButton@PALETTE_SELECTOR:
|
||||||
|
X:PARENT_RIGHT-WIDTH-110
|
||||||
|
Y:60
|
||||||
Width:150
|
Width:150
|
||||||
Height:25
|
Height:25
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Text:Palette
|
|
||||||
DropDownButton@COLOR:
|
DropDownButton@COLOR:
|
||||||
X:380
|
X:PARENT_RIGHT-WIDTH-20
|
||||||
Y:45
|
Y:60
|
||||||
Width:80
|
Width:80
|
||||||
Height:25
|
Height:25
|
||||||
Children:
|
Children:
|
||||||
@@ -71,69 +93,19 @@ Background@ASSETBROWSER_BG:
|
|||||||
Width:PARENT_RIGHT-35
|
Width:PARENT_RIGHT-35
|
||||||
Height:PARENT_BOTTOM-12
|
Height:PARENT_BOTTOM-12
|
||||||
Background@SPRITE_BG:
|
Background@SPRITE_BG:
|
||||||
X:220
|
X:190
|
||||||
Y:80
|
Y:90
|
||||||
Width:250
|
Width:490
|
||||||
Height:250
|
Height:330
|
||||||
Background:dialog4
|
Background:dialog3
|
||||||
Children:
|
Children:
|
||||||
ShpImage@SPRITE:
|
ShpImage@SPRITE:
|
||||||
X:4
|
Width:PARENT_RIGHT
|
||||||
Y:4
|
Height:PARENT_BOTTOM
|
||||||
Width:246
|
|
||||||
Height:246
|
|
||||||
Image:mouse
|
Image:mouse
|
||||||
Label@ACTIONS_TITLE:
|
|
||||||
X:PARENT_RIGHT - 150
|
|
||||||
Y:45
|
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Height:25
|
|
||||||
Text:Actions
|
|
||||||
Font:Bold
|
|
||||||
Button@EXPORT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:80
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Selected to PNG
|
|
||||||
Font:Bold
|
|
||||||
Button@EXTRACT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:115
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Extract all to PNG
|
|
||||||
Font:Bold
|
|
||||||
TextField@IMAGE_FILENAME_INPUT:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 235
|
|
||||||
Width:100
|
|
||||||
Height:25
|
|
||||||
Text:pixelart.png
|
|
||||||
TextField@IMAGE_SIZE_INPUT:
|
|
||||||
X:PARENT_RIGHT - 90
|
|
||||||
Y:PARENT_BOTTOM - 235
|
|
||||||
Width:50
|
|
||||||
Height:25
|
|
||||||
Text:width
|
|
||||||
Button@IMPORT_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 200
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Import from PNG
|
|
||||||
Font:Bold
|
|
||||||
Button@CLOSE_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 200
|
|
||||||
Y:PARENT_BOTTOM - 115
|
|
||||||
Width:160
|
|
||||||
Height:25
|
|
||||||
Text:Close
|
|
||||||
Font:Bold
|
|
||||||
Key:escape
|
|
||||||
Container@FRAME_SELECTOR:
|
Container@FRAME_SELECTOR:
|
||||||
X:45
|
X:190
|
||||||
Y:360
|
Y:425
|
||||||
Children:
|
Children:
|
||||||
Button@BUTTON_PREV:
|
Button@BUTTON_PREV:
|
||||||
X:0
|
X:0
|
||||||
@@ -202,14 +174,22 @@ Background@ASSETBROWSER_BG:
|
|||||||
ImageCollection:music
|
ImageCollection:music
|
||||||
ImageName:next
|
ImageName:next
|
||||||
Slider@FRAME_SLIDER:
|
Slider@FRAME_SLIDER:
|
||||||
X:160
|
X:140
|
||||||
Y:0
|
Y:3
|
||||||
Width:410
|
Width:300
|
||||||
Height:20
|
Height:20
|
||||||
MinimumValue: 0
|
MinimumValue: 0
|
||||||
Label@FRAME_COUNT:
|
Label@FRAME_COUNT:
|
||||||
X:585
|
X:445
|
||||||
Y:0
|
Width:40
|
||||||
Width:25
|
|
||||||
Height:25
|
Height:25
|
||||||
Font:Bold
|
Font:TinyBold
|
||||||
|
Align:Left
|
||||||
|
Button@CLOSE_BUTTON:
|
||||||
|
Key:escape
|
||||||
|
X:PARENT_RIGHT-180
|
||||||
|
Y:PARENT_BOTTOM-45
|
||||||
|
Width:160
|
||||||
|
Height:25
|
||||||
|
Font:Bold
|
||||||
|
Text:Close
|
||||||
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
|
|||||||
Width:144
|
Width:144
|
||||||
Height:72
|
Height:72
|
||||||
ShpImage@FACT:
|
ShpImage@FACT:
|
||||||
X:156
|
X:153
|
||||||
Y:1
|
Y:1
|
||||||
|
Width:80
|
||||||
|
Height:73
|
||||||
Image:fact
|
Image:fact
|
||||||
Palette:colorpicker
|
Palette:colorpicker
|
||||||
Button@RANDOM_BUTTON:
|
Button@RANDOM_BUTTON:
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
Background@CONVERT_ASSETS_PANEL:
|
|
||||||
Logic:ConvertGameFilesLogic
|
|
||||||
X:(WINDOW_RIGHT - WIDTH)/2
|
|
||||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
|
||||||
Width:500
|
|
||||||
Height:160
|
|
||||||
Children:
|
|
||||||
Label@TITLE:
|
|
||||||
X:0
|
|
||||||
Y:20
|
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Height:25
|
|
||||||
Text:Extracting and Converting Gamefiles
|
|
||||||
Align:Center
|
|
||||||
Font:Bold
|
|
||||||
Container@EXTRACTING:
|
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Height:PARENT_BOTTOM
|
|
||||||
Visible: false
|
|
||||||
Children:
|
|
||||||
ProgressBar@PROGRESS_BAR:
|
|
||||||
X:50
|
|
||||||
Y:55
|
|
||||||
Width:PARENT_RIGHT - 100
|
|
||||||
Height:25
|
|
||||||
Label@STATUS_LABEL:
|
|
||||||
X:50
|
|
||||||
Y:80
|
|
||||||
Width:PARENT_RIGHT - 100
|
|
||||||
Height:25
|
|
||||||
Align:Left
|
|
||||||
Button@RETRY_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 280
|
|
||||||
Y:PARENT_BOTTOM - 45
|
|
||||||
Width:120
|
|
||||||
Height:25
|
|
||||||
Text:Retry
|
|
||||||
Font:Bold
|
|
||||||
Key:return
|
|
||||||
Button@BACK_BUTTON:
|
|
||||||
X:PARENT_RIGHT - 140
|
|
||||||
Y:PARENT_BOTTOM - 45
|
|
||||||
Width:120
|
|
||||||
Height:25
|
|
||||||
Text:Back
|
|
||||||
Font:Bold
|
|
||||||
Key:escape
|
|
||||||
@@ -7,14 +7,15 @@ Background@MODS_PANEL:
|
|||||||
Children:
|
Children:
|
||||||
Label@TITLE:
|
Label@TITLE:
|
||||||
Text:Select Mod
|
Text:Select Mod
|
||||||
Width:PARENT_RIGHT
|
|
||||||
Y:20
|
Y:20
|
||||||
|
Width:PARENT_RIGHT
|
||||||
|
Height:25
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Align:Center
|
Align:Center
|
||||||
ScrollPanel@MOD_LIST:
|
ScrollPanel@MOD_LIST:
|
||||||
X:15
|
X:20
|
||||||
Y:70
|
Y:70
|
||||||
Width:710
|
Width:700
|
||||||
Height:PARENT_BOTTOM - 125
|
Height:PARENT_BOTTOM - 125
|
||||||
Children:
|
Children:
|
||||||
ScrollItem@MOD_TEMPLATE:
|
ScrollItem@MOD_TEMPLATE:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
cursor: cursor.pal
|
cursor: cursor.pal
|
||||||
|
|
||||||
Cursors:
|
Cursors:
|
||||||
mouse: cursor
|
mouse.shp: cursor
|
||||||
scroll-t:
|
scroll-t:
|
||||||
start:1
|
start:1
|
||||||
scroll-tr:
|
scroll-tr:
|
||||||
@@ -163,7 +163,7 @@ Cursors:
|
|||||||
start:148
|
start:148
|
||||||
length: 12
|
length: 12
|
||||||
|
|
||||||
nopower: cursor
|
nopower.shp: cursor
|
||||||
powerdown-blocked:
|
powerdown-blocked:
|
||||||
start:0
|
start:0
|
||||||
length: 1
|
length: 1
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ ChromeLayout:
|
|||||||
mods/ra/chrome/musicplayer.yaml
|
mods/ra/chrome/musicplayer.yaml
|
||||||
mods/ra/chrome/tooltips.yaml
|
mods/ra/chrome/tooltips.yaml
|
||||||
mods/ra/chrome/assetbrowser.yaml
|
mods/ra/chrome/assetbrowser.yaml
|
||||||
mods/ra/chrome/convertassets.yaml
|
|
||||||
mods/ra/chrome/irc.yaml
|
mods/ra/chrome/irc.yaml
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
|
|||||||
@@ -30,8 +30,10 @@ Background@COLOR_CHOOSER:
|
|||||||
Width:144
|
Width:144
|
||||||
Height:72
|
Height:72
|
||||||
ShpImage@GTCNST:
|
ShpImage@GTCNST:
|
||||||
X:121
|
X:153
|
||||||
Y:0-68
|
Y:1-40
|
||||||
|
Width:80
|
||||||
|
Height:73
|
||||||
Image:gtcnstmk
|
Image:gtcnstmk
|
||||||
Palette:colorpicker
|
Palette:colorpicker
|
||||||
Button@RANDOM_BUTTON:
|
Button@RANDOM_BUTTON:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
cursor: mousepal.pal
|
cursor: mousepal.pal
|
||||||
|
|
||||||
Cursors:
|
Cursors:
|
||||||
mouse: cursor
|
mouse.shp: cursor
|
||||||
scroll-t: #TODO
|
scroll-t: #TODO
|
||||||
start: 2
|
start: 2
|
||||||
scroll-tr: #TODO
|
scroll-tr: #TODO
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ ChromeLayout:
|
|||||||
mods/ra/chrome/musicplayer.yaml
|
mods/ra/chrome/musicplayer.yaml
|
||||||
mods/ra/chrome/tooltips.yaml
|
mods/ra/chrome/tooltips.yaml
|
||||||
mods/ra/chrome/assetbrowser.yaml
|
mods/ra/chrome/assetbrowser.yaml
|
||||||
mods/ra/chrome/convertassets.yaml
|
|
||||||
mods/ra/chrome/irc.yaml
|
mods/ra/chrome/irc.yaml
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
|
|||||||
Reference in New Issue
Block a user