Compare commits
No commits in common. "21b018298c4fc75a02a65b57b77451debb79c4db" and "3aa6024103c9294036c02584fafffb9cca83a8f4" have entirely different histories.
21b018298c
...
3aa6024103
|
@ -1,123 +0,0 @@
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace KeepersCompound.TMV;
|
|
||||||
|
|
||||||
public partial class TextureLoader
|
|
||||||
{
|
|
||||||
// TODO: Support more types of PCX just in case
|
|
||||||
|
|
||||||
// References:
|
|
||||||
// - https://www.fileformat.info/format/pcx/egff.htm
|
|
||||||
// - http://www.fysnet.net/pcxfile.htm
|
|
||||||
private static ImageTexture LoadPcx(string path)
|
|
||||||
{
|
|
||||||
static Color[] LoadFamilyPalette(string famPath)
|
|
||||||
{
|
|
||||||
var numColors = 256;
|
|
||||||
var bytesPerColor = 3;
|
|
||||||
var paletteSize = numColors * bytesPerColor;
|
|
||||||
var palette = new Color[numColors];
|
|
||||||
|
|
||||||
var options = new EnumerationOptions
|
|
||||||
{
|
|
||||||
MatchCasing = MatchCasing.CaseInsensitive
|
|
||||||
};
|
|
||||||
var paths = Directory.GetFiles(famPath, "full.pcx", options);
|
|
||||||
if (paths.Length != 0)
|
|
||||||
{
|
|
||||||
var palettePath = paths[0];
|
|
||||||
using MemoryStream stream = new(File.ReadAllBytes(palettePath));
|
|
||||||
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
|
||||||
stream.Seek(-paletteSize, SeekOrigin.End);
|
|
||||||
|
|
||||||
for (var i = 0; i < numColors; i++)
|
|
||||||
{
|
|
||||||
var r = reader.ReadByte() / 255.0f;
|
|
||||||
var g = reader.ReadByte() / 255.0f;
|
|
||||||
var b = reader.ReadByte() / 255.0f;
|
|
||||||
palette[i] = new Color(r, g, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return palette;
|
|
||||||
}
|
|
||||||
|
|
||||||
static System.Numerics.Vector2 ReadVec2(BinaryReader reader)
|
|
||||||
{
|
|
||||||
return new(reader.ReadUInt16(), reader.ReadUInt16());
|
|
||||||
}
|
|
||||||
|
|
||||||
using MemoryStream stream = new(File.ReadAllBytes(path));
|
|
||||||
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
|
||||||
|
|
||||||
// Header
|
|
||||||
var tag = reader.ReadByte();
|
|
||||||
var version = reader.ReadByte();
|
|
||||||
var compression = reader.ReadByte();
|
|
||||||
var bytesPerPixel = reader.ReadByte();
|
|
||||||
var min = ReadVec2(reader);
|
|
||||||
var max = ReadVec2(reader);
|
|
||||||
var dpi = ReadVec2(reader);
|
|
||||||
var headerPalette = reader.ReadBytes(48);
|
|
||||||
reader.ReadByte();
|
|
||||||
var numPlanes = reader.ReadByte();
|
|
||||||
var bytesPerRow = reader.ReadUInt16();
|
|
||||||
var paletteMode = reader.ReadUInt16();
|
|
||||||
var dpiSrc = ReadVec2(reader);
|
|
||||||
reader.ReadBytes(54);
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
if (tag != 0x0A)
|
|
||||||
{
|
|
||||||
throw new System.Exception("Invalid tag");
|
|
||||||
}
|
|
||||||
var validVersions = new int[] { 0, 2, 3, 4, 5 };
|
|
||||||
if (!validVersions.Contains(version))
|
|
||||||
{
|
|
||||||
throw new System.Exception("Unsupported version");
|
|
||||||
}
|
|
||||||
if (compression != 1)
|
|
||||||
{
|
|
||||||
throw new System.Exception("Unsupported compression mode");
|
|
||||||
}
|
|
||||||
if (bytesPerPixel != 8 || numPlanes != 1)
|
|
||||||
{
|
|
||||||
throw new System.Exception("Unsupported bpp/plane format");
|
|
||||||
}
|
|
||||||
|
|
||||||
var palette = LoadFamilyPalette(path.GetBaseDir());
|
|
||||||
|
|
||||||
// Read run length encoded pixel Data
|
|
||||||
var width = (int)(max.X - min.X + 1);
|
|
||||||
var height = (int)(max.Y - min.Y + 1);
|
|
||||||
var image = Image.Create(width, height, false, Image.Format.Rgba8);
|
|
||||||
for (var y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
var x = 0;
|
|
||||||
while (x < bytesPerRow)
|
|
||||||
{
|
|
||||||
var b = reader.ReadByte();
|
|
||||||
if ((b & 0xc0) == 0xc0)
|
|
||||||
{
|
|
||||||
var runLength = b & 0x3f;
|
|
||||||
b = reader.ReadByte();
|
|
||||||
for (var i = 0; i < runLength; i++)
|
|
||||||
{
|
|
||||||
image.SetPixel(x, y, palette[b]);
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image.SetPixel(x, y, palette[b]);
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ImageTexture.CreateFromImage(image);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ using Godot;
|
||||||
|
|
||||||
namespace KeepersCompound.TMV;
|
namespace KeepersCompound.TMV;
|
||||||
|
|
||||||
public partial class TextureLoader
|
public class TextureLoader
|
||||||
{
|
{
|
||||||
private readonly string _rootPath; // TODO: Load from installation resources
|
private readonly string _rootPath; // TODO: Load from installation resources
|
||||||
private readonly string _fmPath;
|
private readonly string _fmPath;
|
||||||
|
@ -60,17 +60,17 @@ public partial class TextureLoader
|
||||||
|
|
||||||
public bool Load(int id, string path)
|
public bool Load(int id, string path)
|
||||||
{
|
{
|
||||||
var userTexturesPath = ProjectSettings.GlobalizePath($"user://textures{path}.PCX");
|
var userTexturesPath = ProjectSettings.GlobalizePath($"user://textures{path}.png");
|
||||||
|
|
||||||
var loaded = false;
|
var loaded = false;
|
||||||
if (_fmTexturePaths.TryGetValue(path.ToLower(), out var filePath))
|
if (_fmTexturePaths.TryGetValue(path.ToLower(), out var filePath))
|
||||||
{
|
{
|
||||||
_textureCache.Add(LoadTexture(filePath));
|
_textureCache.Add(ImageTexture.CreateFromImage(Image.LoadFromFile(filePath)));
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
else if (File.Exists(userTexturesPath))
|
else if (File.Exists(userTexturesPath))
|
||||||
{
|
{
|
||||||
_textureCache.Add(LoadTexture(userTexturesPath));
|
_textureCache.Add(ImageTexture.CreateFromImage(Image.LoadFromFile(userTexturesPath)));
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,17 +80,6 @@ public partial class TextureLoader
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImageTexture LoadTexture(string path)
|
|
||||||
{
|
|
||||||
var ext = path.GetExtension().ToLower();
|
|
||||||
var texture = ext switch
|
|
||||||
{
|
|
||||||
"pcx" => LoadPcx(path),
|
|
||||||
_ => ImageTexture.CreateFromImage(Image.LoadFromFile(path)),
|
|
||||||
};
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageTexture Get(int id)
|
public ImageTexture Get(int id)
|
||||||
{
|
{
|
||||||
if (!_idMap.ContainsKey(id))
|
if (!_idMap.ContainsKey(id))
|
||||||
|
|
Loading…
Reference in New Issue