From 9523db7ad24c952f64f8cd016bf1d34a40ba30ad Mon Sep 17 00:00:00 2001 From: DizzyThermal Date: Wed, 11 Mar 2020 15:12:14 -0400 Subject: [PATCH] Pushing updates to TKPartPicker --- .idea/encodings.xml | 6 - pom-tkpartpicker.xml | 116 ++++++++ pom.xml => pom-tkviewer.xml | 0 .../file_handlers/CmpFileHandler.java | 20 ++ .../tkviewer/gui/TKPartPickerGUI.java | 266 +++++++++++++----- .../com/gamemode/tkviewer/gui/ViewFrame.java | 56 +++- .../gamemode/tkviewer/render/MapRenderer.java | 66 +++++ .../gamemode/tkviewer/render/MobRenderer.java | 4 +- .../tkviewer/render/PartRenderer.java | 59 +++- .../tkviewer/resources/Resources.java | 4 +- .../tkpartpicker/resources/PartInfo.kt | 3 +- 11 files changed, 494 insertions(+), 106 deletions(-) delete mode 100644 .idea/encodings.xml create mode 100644 pom-tkpartpicker.xml rename pom.xml => pom-tkviewer.xml (100%) diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e79da7e..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pom-tkpartpicker.xml b/pom-tkpartpicker.xml new file mode 100644 index 0000000..b0d2886 --- /dev/null +++ b/pom-tkpartpicker.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + com.gamemode.tkviewer + TKPartPicker + 1.0 + TKPartPicker + NexusTK Part Picker + + + UTF-8 + 8 + 8 + 1.3.40 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + com.gamemode.tkviewer.TKPartPicker + + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + + default-compile + none + + + java-compile + compile + compile + + + + + + + ${basedir}/src/main/resources + + client_icon.png + + + + + + + + com.google.guava + guava + 28.0-jre + + + net.imagej + ij + 1.52o + + + commons-io + commons-io + 2.6 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + + diff --git a/pom.xml b/pom-tkviewer.xml similarity index 100% rename from pom.xml rename to pom-tkviewer.xml diff --git a/src/main/java/com/gamemode/tkviewer/file_handlers/CmpFileHandler.java b/src/main/java/com/gamemode/tkviewer/file_handlers/CmpFileHandler.java index d85f808..bdd5d4d 100644 --- a/src/main/java/com/gamemode/tkviewer/file_handlers/CmpFileHandler.java +++ b/src/main/java/com/gamemode/tkviewer/file_handlers/CmpFileHandler.java @@ -43,6 +43,26 @@ public CmpFileHandler(File file) { this.close(); } + public int getIndex(int x, int y) { + int depth = 0; + int length = 0; + + for (int i = 0; i < mapTiles.size(); i++) { + if (length == x && depth == y) { + return i; + } + + if ((((i + 1) % this.mapWidth) == 0) && (i != 0)) { + depth += 1; + length = 0; + } else { + length += 1; + } + } + + return -1; + } + @Override public ByteBuffer toByteBuffer() { // Not implemented diff --git a/src/main/java/com/gamemode/tkviewer/gui/TKPartPickerGUI.java b/src/main/java/com/gamemode/tkviewer/gui/TKPartPickerGUI.java index 8aae902..a568ce2 100644 --- a/src/main/java/com/gamemode/tkviewer/gui/TKPartPickerGUI.java +++ b/src/main/java/com/gamemode/tkviewer/gui/TKPartPickerGUI.java @@ -1,6 +1,8 @@ package com.gamemode.tkviewer.gui; import com.gamemode.tkpartpicker.resources.PartInfo; +import com.gamemode.tkviewer.file_handlers.CmpFileHandler; +import com.gamemode.tkviewer.file_handlers.MapFileHandler; import com.gamemode.tkviewer.render.PartRenderer; import com.gamemode.tkviewer.render.TileRenderer; import com.gamemode.tkviewer.resources.EffectImage; @@ -8,15 +10,21 @@ import com.gamemode.tkviewer.resources.Resources; import com.gamemode.tkviewer.utilities.FileUtils; import com.gamemode.tkviewer.utilities.RenderUtils; +import com.sun.tools.javac.comp.Flow; +import org.apache.commons.io.FilenameUtils; import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; -import java.nio.Buffer; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -26,19 +34,33 @@ public class TKPartPickerGUI extends JFrame implements ActionListener { + // GUI Icon Image clientIcon; + // Menu Bar JMenuBar menuBar; JMenu fileMenu = new JMenu("File"); JMenuItem exitMenuItem = new JMenuItem("Exit"); + // Content JPanel contentPanel; + // Character Viewer Panel JPanel viewerPanel; + + // Options Panel + JPanel optionsPanel; JComboBox partPicker; + JComboBox palettePicker; ImageIcon viewerIcon; + JButton changeMapButton = new JButton("Change Map"); + int mapId = 18020; + + JSpinner xSpinner = new JSpinner(new SpinnerNumberModel(11, 0, 20, 1)); + JSpinner ySpinner = new JSpinner(new SpinnerNumberModel(12, 0, 20, 1)); + // Part Picker Scroller JScrollPane partScroller; JPanel partPanel; @@ -55,21 +77,21 @@ public TKPartPickerGUI(String title) { this.setIconImage(this.clientIcon); characterPartInfo = new LinkedHashMap(); - characterPartInfo.put("Bodies", new PartInfo(3, 2, 6, true, RenderUtils.createBodyRenderer())); - characterPartInfo.put("Coats", new PartInfo(0, 0, 6,false, RenderUtils.createCoatRenderer())); - characterPartInfo.put("Shoes", new PartInfo(0, 0, 6,false, RenderUtils.createShoeRenderer())); - characterPartInfo.put("Mantles", new PartInfo(0, 0,6,false, RenderUtils.createMantleRenderer())); - - characterPartInfo.put("Faces", new PartInfo(0, 2,6,true, RenderUtils.createFaceRenderer())); - characterPartInfo.put("Face Decorations", new PartInfo(3,6, 0,false, RenderUtils.createFaceDecRenderer())); - characterPartInfo.put("Hair", new PartInfo(0, 2,6,true, RenderUtils.createHairRenderer())); - characterPartInfo.put("Helmets", new PartInfo(0, 2,6,false, RenderUtils.createHelmetRenderer())); - - characterPartInfo.put("Spears", new PartInfo(0, 1,6,false, RenderUtils.createSpearRenderer())); - characterPartInfo.put("Shields", new PartInfo(0, 2,6,false, RenderUtils.createShieldRenderer())); - characterPartInfo.put("Swords", new PartInfo(0, 2,6,false, RenderUtils.createSwordRenderer())); - characterPartInfo.put("Bows", new PartInfo(0, 2,3,false, RenderUtils.createBowRenderer())); - characterPartInfo.put("Fans", new PartInfo(0, 2,3,false, RenderUtils.createFanRenderer())); + characterPartInfo.put("Bodies", new PartInfo(3, 2, 6, -1, true, RenderUtils.createBodyRenderer())); + characterPartInfo.put("Coats", new PartInfo(0, 2, 6,-1,false, RenderUtils.createCoatRenderer())); + characterPartInfo.put("Shoes", new PartInfo(0, 0, 6,-1,false, RenderUtils.createShoeRenderer())); + characterPartInfo.put("Mantles", new PartInfo(0, 0,6,-1,false, RenderUtils.createMantleRenderer())); + + characterPartInfo.put("Faces", new PartInfo(0, 2,6,-1,true, RenderUtils.createFaceRenderer())); + characterPartInfo.put("Face Decorations", new PartInfo(0,2, 6,-1,false, RenderUtils.createFaceDecRenderer())); + characterPartInfo.put("Hair", new PartInfo(0, 2,6,-1,true, RenderUtils.createHairRenderer())); + characterPartInfo.put("Helmets", new PartInfo(0, 2,6,-1,false, RenderUtils.createHelmetRenderer())); + + characterPartInfo.put("Spears", new PartInfo(0, 1,6,-1,false, RenderUtils.createSpearRenderer())); + characterPartInfo.put("Shields", new PartInfo(0, 2,9,-1,false, RenderUtils.createShieldRenderer())); + characterPartInfo.put("Swords", new PartInfo(0, 2,6,-1,false, RenderUtils.createSwordRenderer())); + characterPartInfo.put("Bows", new PartInfo(0, 2,3,-1,false, RenderUtils.createBowRenderer())); + characterPartInfo.put("Fans", new PartInfo(0, 2,3,-1,false, RenderUtils.createFanRenderer())); initMenu(); initPanel(); @@ -126,21 +148,54 @@ public void initPanel() { } List partPickerItemsList = new ArrayList(Arrays.asList(partPickerItems)); Collections.sort(partPickerItemsList); + JLabel partPickerLabel = new JLabel("Part Picker:"); + partPickerLabel.setAlignmentX(Component.LEFT_ALIGNMENT); partPicker = new JComboBox(partPickerItemsList.toArray()); partPicker.addActionListener(this); + + // Add Palette List to ComboBox + String[] palettePickerItems = new String[257]; + palettePickerItems[0] = "-- Default"; + for (int i = 1; i < palettePickerItems.length; i++) { + palettePickerItems[i] = (i - 1) + ""; + } + JLabel palettePickerLabel = new JLabel("Palette:"); + palettePickerLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + palettePicker = new JComboBox(palettePickerItems); + palettePicker.addActionListener(this); + + // Add Part/Palette Comboboxes to Options Panel + optionsPanel = new JPanel(); + optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS)); + optionsPanel.add(partPickerLabel); + optionsPanel.add(partPicker); + optionsPanel.add(palettePickerLabel); + optionsPanel.add(palettePicker); + + JPanel coordinatePanel = new JPanel(new FlowLayout()); + JLabel xSpinnerLabel = new JLabel("X:"); + coordinatePanel.add(xSpinnerLabel); + coordinatePanel.add(xSpinner); + JLabel ySpinnerLabel = new JLabel(" Y:"); + coordinatePanel.add(ySpinnerLabel); + coordinatePanel.add(ySpinner); + optionsPanel.add(coordinatePanel); + + changeMapButton.addActionListener(this); + optionsPanel.add(changeMapButton); + // Add Character viewerIcon = new ImageIcon(renderCharacter()); viewerPanel.add(new JLabel(viewerIcon)); - viewerPanel.add(partPicker); + viewerPanel.add(optionsPanel); // Add Part Panel - partPanel = new JPanel(new FlowLayout()); + partPanel = new JPanel(new GridLayout(0, 6)); partPanel.setBorder(BorderFactory.createLineBorder(Color.gray)); - partPanel.setPreferredSize(new Dimension(800, 600)); - partScroller = new JScrollPane(partPanel); - updatePartPanel("Bodies", 0); + updatePartPanel("Bodies", 0, -1); + // Add content to the panel contentPanel.add(viewerPanel); @@ -150,14 +205,21 @@ public void initPanel() { this.add(contentPanel); } - public void updatePartPanel(String partKey, Integer partNumber) { + public void updatePartPanel(String partKey, Integer partNumber, int paletteIndex) { partPanel.removeAll(); PartInfo partInfo = characterPartInfo.get(partKey); PartRenderer partRenderer = this.characterPartInfo.get(partKey).getPartRenderer(); + for (int i = 0; i < partRenderer.partDsc.partCount; i++) { Part part = partRenderer.partDsc.parts.get(i); - BufferedImage partImage = partRenderer.renderPart(i, (int)part.getFrameIndex(), partInfo.getIconFrameIndex(), (int) part.getPaletteId()); + int paletteId; + if (paletteIndex < 0) { + paletteId = (int)part.getPaletteId(); + } else { + paletteId = paletteIndex; + } + BufferedImage partImage = partRenderer.renderPart(i, (int)part.getFrameIndex(), partInfo.getIconFrameIndex(), paletteId); JLabel jLabel = new JLabel(new ImageIcon(partImage)); final int partIndex = i; @@ -168,7 +230,9 @@ public void mouseClicked(MouseEvent e) { boolean shouldRender = partInfo.getShouldRender(); if (currentPartIndex == partIndex) { - partInfo.setShouldRender(!shouldRender); + if (!partKey.equals("Bodies") && !partKey.equals("Faces")) { + partInfo.setShouldRender(!shouldRender); + } } else { partInfo.setShouldRender(true); partInfo.setPartIndex(partIndex); @@ -192,85 +256,94 @@ public void mouseExited(MouseEvent e) {} partPanel.revalidate(); partPanel.repaint(); + partScroller.revalidate(); + partScroller.repaint(); + } + + public void clearWeapon(boolean allWeapons) { + if (allWeapons) { + this.characterPartInfo.get("Fans").setShouldRender(false); + this.characterPartInfo.get("Swords").setShouldRender(false); + extendHand(false); + } + + this.characterPartInfo.get("Bows").setShouldRender(false); + this.characterPartInfo.get("Spears").setShouldRender(false); + } + + public void clearShield() { + this.characterPartInfo.get("Shields").setShouldRender(false); + } + + public void extendHand(boolean extendHand) { + if (extendHand) { + this.characterPartInfo.get("Bodies").setAnimationIndex(6); + this.characterPartInfo.get("Coats").setAnimationIndex(6); + } else { + this.characterPartInfo.get("Bodies").setAnimationIndex(2); + this.characterPartInfo.get("Coats").setAnimationIndex(2); + } } public void syncParts(String partKey) { PartInfo partInfo = this.characterPartInfo.get(partKey); + if (partKey.equals("Helmets")) { - this.characterPartInfo.get("Hair").setShouldRender(false); - } else if (partKey.equals("Hair")) { - this.characterPartInfo.get("Helmets").setShouldRender(false); + // Toggle Hair with Helmet + this.characterPartInfo.get("Hair").setShouldRender(!partInfo.getShouldRender()); } else if (partKey.equals("Bodies")) { this.characterPartInfo.get("Coats").setShouldRender(false); } else if (partKey.equals("Coats")) { - this.characterPartInfo.get("Bodies").setShouldRender(false); + this.characterPartInfo.get("Bodies").setShouldRender(!partInfo.getShouldRender()); } else if (partKey.equals("Bows")) { - this.characterPartInfo.get("Fans").setShouldRender(false); - this.characterPartInfo.get("Shields").setShouldRender(false); - this.characterPartInfo.get("Spears").setShouldRender(false); - this.characterPartInfo.get("Swords").setShouldRender(false); + if (partInfo.getShouldRender()) { + clearWeapon(true); + extendHand(true); + partInfo.setShouldRender(true); + } } else if (partKey.equals("Fans")) { if (partInfo.getShouldRender()) { - this.characterPartInfo.get("Bodies").setAnimationIndex(6); - this.characterPartInfo.get("Coats").setAnimationIndex(6); + clearWeapon(true); + extendHand(true); + partInfo.setShouldRender(true); } else { - this.characterPartInfo.get("Bodies").setAnimationIndex(2); - this.characterPartInfo.get("Coats").setAnimationIndex(2); + extendHand(false); } - this.characterPartInfo.get("Bows").setShouldRender(false); - this.characterPartInfo.get("Spears").setShouldRender(false); - this.characterPartInfo.get("Swords").setShouldRender(false); - } else if (partKey.equals("Shields")) { - this.characterPartInfo.get("Bows").setShouldRender(false); - this.characterPartInfo.get("Spears").setShouldRender(false); } else if (partKey.equals("Spears")) { if (partInfo.getShouldRender()) { - this.characterPartInfo.get("Bodies").setAnimationIndex(6); - this.characterPartInfo.get("Coats").setAnimationIndex(6); + clearWeapon(true); + clearShield(); + extendHand(true); + partInfo.setShouldRender(true); } else { - this.characterPartInfo.get("Bodies").setAnimationIndex(2); - this.characterPartInfo.get("Coats").setAnimationIndex(2); + extendHand(false); } - this.characterPartInfo.get("Bows").setShouldRender(false); - this.characterPartInfo.get("Fans").setShouldRender(false); - this.characterPartInfo.get("Shields").setShouldRender(false); - this.characterPartInfo.get("Spears").setShouldRender(false); - this.characterPartInfo.get("Swords").setShouldRender(false); } else if (partKey.equals("Swords")) { if (partInfo.getShouldRender()) { - this.characterPartInfo.get("Bodies").setAnimationIndex(6); - this.characterPartInfo.get("Coats").setAnimationIndex(6); + clearWeapon(true); + extendHand(true); + partInfo.setShouldRender(true); } else { - this.characterPartInfo.get("Bodies").setAnimationIndex(2); - this.characterPartInfo.get("Coats").setAnimationIndex(2); + extendHand(false); } - this.characterPartInfo.get("Bows").setShouldRender(false); - this.characterPartInfo.get("Fans").setShouldRender(false); - this.characterPartInfo.get("Spears").setShouldRender(false); } } - public BufferedImage createGrassBackground() { - int grassWidth = 4; + public BufferedImage createBackground() { + // Rhino LR + return createBackground(18020, 11, 12, 5); + } - BufferedImage grassBackground = new BufferedImage(Resources.TILE_DIM * grassWidth, Resources.TILE_DIM * grassWidth, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphicsObject = grassBackground.createGraphics(); + public BufferedImage createBackground(int mapId, int x, int y, int width) { + BufferedImage background; - TileRenderer tileRenderer = new TileRenderer(); - BufferedImage tile = tileRenderer.renderTile(21); // Grass Patch + background = RenderUtils.createMapRenderer().renderCropped(mapId, x, y, width, width); - for (int i = 0; i < grassWidth; i++) { - for (int j = 0; j < grassWidth; j++) { - graphicsObject.drawImage(tile, null, (i * Resources.TILE_DIM), (j * Resources.TILE_DIM)); - } - } - - return grassBackground; + return background; } public BufferedImage renderCharacter() { - // 192 x 192 - BufferedImage characterImage = createGrassBackground(); + BufferedImage characterImage = createBackground(mapId, (int)xSpinner.getValue(), (int)ySpinner.getValue() , 5); Graphics2D graphicsObject = characterImage.createGraphics(); List> effImages = new ArrayList>(); @@ -282,8 +355,14 @@ public BufferedImage renderCharacter() { int partIndex = partInfo.getPartIndex(); int animationIndex = partInfo.getAnimationIndex(); + int paletteIndex = partInfo.getPaletteIndex(); - List effectImages = partInfo.getPartRenderer().renderAnimation(partIndex, animationIndex); + List effectImages; + if (paletteIndex < 0) { + effectImages = partInfo.getPartRenderer().renderAnimation(partIndex, animationIndex); + } else { + effectImages = partInfo.getPartRenderer().renderAnimation(partIndex, animationIndex, paletteIndex); + } effImages.add(effectImages); } @@ -306,10 +385,45 @@ public void actionPerformed(ActionEvent ae) { if (ae.getSource() == this.partPicker) { String partKey = this.partPicker.getSelectedItem().toString(); PartInfo partInfo = this.characterPartInfo.get(partKey); - this.updatePartPanel(partKey, partInfo.getIconFrameIndex()); + + int paletteIndex = (partInfo.getPaletteIndex() + 1); + this.palettePicker.setSelectedIndex(paletteIndex); + + String palette = this.palettePicker.getSelectedItem().toString(); + paletteIndex = (palette.contains("Default"))?-1:(Integer.parseInt(palette)-1); + + this.updatePartPanel(partKey, partInfo.getIconFrameIndex(), paletteIndex); + } else if (ae.getSource() == this.palettePicker) { + String partKey = this.partPicker.getSelectedItem().toString(); + PartInfo partInfo = this.characterPartInfo.get(partKey); + + String palette = this.palettePicker.getSelectedItem().toString(); + int paletteIndex = (palette.contains("Default"))?-1:(Integer.parseInt(palette)-1); + partInfo.setPaletteIndex(paletteIndex+1); + + this.updatePartPanel(partKey, partInfo.getIconFrameIndex(), paletteIndex); } else if (ae.getSource() == this.exitMenuItem) { this.dispose(); - System.out.println(); + } else if (ae.getSource() == this.changeMapButton) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setDialogTitle("Select a NexusTK map"); + + fileChooser.setCurrentDirectory(new File(Resources.NTK_MAP_DIRECTORY)); + fileChooser.setAcceptAllFileFilterUsed(false); + FileNameExtensionFilter mapFilter = new FileNameExtensionFilter("Maps (*.cmp;*.map)", "cmp", "map"); + fileChooser.addChoosableFileFilter(mapFilter); + + int result = fileChooser.showOpenDialog(this); + if (result == JFileChooser.APPROVE_OPTION) { + // Get Map File + File selectedFile = fileChooser.getSelectedFile(); + int newMapId = Integer.parseInt(selectedFile.getName().replaceAll("TK", "").replaceAll(".cmp", "")); + + CmpFileHandler cmpFileHandler = new CmpFileHandler(selectedFile); + xSpinner.setModel(new SpinnerNumberModel(0, 0, cmpFileHandler.mapWidth - 5, 1)); + ySpinner.setModel(new SpinnerNumberModel(0, 0, cmpFileHandler.mapHeight - 5, 1)); + mapId = newMapId; + } } } } \ No newline at end of file diff --git a/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java b/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java index 94ad143..1ec3e58 100644 --- a/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java +++ b/src/main/java/com/gamemode/tkviewer/gui/ViewFrame.java @@ -3,6 +3,7 @@ import com.gamemode.tkviewer.render.*; import com.gamemode.tkviewer.render.Renderer; import com.gamemode.tkviewer.resources.EffectImage; +import com.gamemode.tkviewer.resources.Mob; import com.gamemode.tkviewer.resources.Part; import com.gamemode.tkviewer.resources.Resources; import com.gamemode.tkviewer.utilities.FileUtils; @@ -99,18 +100,12 @@ public void configure(boolean useEpfCount) { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { int idx = list.getSelectedIndex(); - if (renderer instanceof EffectRenderer) { - if (framesButton.isSelected()) { - renderFrames(idx); - } else { - renderEffectAnimations(idx); - } - } else if (renderer instanceof PartRenderer) { - if (framesButton.isSelected()) { - renderFrames(idx); - } else { - renderPartAnimations(idx); - } + if (renderer instanceof MobRenderer && !framesButton.isSelected()) { + renderMobAnimations(idx); + } else if (renderer instanceof EffectRenderer && !framesButton.isSelected()) { + renderEffectAnimations(idx); + } else if (renderer instanceof PartRenderer && !framesButton.isSelected()) { + renderPartAnimations(idx); } else { renderFrames(idx); } @@ -197,6 +192,42 @@ public void renderEffectAnimations(int index) { revalidate(); } + public void renderMobAnimations(int index) { + clearImagePanel(); + + // Create Part Animations in Temp Directory + File outputDirectory = new File(Resources.MOB_ANIMATION_DIRECTORY + File.separator + index); + if (!outputDirectory.exists()) { + outputDirectory.mkdirs(); + } + + MobRenderer mobRenderer = ((MobRenderer) renderer); + + List gifPaths = new ArrayList(); + Mob mob = mobRenderer.mobDna.mobs.get(index); + for (int i = 0; i < mob.getChunks().size(); i++) { + List chunkImages = mobRenderer.renderAnimation(index, i); + if (chunkImages.size() != 0) { + String gifPath = outputDirectory + File.separator + singular + "-" + index + "-" + i + "-.gif"; + FileUtils.exportGifFromImages(chunkImages, gifPath); + gifPaths.add(gifPath); + } + } + + for (int i = 0; i < gifPaths.size(); i++) { + // Add GIF to imagePanel + String gifPath = gifPaths.get(i); + if (new File(gifPath).exists()) { + Icon gifIcon = new ImageIcon(gifPath); + JLabel jLabel = new JLabel(gifIcon); + imagePanel.add(jLabel); + } else { + System.err.println("Couldn't find file: " + gifPath); + } + } + + revalidate(); + } public void renderPartAnimations(int index) { clearImagePanel(); @@ -235,7 +266,6 @@ public void renderPartAnimations(int index) { revalidate(); } - public void renderFrames(int index) { clearImagePanel(); diff --git a/src/main/java/com/gamemode/tkviewer/render/MapRenderer.java b/src/main/java/com/gamemode/tkviewer/render/MapRenderer.java index 2ba39b8..9e468c8 100644 --- a/src/main/java/com/gamemode/tkviewer/render/MapRenderer.java +++ b/src/main/java/com/gamemode/tkviewer/render/MapRenderer.java @@ -3,10 +3,16 @@ import com.gamemode.tkviewer.file_handlers.CmpFileHandler; import com.gamemode.tkviewer.file_handlers.MapFileHandler; import com.gamemode.tkviewer.resources.Resources; +import com.gamemode.tkviewer.utilities.FileUtils; +import com.gamemode.tkviewer.utilities.Utils; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; +import java.io.File; +import java.nio.Buffer; +import java.nio.file.Path; +import java.nio.file.Paths; public class MapRenderer { @@ -23,6 +29,66 @@ public MapRenderer(TileRenderer tileRenderer, SObjRenderer sObjRenderer) { this.sObjRenderer = sObjRenderer; } + public BufferedImage renderCropped(int mapId, int x, int y, int width, int height) { + CmpFileHandler cmp = new CmpFileHandler(Resources.NTK_MAP_DIRECTORY + File.separator + "TK" + Utils.pad(mapId, 6) + ".cmp"); + + return renderCropped(cmp, x, y, width, height); + } + + // Overrenders downwards to get all static objects + public BufferedImage renderCropped(CmpFileHandler cmpFileHandler, int x, int y, int width, int height) { + BufferedImage image = new BufferedImage((width * Resources.TILE_DIM), (height * Resources.TILE_DIM), BufferedImage.TYPE_INT_ARGB); + Graphics2D graphicsObject = image.createGraphics(); + graphicsObject.setColor(Color.BLACK); + + int originalHeight = height; + height += 10; + if (y + height > cmpFileHandler.mapHeight) { + height = cmpFileHandler.mapHeight - y; + } + for (int i = x; i < (x + width); i++) { + for (int j = y; j < (y + height); j++) { + int tileIndex = cmpFileHandler.mapTiles.get(cmpFileHandler.getIndex(i, j)).getAbTile(); + if (tileIndex >= 0) { + graphicsObject.drawImage( + this.tileRenderer.renderTile(tileIndex + 1), + null, + (i - x) * Resources.TILE_DIM, + (j - y) * Resources.TILE_DIM); + } else { + BufferedImage transparent = new BufferedImage((width * Resources.TILE_DIM), + (height * Resources.TILE_DIM), BufferedImage.TYPE_INT_ARGB); + graphicsObject.drawImage( + transparent, + null, + (i - x) * Resources.TILE_DIM, + (j - y) * Resources.TILE_DIM); + } + + // Render Static Object (C Tile) + int sObjIndex = cmpFileHandler.mapTiles.get(cmpFileHandler.getIndex(i, j)).getSObjTile(); + if (sObjIndex > 0) { + int sObjHeight = this.sObjRenderer.tileSObjTbl.objects.get(sObjIndex).getHeight(); + if (sObjHeight > 0) { + graphicsObject.drawImage( + this.sObjRenderer.renderSObject(sObjIndex), + null, + (i - x) * Resources.TILE_DIM, + (j - y - sObjHeight + 1) * Resources.TILE_DIM); + } + } + } + } + + return image.getSubimage(0, 0, width * Resources.TILE_DIM, originalHeight * Resources.TILE_DIM); + } + + public BufferedImage renderMap(int mapId) { + CmpFileHandler cmp = new CmpFileHandler(Resources.NTK_MAP_DIRECTORY + File.separator + "TK" + Utils.pad(mapId, 6) + ".cmp"); + + return renderMap(cmp); + } + public BufferedImage renderMap(CmpFileHandler cmpFileHandler) { int width = cmpFileHandler.mapWidth; int height = cmpFileHandler.mapHeight; diff --git a/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java b/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java index 218c4db..13f71f0 100644 --- a/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java +++ b/src/main/java/com/gamemode/tkviewer/render/MobRenderer.java @@ -48,11 +48,11 @@ public static enum ANIMATIONS { public int manualPaletteIndex = 0; public MobRenderer() { - DatFileHandler monDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "monster.dat"); + DatFileHandler monDat = new DatFileHandler(Resources.NTK_DATA_DIRECTORY + File.separator + "mon.dat"); mobs = new HashMap(); - this.mobEpfs = FileUtils.createEpfsFromDats("Mantle"); + this.mobEpfs = FileUtils.createEpfsFromDats("mon"); this.mobPal = new PalFileHandler(monDat.getFile("monster.pal")); this.mobDna = new DnaFileHandler(monDat.getFile("monster.dna")); } diff --git a/src/main/java/com/gamemode/tkviewer/render/PartRenderer.java b/src/main/java/com/gamemode/tkviewer/render/PartRenderer.java index 0383ca4..8ae69e4 100644 --- a/src/main/java/com/gamemode/tkviewer/render/PartRenderer.java +++ b/src/main/java/com/gamemode/tkviewer/render/PartRenderer.java @@ -227,13 +227,7 @@ public PartRenderer(List partEpfs, PalFileHandler partPal, int m this.manualPaletteIndex = manualPaletteIndex; } - - public BufferedImage renderPart(int partIndex, int frameIndex, int frameOffset, int paletteIndex) { - // Return Part if cached. - if (parts.containsKey(frameIndex + frameOffset)) { - return parts.get(frameIndex + frameOffset); - } - + public Frame getFrame(int frameIndex, int frameOffset) { int epfIndex = 0; int frameCount = 0; @@ -247,6 +241,17 @@ public BufferedImage renderPart(int partIndex, int frameIndex, int frameOffset, } Frame frame = this.partEpfs.get(epfIndex).getFrame(frameIndex + frameOffset - frameCount); + return frame; + } + + public BufferedImage renderPart(int partIndex, int frameIndex, int frameOffset, int paletteIndex) { + // Return Part if cached. + if (parts.containsKey(frameIndex + frameOffset)) { + return parts.get(frameIndex + frameOffset); + } + + Frame frame = getFrame(frameIndex, frameOffset); + int width = frame.getWidth(); int height = frame.getHeight(); @@ -342,6 +347,46 @@ public List renderAnimation(int partIndex, int chunkIndex, int manu return images; } + + public Dimension getMaxDimensions(int frameOffset) { + Dimension returnDim = new Dimension(0, 0); + + List epfs = this.partEpfs; + for (int i = 0; i < epfs.size(); i++) { + EpfFileHandler epf = epfs.get(i); + for (int j = 0; j < epf.frameCount; j++) { + Frame frame = epf.getFrame(j); + + if (frame.getWidth() > returnDim.getWidth()) { + returnDim.setSize(frame.getWidth(), returnDim.getHeight()); + } + if (frame.getHeight() > returnDim.getHeight()) { + returnDim.setSize(returnDim.getWidth(), frame.getHeight()); + } + } + } + + return returnDim; + } + + public Dimension getMaxDimensionsForOffset(int frameOffset) { + Dimension returnDim = new Dimension(0, 0); + + for (int i = 0; i < this.partDsc.partCount; i++) { + Part part = this.partDsc.parts.get(i); + Frame frame = getFrame((int)part.getFrameIndex(), frameOffset); + + if (frame.getWidth() > returnDim.getWidth()) { + returnDim.setSize(frame.getWidth(), returnDim.getHeight()); + } + if (frame.getHeight() > returnDim.getHeight()) { + returnDim.setSize(returnDim.getWidth(), frame.getHeight()); + } + } + + return returnDim; + } + @Override public int getCount(boolean useEpfCount) { int output = 0; diff --git a/src/main/java/com/gamemode/tkviewer/resources/Resources.java b/src/main/java/com/gamemode/tkviewer/resources/Resources.java index 6c98472..cb86afd 100644 --- a/src/main/java/com/gamemode/tkviewer/resources/Resources.java +++ b/src/main/java/com/gamemode/tkviewer/resources/Resources.java @@ -68,9 +68,11 @@ public class Resources { public static final String PROGRAM_FILES_X86 = "C:\\Program Files (x86)"; public static final String NTK_DATA_DIRECTORY = PROGRAM_FILES_X86 + File.separator + "KRU\\NexusTK\\Data"; + public static final String NTK_MAP_DIRECTORY = System.getProperty("user.home") + File.separator + "Documents" + File.separator + "NexusTK" + File.separator + "Maps"; public static final String TKVIEWER_DIRECTORY = System.getProperty("java.io.tmpdir") + File.separator + "TKViewer"; - public static final String DATA_DIRECTORY = TKVIEWER_DIRECTORY + File.separator + "NexusTK-Data"; + public static final String DATA_DIRECTORY = TKVIEWER_DIRECTORY + File.separator + "Data"; public static final String EFFECT_ANIMATION_DIRECTORY = TKVIEWER_DIRECTORY + File.separator + "Effect-Animations"; + public static final String MOB_ANIMATION_DIRECTORY = TKVIEWER_DIRECTORY + File.separator + "Mob-Animations"; public static final String PART_ANIMATION_DIRECTORY = TKVIEWER_DIRECTORY + File.separator + "Part-Animations"; public static final String CLIENT_ICON = "client_icon.png"; diff --git a/src/main/kotlin/com/gamemode/tkpartpicker/resources/PartInfo.kt b/src/main/kotlin/com/gamemode/tkpartpicker/resources/PartInfo.kt index 5081334..cc329d0 100644 --- a/src/main/kotlin/com/gamemode/tkpartpicker/resources/PartInfo.kt +++ b/src/main/kotlin/com/gamemode/tkpartpicker/resources/PartInfo.kt @@ -2,4 +2,5 @@ package com.gamemode.tkpartpicker.resources import com.gamemode.tkviewer.render.PartRenderer -class PartInfo(var partIndex: Int, var animationIndex: Int, var iconFrameIndex: Int, var shouldRender: Boolean, val partRenderer: PartRenderer) \ No newline at end of file +class PartInfo(var partIndex: Int, var animationIndex: Int, var iconFrameIndex: Int, var paletteIndex: Int, + var shouldRender: Boolean, val partRenderer: PartRenderer) \ No newline at end of file