public async Task <SpriteResourceContext> DeserializeSprite(string fileName, MonsterMetadata metadata) { var dataFile = new FileDataSource("monsterFile", fileName); var palEntries = metadata.ColorDepth == TileColorDepth.Bpp4 ? 16 : 8; var paletteSources = Enumerable.Range(0, palEntries) .Select(x => (IColorSource) new FileColorSource(new BitAddress(PaletteOffset + 16 * metadata.PaletteID + x * 2, 0), Endian.Little)) .ToList(); var pal = new Palette("monsterPalette", new ColorFactory(), ColorModel.Bgr15, paletteSources, true, PaletteStorageSource.Project); pal.DataSource = dataFile; Console.WriteLine(pal.GetNativeColor(0).ToString()); int arrangerWidth = metadata.TileSetSize == TileSetSize.Small ? 8 : 16; int arrangerHeight = metadata.TileSetSize == TileSetSize.Small ? 8 : 16; var formData = new byte[arrangerWidth * arrangerHeight / 8]; int formAddress = metadata.TileSetSize == TileSetSize.Small ? FormSmallOffset + 8 * metadata.FormID : FormLargeOffset + 32 * metadata.FormID; //dataFile.Stream.Seek(formAddress, SeekOrigin.Begin); //var length = await dataFile.Stream.ReadAsync(formData, 0, formData.Length); dataFile.Read(new BitAddress(formAddress, 0), formData.Length * 8, formData); if (metadata.TileSetSize == TileSetSize.Large) // Requires endian swapping the tile form { EndianSwapArray(formData); } var bitStream = BitStream.OpenRead(formData, formData.Length * 8); var arranger = ArrangerBuilder.WithTiledLayout() .WithArrangerElementSize(arrangerWidth, arrangerHeight) .WithElementPixelSize(8, 8) .WithPixelColorType(PixelColorType.Indexed) .WithName("monsterArranger") .AsScatteredArranger() .Build(); int elementsStored = 0; int tileOffset = TileSetOffset + 8 * metadata.TileSetID; int tileSize = metadata.ColorDepth == TileColorDepth.Bpp4 ? 32 : 24; for (int y = 0; y < arrangerHeight; y++) { for (int x = 0; x < arrangerWidth; x++) { if (bitStream.ReadBit() == 1) { IGraphicsCodec codec = metadata.ColorDepth == TileColorDepth.Bpp4 ? new Snes4bppCodec(8, 8) : new Snes3bppCodec(8, 8); var element = new ArrangerElement(x * 8, y * 8, dataFile, new BitAddress(tileOffset * 8), codec, pal); tileOffset += tileSize; arranger.SetElement(element, x, y); elementsStored++; } } } return(new SpriteResourceContext(dataFile, pal, arranger)); }
public static ScatteredArranger CreateIndexedArrangerFromImage(string imageFile, ColorModel colorModel, bool zeroIndexTransparent, ICodecFactory factory, IGraphicsCodec codec) { var image = new Bitmap(imageFile); var imagePalette = image.Palette; var palette = new Palette("testPalette", new ColorFactory(), colorModel, zeroIndexTransparent, PaletteStorageSource.Project); var colorSources = imagePalette.Entries .Select(x => new ProjectNativeColorSource(new ColorRgba32(x.R, x.G, x.B, x.A))); palette.SetColorSources(colorSources); var file = new MemoryDataSource("test", image.Width * image.Height); var elemsX = image.Width / codec.Width; var elemsY = image.Height / codec.Height; var arranger = new ScatteredArranger("testArranger", PixelColorType.Indexed, ElementLayout.Tiled, elemsX, elemsY, codec.Width, codec.Height); var address = new BitAddress(0); for (int y = 0; y < elemsY; y++) { for (int x = 0; x < elemsX; x++) { var element = new ArrangerElement(x, y, file, address, factory.CloneCodec(codec), palette); address += codec.StorageSize; arranger.SetElement(element, x, y); } } return(arranger); }
private MagitekResult <ArrangerElement?> CreateElement(ScatteredArrangerModel arrangerModel, int x, int y) { var elementModel = arrangerModel.ElementGrid[x, y]; IGraphicsCodec codec = default; Palette palette = default; DataSource df = default; var address = BitAddress.Zero; if (elementModel is null) { return(new MagitekResult <ArrangerElement?> .Success(null)); } else if (arrangerModel.ColorType == PixelColorType.Indexed) { if (!string.IsNullOrWhiteSpace(elementModel.DataFileKey)) { Tree.TryGetItem <DataSource>(elementModel.DataFileKey, out df); } address = elementModel.FileAddress; var paletteKey = elementModel.PaletteKey; palette = ResolvePalette(paletteKey); if (palette is null) { return(new MagitekResult <ArrangerElement?> .Failed($"Could not resolve palette '{paletteKey}' referenced by arranger '{arrangerModel.Name}'")); } codec = _codecFactory.GetCodec(elementModel.CodecName, new Size(arrangerModel.ElementPixelSize.Width, arrangerModel.ElementPixelSize.Height)); } else if (arrangerModel.ColorType == PixelColorType.Direct) { if (!string.IsNullOrWhiteSpace(elementModel.DataFileKey)) { Tree.TryGetItem <DataSource>(elementModel.DataFileKey, out df); } address = elementModel.FileAddress; codec = _codecFactory.GetCodec(elementModel.CodecName, new Size(arrangerModel.ElementPixelSize.Width, arrangerModel.ElementPixelSize.Height)); } else { return(new MagitekResult <ArrangerElement?> .Failed($"{nameof(CreateElement)}: Arranger '{arrangerModel.Name}' has invalid {nameof(PixelColorType)} '{arrangerModel.ColorType}'")); } var pixelX = x * arrangerModel.ElementPixelSize.Width; var pixelY = y * arrangerModel.ElementPixelSize.Height; var el = new ArrangerElement(pixelX, pixelY, df, address, codec, palette, elementModel.Mirror, elementModel.Rotation); return(new MagitekResult <ArrangerElement?> .Success(el)); }
/// <summary> /// Lays out ArrangerElements /// </summary> private void PerformLayout() { var address = Address; var patternsX = ArrangerElementSize.Width / TileLayout.Width; var patternsY = ArrangerElementSize.Height / TileLayout.Height; for (int y = 0; y < patternsY; y++) { for (int x = 0; x < patternsX; x++) { foreach (var pos in TileLayout.Pattern) { var posX = x * TileLayout.Width + pos.X; var posY = y * TileLayout.Height + pos.Y; var el = new ArrangerElement(posX * ElementPixelSize.Width, posY * ElementPixelSize.Height, ActiveDataSource, address, ActiveCodec, ActivePalette); if (el.Codec.Layout == ImageLayout.Tiled) { address += ActiveCodec.StorageSize; } else if (el.Codec.Layout == ImageLayout.Single) { address += ElementPixelSize.Width * ActiveCodec.ColorDepth / 4; // TODO: Fix sequential arranger offsets to be bit-wise } else { throw new NotSupportedException(); } ElementGrid[posY, posX] = el; } } } Move(Address); }
public void Setup(string dataFileName, string arrangerName) { using (var fs = File.Create(dataFileName)) { Random rng = new Random(); var data = new byte[3 * 16 * 32]; rng.NextBytes(data); fs.Write(data); } _df = new FileDataSource("FileSource", Path.GetFullPath(dataFileName)); _arranger = new ScatteredArranger(arrangerName, PixelColorType.Indexed, ElementLayout.Tiled, 16, 32, 8, 8); for (int y = 0; y < _arranger.ArrangerElementSize.Height; y++) { for (int x = 0; x < _arranger.ArrangerElementSize.Width; x++) { var el = new ArrangerElement(x * 8, y * 8, _df, new BitAddress(24 * x + 24 * x * y), _codec, _pal); _arranger.SetElement(el, x, y); } } }