public static WriteableBitmap CreateImage(EntityModel entityModel) { WriteableBitmap bankBitmap = BitmapFactory.New(64, 64); using (bankBitmap.GetBitmapContext()) { foreach (CharacterTile tile in entityModel.Frame.Tiles) { if (string.IsNullOrEmpty(tile.BankID) || string.IsNullOrEmpty(tile.BankTileID)) { continue; } BankModel ptModel = ProjectFiles.GetModel <BankModel>(tile.BankID); if (ptModel == null) { continue; } PTTileModel bankModel = ptModel.GetTileModel(tile.BankTileID); if (string.IsNullOrEmpty(bankModel.GUID) && string.IsNullOrEmpty(bankModel.TileSetID)) { continue; } WriteableBitmap sourceBitmap = CreateImageUtil.GetCacheBitmap(bankModel.TileSetID); if (sourceBitmap == null) { continue; } using (sourceBitmap.GetBitmapContext()) { WriteableBitmap cropped = sourceBitmap.Crop((int)bankModel.Point.X, (int)bankModel.Point.Y, 8, 8); if (tile.FlipX) { cropped = WriteableBitmapExtensions.Flip(cropped, WriteableBitmapExtensions.FlipMode.Vertical); } if (tile.FlipY) { cropped = WriteableBitmapExtensions.Flip(cropped, WriteableBitmapExtensions.FlipMode.Horizontal); } int destX = (int)Math.Floor(tile.Point.X / 8) * 8; int destY = (int)Math.Floor(tile.Point.Y / 8) * 8; Util.CopyBitmapImageToWriteableBitmap(ref bankBitmap, destX, destY, cropped); } } } return(bankBitmap); }
public static WriteableBitmap GetCacheBitmap(string tileSetID) { if (!TileSetModel.BitmapCache.TryGetValue(tileSetID, out WriteableBitmap tileSetBitmap)) { // The tileset exists but the bitmap is not in the cache, so I will try to load it here TileSetModel tileSetModel = ProjectFiles.GetModel <TileSetModel>(tileSetID); return(tileSetModel != null?TileSetModel.LoadBitmap(tileSetModel) : null); } return(tileSetBitmap); }
private void SerializeNametable(MapModel model, ref List <byte> serializedData) { // iterate vertically for (int j = 0; j < 15; ++j) { // each meta tile has two rows, so we have to iterate same index twice for (int k = 0; k < 2; ++k) { // iterate horizontally for (int i = 0; i < 16; ++i) { MapTile[] mapTile = model.AttributeTable[i + (j * 16)].MapTile; if (mapTile == null) { continue; } if (string.IsNullOrEmpty(mapTile[0 + (k * 2)].BankID) || string.IsNullOrEmpty(mapTile[0 + (k * 2)].BankTileID) || string.IsNullOrEmpty(mapTile[1 + (k * 2)].BankID) || string.IsNullOrEmpty(mapTile[1 + (k * 2)].BankTileID)) { continue; } SerializeMapTile(ref serializedData, mapTile[0 + (k * 2)]); SerializeMapTile(ref serializedData, mapTile[1 + (k * 2)]); } } } void SerializeMapTile(ref List <byte> serialized, MapTile mapTile) { BankModel bank = ProjectFiles.GetModel <BankModel>(mapTile.BankID); if (bank == null) { serialized.Add(0); } else { byte tile = (byte)bank.GetTileIndex(mapTile.BankTileID); serialized.Add(tile); } } }
private void WriteMetaSprites(StreamWriter outputFile, CharacterModel model, string name) { ProjectModel projectModel = ModelManager.Get <ProjectModel>(); int nesFPS = projectModel.Header.FrameTiming == FrameTiming.NTSC ? NTSC : PAL; List <string> animationIndices = new List <string>(); foreach (CharacterAnimation animation in model.Animations) { if (string.IsNullOrEmpty(animation.ID)) { continue; } int frameIndex = 0; List <string> frameNames = new List <string>(); for (int i = 0; i < animation.Frames.Length; ++i) { if (animation.Frames[i].Tiles == null) { continue; } string frameName = $"{name}_{animation.Name}_data_{frameIndex++}"; bool foundFrame = false; for (int j = 0; j < animation.Frames[i].Tiles.Length; ++j) { CharacterTile charTile = animation.Frames[i].Tiles[j]; if (string.IsNullOrEmpty(charTile.BankID) || string.IsNullOrEmpty(charTile.BankTileID)) { continue; } if (foundFrame == false) { frameNames.Add(frameName); outputFile.WriteLine($"{frameName}:"); outputFile.WriteLine("; vert tile attr horiz"); foundFrame = true; } byte horiz = (byte)charTile.Point.X; byte vert = (byte)charTile.Point.Y; BankModel bank = ProjectFiles.GetModel <BankModel>(charTile.BankID); byte tile = (byte)bank.GetTileIndex(charTile.BankTileID); int paletteIndex = charTile.PaletteIndex; byte attrs = (byte)paletteIndex; attrs |= charTile.BackBackground ? (byte)32 : (byte)0; attrs |= charTile.FlipX ? (byte)64 : (byte)0; attrs |= charTile.FlipY ? (byte)128 : (byte)0; outputFile.WriteLine($" .byte ${vert:X2}, ${tile:X2}, ${attrs:X2}, ${horiz:X2}"); } if (foundFrame) { // Add the termination byte outputFile.WriteLine(" .byte $FF"); outputFile.WriteLine(""); } } outputFile.WriteLine($"{name}_{animation.Name}_data:"); animationIndices.Add($"{animation.Name}"); int frameDuration = (int)(nesFPS * animation.Speed); int colBoxAx = animation.CollisionInfo == null ? 0 : animation.CollisionInfo.OffsetX; int colBoxAy = animation.CollisionInfo == null ? 0 : animation.CollisionInfo.OffsetY; int colBoxBx = animation.CollisionInfo == null ? 0 : animation.CollisionInfo.OffsetX + animation.CollisionInfo.Width; int colBoxCy = animation.CollisionInfo == null ? 0 : animation.CollisionInfo.OffsetY + animation.CollisionInfo.Height; outputFile.WriteLine($" ; number of frames"); outputFile.WriteLine($" .byte ${frameNames.Count:X2} ; decimal {frameNames.Count}"); outputFile.WriteLine($" ; frame duration"); outputFile.WriteLine($" .byte ${frameDuration:X2} ; decimal {frameDuration}"); outputFile.WriteLine($" ; collision"); outputFile.WriteLine($" ; a____b"); outputFile.WriteLine($" ; | |"); outputFile.WriteLine($" ; |____|"); outputFile.WriteLine($" ; c d"); outputFile.WriteLine($" ; a b c"); outputFile.WriteLine($" ; x y x y"); outputFile.Write($" .byte "); outputFile.Write($"${colBoxAx:X2}, "); outputFile.Write($"${colBoxAy:X2}, "); outputFile.Write($"${colBoxBx:X2}, "); outputFile.Write($"${colBoxCy:X2}"); outputFile.Write(Environment.NewLine); foreach (string frameName in frameNames) { outputFile.WriteLine($" .addr {frameName}"); } outputFile.WriteLine(""); } if (animationIndices.Count > 0) { outputFile.WriteLine("; aninmation indices"); for (int i = 0; i < animationIndices.Count; ++i) { string index = animationIndices[i].ToUpper(); string nameUpper = name.ToUpper(); outputFile.WriteLine($"ANIM_{nameUpper}_{index} = ${i:X2}"); } outputFile.WriteLine(""); outputFile.WriteLine($"{name}_anim_num_map:"); for (int i = 0; i < animationIndices.Count; ++i) { string index = animationIndices[i]; outputFile.WriteLine($" .addr {name}_{index}_data"); } } }
public static WriteableBitmap CreateImage(BankModel bankModel, ref Dictionary <string, WriteableBitmap> bitmapCache, bool sendSignals = true) { FileModelVO[] tileSets = ProjectFiles.GetModels <TileSetModel>().ToArray(); WriteableBitmap bankBitmap = BitmapFactory.New(128, 128); int index = 0; foreach (PTTileModel tile in bankModel.PTTiles) { if (string.IsNullOrEmpty(tile.GUID) || string.IsNullOrEmpty(tile.TileSetID)) { continue; } if (!bitmapCache.TryGetValue(tile.TileSetID, out WriteableBitmap sourceBitmap)) { TileSetModel model = ProjectFiles.GetModel <TileSetModel>(tile.TileSetID); if (model == null) { continue; } ProjectModel projectModel = ModelManager.Get <ProjectModel>(); string path = Path.Combine(projectModel.ProjectPath, model.ImagePath); BitmapImage bmImage = new BitmapImage(); bmImage.BeginInit(); bmImage.CacheOption = BitmapCacheOption.OnLoad; bmImage.UriSource = new Uri(path, UriKind.RelativeOrAbsolute); bmImage.EndInit(); bmImage.Freeze(); sourceBitmap = BitmapFactory.ConvertToPbgra32Format(bmImage); bitmapCache.Add(tile.TileSetID, sourceBitmap); if (sendSignals) { // Add the link object foreach (FileModelVO tileset in tileSets) { if (tileset.Model.GUID == tile.TileSetID) { SignalManager.Get <AddNewTileSetLinkSignal>().Dispatch(new BankLinkVO() { Caption = tileset.Name, Id = tile.TileSetID }); break; } } } } WriteableBitmap cropped = sourceBitmap.Crop((int)tile.Point.X, (int)tile.Point.Y, 8, 8); int destX = index % 16 * 8; int destY = index / 16 * 8; Util.CopyBitmapImageToWriteableBitmap(ref bankBitmap, destX, destY, cropped); index++; } return(bankBitmap); }
public static void CreateImage(MapModel mapModel, ref WriteableBitmap mapBitmap, bool isUpdate) { if (!isUpdate) { mapBitmap = BitmapFactory.New(256, 240); } using (mapBitmap.GetBitmapContext()) { for (int i = 0; i < mapModel.AttributeTable.Length; ++i) { AttributeTable attTable = mapModel.AttributeTable[i]; if (attTable.MapTile == null) { continue; } bool erased = false; bool updateTile = false; if (isUpdate) { // Only update the tiles that were affected by the change if (MapViewModel.FlagMapBitmapChanges[i] == TileUpdate.None) { continue; } erased = MapViewModel.FlagMapBitmapChanges[i] == TileUpdate.Erased; updateTile = MapViewModel.FlagMapBitmapChanges[i] == TileUpdate.Normal; MapViewModel.FlagMapBitmapChanges[i] = TileUpdate.None; } foreach (MapTile tile in attTable.MapTile) { if (isUpdate && !updateTile) { if (tile.Point != MapViewModel.PointMapBitmapChanges[i]) { continue; } } if (string.IsNullOrEmpty(tile.BankID) || string.IsNullOrEmpty(tile.BankTileID)) { continue; } BankModel bankModel = ProjectFiles.GetModel <BankModel>(tile.BankID); if (bankModel == null) { continue; } PTTileModel ptTileModel = bankModel.GetTileModel(tile.BankTileID); if (ptTileModel.TileSetID == null) { continue; } WriteableBitmap tileSetBitmap = CreateImageUtil.GetCacheBitmap(ptTileModel.TileSetID); if (tileSetBitmap == null) { continue; } CacheColorsFromBank(ptTileModel.Group, attTable, mapModel, bankModel); WriteableBitmap cropped = tileSetBitmap.Crop((int)ptTileModel.Point.X, (int)ptTileModel.Point.Y, 8, 8); using (cropped.GetBitmapContext()) { if (erased) { cropped.Clear(BackgroundColor); } else { Tuple <int, PaletteIndex> colorsKey = Tuple.Create(ptTileModel.Group, (PaletteIndex)attTable.PaletteIndex); if (!MapViewModel.GroupedPalettes.TryGetValue(colorsKey, out Dictionary <Color, Color> colors)) { colors = new Dictionary <Color, Color>(); } CreateImageUtil.PaintPixelsBasedOnPalettes(ref cropped, ref colors); } } int destX = (int)Math.Floor(tile.Point.X / 8) * 8; int destY = (int)Math.Floor(tile.Point.Y / 8) * 8; Util.CopyBitmapImageToWriteableBitmap(ref mapBitmap, destX, destY, cropped); } } } }
private static void CacheColorsFromBank(int group, AttributeTable attributeTable, MapModel mapModel, BankModel bankModel) { string paletteId = mapModel.PaletteIDs[(int)attributeTable.PaletteIndex]; PaletteModel paletteModel = ProjectFiles.GetModel <PaletteModel>(paletteId); Color firstColor = paletteModel == null ? Util.NullColor : Util.GetColorFromInt(paletteModel.Color0); Tuple <int, PaletteIndex> tuple = Tuple.Create(group, (PaletteIndex)attributeTable.PaletteIndex); if (!MapViewModel.GroupedPalettes.TryGetValue(tuple, out Dictionary <Color, Color> colors)) { colors = new Dictionary <Color, Color> { // always add the first color of the palette as the background color { Util.NullColor, firstColor } }; MapViewModel.GroupedPalettes.Add(tuple, colors); } // only 4 color per tile if (colors.Count >= 4) { return; } foreach (PTTileModel tile in bankModel.PTTiles) { if (string.IsNullOrEmpty(tile.GUID)) { continue; } if (tile.Group != group) { continue; } if (!TileSetModel.BitmapCache.TryGetValue(tile.TileSetID, out WriteableBitmap tileSetBitmap)) { continue; } WriteableBitmap cropped = tileSetBitmap.Crop((int)tile.Point.X, (int)tile.Point.Y, 8, 8); for (int y = 0; y < 8; ++y) { for (int x = 0; x < 8; ++x) { Color color = cropped.GetPixel(x, y); color.A = 255; if (!colors.TryGetValue(color, out _)) { int paletteColor; switch (colors.Count) { case 0: paletteColor = paletteModel == null ? 0 : paletteModel.Color0; break; case 1: paletteColor = paletteModel == null ? 0 : paletteModel.Color1; break; case 2: paletteColor = paletteModel == null ? 0 : paletteModel.Color2; break; case 3: paletteColor = paletteModel == null ? 0 : paletteModel.Color3; break; default: paletteColor = paletteModel == null ? 0 : paletteModel.Color0; break; } Color newColor = Util.GetColorFromInt(paletteColor); colors.Add(color, newColor); } if (colors.Count >= 4) { return; } } } } }
private static Dictionary <Color, Color> FillColorCacheByGroup(CharacterTile characterTile, int group, string paletteId) { Color nullColor = Util.NullColor; BankModel bankModel = ProjectFiles.GetModel <BankModel>(characterTile.BankID); PaletteModel paletteModel = ProjectFiles.GetModel <PaletteModel>(paletteId); Dictionary <Color, Color> colors = new Dictionary <Color, Color>() { { nullColor, nullColor } }; foreach (PTTileModel tile in bankModel.PTTiles) { if (string.IsNullOrEmpty(tile.GUID)) { continue; } if (tile.Group != group) { continue; } TileSetModel model = ProjectFiles.GetModel <TileSetModel>(tile.TileSetID); if (model == null) { continue; } if (!TileSetModel.BitmapCache.TryGetValue(tile.TileSetID, out WriteableBitmap tileSetBitmap)) { continue; } WriteableBitmap cropped = tileSetBitmap.Crop((int)tile.Point.X, (int)tile.Point.Y, 8, 8); for (int y = 0; y < 8; ++y) { for (int x = 0; x < 8; ++x) { Color color = cropped.GetPixel(x, y); color.A = 255; if (!colors.TryGetValue(color, out Color newColor)) { if (paletteModel == null) { newColor = nullColor; } else { switch (colors.Count) { case 1: newColor = Util.GetColorFromInt(paletteModel.Color1); break; case 2: newColor = Util.GetColorFromInt(paletteModel.Color2); break; case 3: newColor = Util.GetColorFromInt(paletteModel.Color3); break; } } colors.Add(color, newColor); } } } } return(colors); }
public static WriteableBitmap CreateImage(CharacterModel characterModel, int animationIndex, int frameIndex, ref GroupedPalettes groupedPalettes) { if (characterModel.Animations[animationIndex].Frames == null) { return(null); } if (characterModel.Animations[animationIndex].Frames[frameIndex].Tiles == null) { return(null); } WriteableBitmap bankBitmap = BitmapFactory.New(64, 64); using (bankBitmap.GetBitmapContext()) { foreach (CharacterTile tile in characterModel.Animations[animationIndex].Frames[frameIndex].Tiles) { if (string.IsNullOrEmpty(tile.BankID) || string.IsNullOrEmpty(tile.BankTileID)) { continue; } BankModel ptModel = ProjectFiles.GetModel <BankModel>(tile.BankID); if (ptModel == null) { continue; } PTTileModel bankModel = ptModel.GetTileModel(tile.BankTileID); if (string.IsNullOrEmpty(bankModel.GUID) && string.IsNullOrEmpty(bankModel.TileSetID)) { continue; } WriteableBitmap sourceBitmap = CreateImageUtil.GetCacheBitmap(bankModel.TileSetID); if (sourceBitmap == null) { continue; } WriteableBitmap cropped = sourceBitmap.Crop((int)bankModel.Point.X, (int)bankModel.Point.Y, 8, 8); using (cropped.GetBitmapContext()) { if (tile.FlipX) { cropped = WriteableBitmapExtensions.Flip(cropped, WriteableBitmapExtensions.FlipMode.Vertical); } if (tile.FlipY) { cropped = WriteableBitmapExtensions.Flip(cropped, WriteableBitmapExtensions.FlipMode.Horizontal); } Tuple <int, PaletteIndex> tuple = Tuple.Create(bankModel.Group, (PaletteIndex)tile.PaletteIndex); if (!groupedPalettes.TryGetValue(tuple, out Dictionary <Color, Color> colors)) { colors = FillColorCacheByGroup(tile, bankModel.Group, characterModel.PaletteIDs[tile.PaletteIndex]); groupedPalettes.Add(tuple, colors); } CreateImageUtil.PaintPixelsBasedOnPalettes(ref cropped, ref colors); } int destX = (int)Math.Floor(tile.Point.X / 8) * 8; int destY = (int)Math.Floor(tile.Point.Y / 8) * 8; Util.CopyBitmapImageToWriteableBitmap(ref bankBitmap, destX, destY, cropped); } } bankBitmap.Freeze(); return(bankBitmap); }