From f63069f05a73c26f1987fa241436deb397ab76c7 Mon Sep 17 00:00:00 2001 From: Stephen Diniz Date: Tue, 27 Oct 2020 16:29:58 -0400 Subject: [PATCH] Adding Export Frames button to ViewFrame --- .../java/com/gamemode/tkviewer/TKItems.java | 36 ++ .../com/gamemode/tkviewer/gui/ViewFrame.java | 27 ++ .../gamemode/tkviewer/render/MobRenderer.java | 66 ++-- .../tkviewer/utilities/FileUtils.java | 317 +----------------- 4 files changed, 105 insertions(+), 341 deletions(-) create mode 100644 common/src/main/java/com/gamemode/tkviewer/TKItems.java diff --git a/common/src/main/java/com/gamemode/tkviewer/TKItems.java b/common/src/main/java/com/gamemode/tkviewer/TKItems.java new file mode 100644 index 0000000..c9f61ce --- /dev/null +++ b/common/src/main/java/com/gamemode/tkviewer/TKItems.java @@ -0,0 +1,36 @@ +package com.gamemode.tkviewer; + +import com.gamemode.tkviewer.file_handlers.DatFileHandler; +import com.gamemode.tkviewer.file_handlers.EpfFileHandler; +import com.gamemode.tkviewer.file_handlers.PalFileHandler; +import com.gamemode.tkviewer.render.TileRenderer; +import com.gamemode.tkviewer.resources.Resources; +import com.gamemode.tkviewer.utilities.FileUtils; + +import java.io.File; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; + +public class TKItems { + + public static void main(String[] args) { + File outputDirectory = new File("C:\\NTK_Items"); + + if (!outputDirectory.exists()) { + outputDirectory.mkdirs(); + } + + DatFileHandler charDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "char.dat"); + DatFileHandler miscDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "misc.dat"); + + EpfFileHandler itemEpf = new EpfFileHandler(miscDat.getFile("ITEM.EPF")); + PalFileHandler itemPal = new PalFileHandler(charDat.getFile("ITEM.PAL")); + + TileRenderer tileRenderer = new TileRenderer(new ArrayList(Arrays.asList(itemEpf)), itemPal, 0); + + for (int i = 0; i < itemEpf.frameCount; i++) { + FileUtils.writeBufferedImageToFile(tileRenderer.renderTile(i), Paths.get(outputDirectory.toString(), "item-" + i + ".png").toString()); + } + } +} diff --git a/common/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java b/common/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java index 2a95e22..91b0695 100644 --- a/common/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java +++ b/common/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java @@ -7,6 +7,7 @@ import com.gamemode.tkviewer.render.Renderer; import com.gamemode.tkviewer.resources.Resources; import com.gamemode.tkviewer.utilities.FileUtils; +import org.apache.commons.io.FilenameUtils; import javax.swing.*; import javax.swing.border.LineBorder; @@ -17,7 +18,9 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -33,6 +36,7 @@ public class ViewFrame extends JFrame implements ActionListener { JPanel imagePanel; JList list; + JButton exportButton; JRadioButton framesButton; JRadioButton animationsButton; @@ -118,6 +122,9 @@ public void valueChanged(ListSelectionEvent e) { statusPanel.setBorder(new LineBorder(Color.BLACK)); statusPanel.setPreferredSize(new Dimension(this.getWidth(), 36)); + exportButton = new JButton("Export Frames"); + exportButton.addActionListener(this); + framesButton = new JRadioButton("Frames"); animationsButton = new JRadioButton("Animations"); animationsButton.setSelected(true); @@ -129,6 +136,8 @@ public void valueChanged(ListSelectionEvent e) { framesButton.addActionListener(this); animationsButton.addActionListener(this); + statusPanel.add(exportButton); + statusPanel.add(framesButton); statusPanel.add(animationsButton); @@ -298,6 +307,22 @@ public void mouseClicked(MouseEvent e) { revalidate(); } + public void exportFrames(int index) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setDialogTitle("Choose export directory"); + int result = fileChooser.showSaveDialog(this); + if (result == JFileChooser.APPROVE_OPTION) { + Image[] images = renderer.getFrames(index); + for (int i = 0; i < images.length; i++) { + final int frameIndex = renderer.getFrameIndex(index, i); + FileUtils.writeBufferedImageToFile(((BufferedImage) images[i]), Paths.get(fileChooser.getSelectedFile().toString(), singular + "-" + index + "-" + frameIndex + ".png").toString()); + } + + JOptionPane.showMessageDialog(this, "Frames exported successfully!", "TKViewer", JOptionPane.INFORMATION_MESSAGE); + } + } + @Override public void actionPerformed(ActionEvent ae) { int listIndex = list.getSelectedIndex(); @@ -315,6 +340,8 @@ public void actionPerformed(ActionEvent ae) { } else if (renderer instanceof PartRenderer) { this.renderPartAnimations(listIndex); } + } else if (ae.getSource() == this.exportButton) { + this.exportFrames(listIndex); } } } diff --git a/common/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java b/common/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java index 8dc0594..b38dff1 100644 --- a/common/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java +++ b/common/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java @@ -131,6 +131,42 @@ public BufferedImage renderMob(int tileIndex, int paletteIndex) { return image; } + public int[] getGlobalCanvasSize(int mobIndex) { + // Returns [l, t, r, b] for all chunks in mob + Mob mob = this.mobDna.mobs.get(mobIndex); + + // Determine Canvas Size + int l, t, r, b; + l = t = r = b = 0; + for (int i = 0; i < mob.getChunkCount(); i++) { + MobChunk chunk = mob.getChunks().get(i); + int frameCount = chunk.getBlockCount(); + for (int j = 0; j < frameCount; j++) { + MobBlock block = chunk.getBlocks().get(j); + int frameIndex = (int) (mob.getFrameIndex() + block.getFrameOffset()); + + Frame frame = FileUtils.getFrameFromEpfs(frameIndex, this.mobEpfs); + if (frame == null) { + continue; + } + if (frame.getLeft() < l) { + l = frame.getLeft(); + } + if (frame.getTop() < t) { + t = frame.getTop(); + } + if (frame.getRight() > r) { + r = frame.getRight(); + } + if (frame.getBottom() > b) { + b = frame.getBottom(); + } + } + } + + return new int[]{l, t, r, b}; + } + public List renderAnimation(int mobIndex, ANIMATIONS animation) { return renderAnimation(mobIndex, animation.ordinal()); } @@ -141,31 +177,11 @@ public List renderAnimation(int mobIndex, int chunkIndex) { int frameCount = chunk.getBlockCount(); - // Determine Canvas Size - int l, t, r, b; - l = t = r = b = 0; - for (int i = 0; i < frameCount; i++) { - MobBlock block = chunk.getBlocks().get(i); - int frameIndex = (int)(mob.getFrameIndex() + block.getFrameOffset()); - - Frame frame = FileUtils.getFrameFromEpfs(frameIndex, this.mobEpfs); - if (frame == null) { - continue; - } -// if (frame) - if (frame.getLeft() < l) { - l = frame.getLeft(); - } - if (frame.getTop() < t) { - t = frame.getTop(); - } - if (frame.getRight() > r) { - r = frame.getRight(); - } - if (frame.getBottom() > b) { - b = frame.getBottom(); - } - } + int[] dims = getGlobalCanvasSize(mobIndex); + int l = dims[0]; + int t = dims[1]; + int r = dims[2]; + int b = dims[3]; int effectWidth = r-l; int effectHeight = b-t; diff --git a/common/src/main/java/com/gamemode/tkviewer/utilities/FileUtils.java b/common/src/main/java/com/gamemode/tkviewer/utilities/FileUtils.java index d6013c0..f5d6db4 100644 --- a/common/src/main/java/com/gamemode/tkviewer/utilities/FileUtils.java +++ b/common/src/main/java/com/gamemode/tkviewer/utilities/FileUtils.java @@ -22,6 +22,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.gamemode.tkviewer.resources.Resources.TILE_DIM; import static com.gamemode.tkviewer.utilities.Utils.pad; // Static File Utilities Class @@ -260,322 +261,6 @@ public static void generateStaticObjectTileImages(Path outputDirectory) { } } - public static void generateGroundTileSets(Path outputDirectory) { - FileUtils.generateGroundTileSets(outputDirectory, 1000); - } - - public static void generateGroundTileSets(Path outputDirectory, int tilesetDelimiter) { - if (!outputDirectory.toFile().exists()) { - outputDirectory.toFile().mkdirs(); - } - - DatFileHandler tileDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "tile.dat"); - TileTblFileHandler tileTblFileHandler = new TileTblFileHandler(tileDat.getFile("tile.tbl")); - - // Break the tilesets up by, tileset_delim - for (int i = 0; i < (tileTblFileHandler.tileCount / tilesetDelimiter) + 1; i++) { - File groundTileSetFile = Paths.get(outputDirectory.toString(), - "ground_tiles_" + pad(i, 2) + ".tsx").toFile(); - if (!groundTileSetFile.exists()) { - boolean isLastTileSet = !((i + 1) < (tileTblFileHandler.tileCount / tilesetDelimiter)); - int tileCount = isLastTileSet ? ((int) (tileTblFileHandler.tileCount % tilesetDelimiter)) : tilesetDelimiter; - - try { - FileWriter writer = new FileWriter(groundTileSetFile); - // Clear the file - writer.write("\n"); - writer.append("\n"); - writer.append("\t\n"); - - for (int j = 0; j < tilesetDelimiter; j++) { - int tileId = (i * tilesetDelimiter) + j; - if (tileId == tileTblFileHandler.tileCount) { - break; - } - writer.append("\t\n"); - writer.append("\t\t\n"); - writer.append("\t\n"); - } - - writer.append("\n"); - - writer.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - } - - public static void generateStaticObjectTileSets(Path outputDirectory) { - FileUtils.generateStaticObjectTileSets(outputDirectory, 1000); - } - - public static void generateStaticObjectTileSets(Path outputDirectory, int tilesetDelimiter) { - if (!outputDirectory.toFile().exists()) { - outputDirectory.toFile().mkdirs(); - } - - DatFileHandler tileDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "tile.dat"); - SObjTblFileHandler sObjTblFileHandler = new SObjTblFileHandler(tileDat.getFile("SObj.tbl")); - - // Break the tilesets up by, tileset_delim - for (int i = 0; i < (sObjTblFileHandler.objectCount / tilesetDelimiter) + 1; i++) { - File staticObjectTileSetFile = Paths.get(outputDirectory.toString(), - "object_tiles_" + pad(i, 2) + ".tsx").toFile(); - if (!staticObjectTileSetFile.exists()) { - boolean isLastTileSet = !((i + 1) < (sObjTblFileHandler.objectCount / tilesetDelimiter)); - int tileCount = isLastTileSet ? ((int) (sObjTblFileHandler.objectCount % tilesetDelimiter)) : tilesetDelimiter; - - try { - FileWriter writer = new FileWriter(staticObjectTileSetFile); - // Clear the file - writer.write("\n"); - writer.append("\n"); - writer.append("\t\n"); - - for (int j = 0; j < tilesetDelimiter; j++) { - int objectId = (i * tilesetDelimiter) + j; - if (objectId == sObjTblFileHandler.objectCount) { - break; - } - writer.append("\t\n"); - int objectHeight = sObjTblFileHandler.objects.get(objectId).getHeight(); - writer.append("\t\t\n"); - writer.append("\t\n"); - } - - writer.append("\n"); - - writer.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - } - - private static List collectUsedGroundTileSets(CmpFileHandler cmpFileHandler, int tileDelimiter) { - // Create and Sort Tile Sets - List usedTileSets = new ArrayList(); - for (Tile tile : cmpFileHandler.mapTiles) { - if (tile.getAbTile() >= 0) { - int tileSetIndex = tile.getAbTile() / tileDelimiter; - String tileSetString = "\t\n"; - if (usedTileSets.isEmpty()) { - usedTileSets.add(tileSetString); - } - if (!usedTileSets.contains(tileSetString)) { - usedTileSets.add(tileSetString); - } - } - } - Collections.sort(usedTileSets); - - // Inject GIDs - for (int i = 0; i < usedTileSets.size(); i++) { - int firstGid = (i * tileDelimiter) + 1; - usedTileSets.set(i, usedTileSets.get(i).replace("firstgid=\"?\"", "firstgid=\"" + firstGid + "\"")); - } - - return usedTileSets; - } - - private static List collectUsedStaticObjectTileSets(CmpFileHandler cmpFileHandler, int tileDelimiter, int groundTileSetOffset) { - // Create and Sort Tile Sets - List usedTileSets = new ArrayList(); - for (Tile tile : cmpFileHandler.mapTiles) { - if (tile.getSObjTile() >= 0) { - int tileSetIndex = tile.getSObjTile() / tileDelimiter; - String tileSetString = "\t\n"; - if (usedTileSets.isEmpty()) { - usedTileSets.add(tileSetString); - } - if (!usedTileSets.contains(tileSetString)) { - usedTileSets.add(tileSetString); - } - } - } - Collections.sort(usedTileSets); - - // Inject GIDs - for (int i = 0; i < usedTileSets.size(); i++) { - int firstGid = ((i + groundTileSetOffset) * tileDelimiter) + 1; - usedTileSets.set(i, usedTileSets.get(i).replace("firstgid=\"?\"", "firstgid=\"" + firstGid + "\"")); - } - return usedTileSets; - } - - public static Integer getTileGetGid(Integer tileSetIndex, List usedTileSets, Pattern p) { - for (String tileSetString : usedTileSets) { - if (tileSetString.contains("_" + pad(tileSetIndex, 2) + ".tsx")) { - Matcher m = p.matcher(tileSetString); - - if (m.find()) { - return Integer.parseInt(m.group(1)); - } - } - } - - return -1; - } - - public static void cmpFileToTmxFile(final File cmpFile, final File tmxFile) { - FileUtils.cmpFileToTmxFile(cmpFile, tmxFile, 1000); - } - - public static void cmpFileToTmxFile(final File cmpFile, final File tmxFile, int tileDelimiter) { - CmpFileHandler cmp = new CmpFileHandler(cmpFile); - SObjTblFileHandler sObjTblFileHandler = new SObjTblFileHandler(new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "tile.dat").getFile("SObj.tbl")); - - try { - Pattern p = Pattern.compile("firstgid=\"([0-9]+)\""); - - FileWriter writer = new FileWriter(tmxFile); - writer.write(""); // Clear File - - // Map Header - writer.append("\n"); - writer.append("\n"); - - // Insert Used Ground Tile Sets - List usedGroundTileSets = collectUsedGroundTileSets(cmp, tileDelimiter); - for (String tileSetString : usedGroundTileSets) { - writer.append(tileSetString); - } - - // Insert Used Object Tile Sets - List usedStaticObjectTileSets = collectUsedStaticObjectTileSets(cmp, tileDelimiter, usedGroundTileSets.size()); - for (String tileSetString : usedStaticObjectTileSets) { - writer.append(tileSetString); - } - - // Ground Layer - writer.append("\t\n"); - writer.append("\t\t\n"); - writer.append("\t\t\t\n"); - writer.append("\t\t\n"); - writer.append("\t\t\n"); - - int tileCount = 0; - for (int i = 0; i < cmp.mapHeight; i++) { - for (int j = 0; j < cmp.mapWidth; j++) { - int abTile = cmp.mapTiles.get(tileCount).getAbTile(); - int tileSetIndex = abTile / tileDelimiter; - int tileGid = FileUtils.getTileGetGid(tileSetIndex, usedGroundTileSets, p); - int relativeId = tileGid + (abTile - (tileSetIndex * tileDelimiter)) + 1; - writer.append(((relativeId > 1) ? relativeId : 0) + (((j == (cmp.mapWidth - 1) && i == (cmp.mapHeight - 1)) ? "" : ","))); - tileCount++; - } - writer.append("\n"); - } - - writer.append("\t\t\n"); - writer.append("\t\n"); - - // Object Layer - writer.append("\t\n"); - writer.append("\t\t\n"); - writer.append("\t\t\t\n"); - writer.append("\t\t\n"); - writer.append("\t\t\n"); - - int objectCount = 0; - for (int i = 0; i < cmp.mapHeight; i++) { - for (int j = 0; j < cmp.mapWidth; j++) { - int sObjTile = cmp.mapTiles.get(objectCount).getSObjTile(); - int tileSetIndex = sObjTile / tileDelimiter; - int tileGid = FileUtils.getTileGetGid(tileSetIndex, usedStaticObjectTileSets, p); - int relativeId = tileGid + (sObjTile - (tileSetIndex * tileDelimiter)); - writer.append(((sObjTile >= 0) ? relativeId : 0) + (((j == (cmp.mapWidth - 1) && i == (cmp.mapHeight - 1)) ? "" : ","))); - objectCount++; - } - writer.append("\n"); - } - - writer.append("\t\t\n"); - writer.append("\t\n"); - - // Object Collisions - writer.append("\t\n"); - writer.append("\t\t\n"); - writer.append("\t\t\t\n"); - writer.append("\t\t\n"); - - objectCount = 0; - int collisionWidthHeight = 10; - for (int i = 0; i < cmp.mapHeight; i++) { - for (int j = 0; j < cmp.mapWidth; j++) { - Tile mapTile = cmp.mapTiles.get(objectCount); - int sObjTile = mapTile.getSObjTile(); - int x = -1; - int y = -1; - int width = -1; - int height = -1; - if (sObjTile >= 0) { - SObject sObj = sObjTblFileHandler.objects.get(sObjTile); - byte movementDirection = sObj.getMovementDirection(); - if (movementDirection == 0xF) { - // Full - x = (j * 48); - y = (i * 48); - width = 48; - height = 48; - } - if (movementDirection == 0x1) { - // Bottom - x = (j * 48) + 1; - y = (i * 48) + 48 - collisionWidthHeight; - width = 46; - height = collisionWidthHeight; - } else if (movementDirection == 0x2) { - // Top - x = (j * 48) + 1; - y = (i * 48) + collisionWidthHeight; - width = 46; - height = collisionWidthHeight; - } else if (movementDirection == 0x4) { - // Left - x = (j * 48) - collisionWidthHeight; - y = (i * 48) + 1; - width = collisionWidthHeight; - height = 46; - } else if (movementDirection == 0x8) { - // Right - x = (j * 48) + 48 - collisionWidthHeight; - y = (i * 48) + 1; - width = collisionWidthHeight; - height = 46; - } - } - if (mapTile.getPassableTile() != 0) { - // Full - x = (j * 48); - y = (i * 48); - width = 48; - height = 48; - } - - if (x == -1 || y == -1 || width == -1 || height == -1) { - objectCount++; - continue; - } - - writer.append("\t\t\n"); - objectCount++; - } - } - - writer.append("\t\n"); - - writer.append(""); - - writer.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - public static void generateStencilsFromMaps(Path mapDirectory, Path outputDirectory) { if (!outputDirectory.toFile().exists()) { outputDirectory.toFile().mkdirs();