From 63ff7c384bd25faacdd19dcb52eeaa24e22470d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Tue, 3 Oct 2023 22:58:40 +0200 Subject: [PATCH] Added #2079 Bulk import sprites from GIFs --- CHANGELOG.md | 2 +- .../flash/configuration/Configuration.java | 3 + .../flash/importers/SpriteImporter.java | 77 +++++++++++++++++- .../decompiler/flash/gui/MainFrameMenu.java | 12 +++ .../jpexs/decompiler/flash/gui/MainPanel.java | 61 +++++++++++++- .../decompiler/flash/gui/PreviewPanel.java | 2 +- .../flash/gui/graphics/importsprite16.png | Bin 0 -> 6067 bytes .../flash/gui/graphics/importsprite32.png | Bin 0 -> 8442 bytes .../locales/AdvancedSettingsDialog.properties | 4 + .../flash/gui/locales/MainFrame.properties | 10 ++- .../flash/gui/tagtree/TagTreeContextMenu.java | 2 +- 11 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/importsprite16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/importsprite32.png diff --git a/CHANGELOG.md b/CHANGELOG.md index aa83fef14..5cb3f6e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ### Added - [#2090] Support for Mochicrypt packed binarydata tags - loading SWF as subtree -- [#2079] Replace DefineSprite with GIF +- [#2079] Replace DefineSprite with GIF, Bulk import sprites from GIFs ## [19.0.0] - 2023-10-01 ### Added diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 273b8b665..76749bded 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -924,6 +924,9 @@ public final class Configuration { @ConfigurationDefaultBoolean(true) public static ConfigurationItem lastFlaExportCompressed = null; + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static ConfigurationItem showImportSpriteInfo = null; private enum OSId { WINDOWS, OSX, UNIX } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SpriteImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SpriteImporter.java index d84387ec9..dba1885c8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SpriteImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SpriteImporter.java @@ -22,20 +22,27 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.DefineShape2Tag; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; -import com.jpexs.decompiler.flash.tags.RemoveObjectTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; -import com.jpexs.decompiler.flash.timeline.Timelined; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.imageio.ImageIO; /** @@ -145,4 +152,70 @@ public class SpriteImporter { return true; } + + public int bulkImport(File spritesDir, SWF swf, boolean printOut) { + Map characters = swf.getCharacters(); + int spriteCount = 0; + List extensions = Arrays.asList("gif"); + File allFiles[] = spritesDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + String nameLower = name.toLowerCase(); + for (String ext : extensions) { + if (nameLower.endsWith("." + ext)) { + return true; + } + } + return false; + } + }); + for (int characterId : characters.keySet()) { + CharacterTag tag = characters.get(characterId); + if (tag instanceof DefineSpriteTag) { + DefineSpriteTag spriteTag = (DefineSpriteTag) tag; + List existingFilesForSpriteTag = new ArrayList<>(); + for (File f : allFiles) { + if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) { + existingFilesForSpriteTag.add(f); + } + } + existingFilesForSpriteTag.sort(new Comparator() { + @Override + public int compare(File o1, File o2) { + String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1); + String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1); + int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2); + if (ret == 0) { + return o1.getName().compareTo(o2.getName()); + } + return ret; + } + }); + + if (existingFilesForSpriteTag.isEmpty()) { + continue; + } + + if (existingFilesForSpriteTag.size() > 1) { + Logger.getLogger(SpriteImporter.class.getName()).log(Level.WARNING, "Multiple matching files for sprite tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForSpriteTag.get(0).getName()}); + } + File sourceFile = existingFilesForSpriteTag.get(0); + + if (printOut) { + System.out.println("Importing character " + characterId + " from file " + sourceFile.getName()); + } + + try(FileInputStream fis = new FileInputStream(sourceFile.getAbsolutePath())) { + importSprite(spriteTag, fis); + spriteCount++; + } catch (IOException ex) { + Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Cannot import sprite " + characterId + " from file " + sourceFile.getName(), ex); + } + if (Thread.currentThread().isInterrupted()) { + break; + } + } + } + return spriteCount; + } } diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index 480f43439..c24e3c188 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -380,6 +380,16 @@ public abstract class MainFrameMenu implements MenuBuilder { } mainFrame.getPanel().importShape((SWF) openable, true); } + + protected void importSpritesActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + if (mainFrame.getPanel().checkEdited()) { + return; + } + mainFrame.getPanel().importSprite((SWF) openable); + } protected void importMoviesActionPerformed(ActionEvent evt) { if (Main.isWorking()) { @@ -1031,6 +1041,7 @@ public abstract class MainFrameMenu implements MenuBuilder { setMenuEnabled("/import/importtab/importText", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/import/importtab/importScript", allSameOpenable && openableSelected && !isWorking); setMenuEnabled("/import/importtab/importImages", allSameSwf && swfSelected && !isWorking); + setMenuEnabled("/import/importtab/importSprites", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/import/importtab/importShapes", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/import/importtab/importShapesNoFill", allSameSwf && swfSelected && !isWorking); setMenuEnabled("/import/importtab/importMovies", allSameSwf && swfSelected && !isWorking); @@ -1164,6 +1175,7 @@ public abstract class MainFrameMenu implements MenuBuilder { addMenuItem("/import/importtab/importImages", translate("menu.file.import.image"), "importimage32", this::importImagesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/import/importtab/importShapes", translate("menu.file.import.shape"), "importshape32", this::importShapesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/import/importtab/importShapesNoFill", translate("menu.file.import.shapeNoFill"), "importshape32", this::importShapesNoFillActionPerformed, PRIORITY_MEDIUM, null, true, null, false); + addMenuItem("/import/importtab/importSprites", translate("menu.file.import.sprite"), "importsprite32", this::importSpritesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/import/importtab/importMovies", translate("menu.file.import.movie"), "importmovie32", this::importMoviesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/import/importtab/importSounds", translate("menu.file.import.sound"), "importsound32", this::importSoundsActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/import/importtab/importSymbolClass", translate("menu.file.import.symbolClass"), "importsymbolclass32", this::importSymbolClassActionPerformed, PRIORITY_MEDIUM, null, true, null, false); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index cc61afadc..1a2381efc 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -3389,6 +3389,65 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se }.execute(); } } + + public void importSprite(final SWF swf) { + ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importSprites"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportSpriteInfo); + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get())); + chooser.setDialogTitle(translate("import.select.directory")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + File spritesDir = new File(Path.combine(selFile, SpriteExportSettings.EXPORT_FOLDER_NAME)); + if (!spritesDir.exists()) { + spritesDir = new File(selFile); + } + final File fSpritesDir = spritesDir; + SpriteImporter spriteImporter = new SpriteImporter(); + + final long timeBefore = System.currentTimeMillis(); + new CancellableWorker() { + + private int count = 0; + + @Override + public Void doInBackground() throws Exception { + try { + count = spriteImporter.bulkImport(fSpritesDir, swf, false); + swf.clearImageCache(); + swf.clearShapeCache(); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error during import", ex); + ViewMessages.showMessageDialog(null, translate("error.import") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage()); + } + return null; + } + + @Override + protected void onStart() { + Main.startWork(translate("work.importing") + "...", this); + } + + @Override + protected void done() { + Main.stopWork(); + long timeAfter = System.currentTimeMillis(); + final long timeMs = timeAfter - timeBefore; + + View.execInEventDispatch(() -> { + refreshTree(swf); + setStatus(translate("import.finishedin").replace("%time%", Helper.formatTimeSec(timeMs))); + + ViewMessages.showMessageDialog(MainPanel.this, translate("import.sprite.result").replace("%count%", Integer.toString(count))); + if (count != 0) { + reload(true); + } + }); + } + }.execute(); + } + } public void importShape(final SWF swf, boolean noFill) { ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importShapes2"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportShapeInfo); @@ -4439,7 +4498,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - public void replaceWithGifButtonActionPerformed(TreeItem item) { + public void replaceSpriteWithGifButtonActionPerformed(TreeItem item) { if (item == null) { return; } diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 684184c8d..51a499b1d 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -403,7 +403,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel replaceSpriteButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - mainPanel.replaceWithGifButtonActionPerformed(mainPanel.getCurrentTree().getCurrentTreeItem()); + mainPanel.replaceSpriteWithGifButtonActionPerformed(mainPanel.getCurrentTree().getCurrentTreeItem()); } }); replaceSpriteButton.setVisible(false); diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/importsprite16.png b/src/com/jpexs/decompiler/flash/gui/graphics/importsprite16.png new file mode 100644 index 0000000000000000000000000000000000000000..2edd3587e998fe02e896075b90634211053f23d2 GIT binary patch literal 6067 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 Hrz`&j{A>j| literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index e105df715..cb88715c8 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -704,3 +704,7 @@ config.description.lastFlaExportVersion = Last exported FLA version config.name.lastFlaExportCompressed = Last FLA export compressed config.description.lastFlaExportCompressed = Last exported FLA version compressed + +#after 19.0.0 +config.name.showImportSpriteInfo = Show information before importing sprites +config.description.showImportSpriteInfo = Displays some info about how importing sprites works after clicking Import sprites in the menu. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 2e36bd09b..bcb3e8b37 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1162,4 +1162,12 @@ button.abcexploretrait = Show trait in ABC Explorer #after 19.0.0 binarydata.swfInside.packer = It looks like there is SWF inside this binary data tag packed with %packer%. Click here to unpack the SWF and load it as subtree. -button.replaceWithGif = Replace with GIF... \ No newline at end of file +button.replaceWithGif = Replace with GIF... + +message.info.importSprites = During importing sprites, you need to select a FOLDER.\r\n \ + The folder must contain "sprites" subfolder and filenames inside must match existing sprites in current selected SWF.\r\n \ + Each file must have ".gif" extension. + +import.sprite.result = %count% sprites imported. + +menu.file.import.sprite = Import sprites from GIF \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 1bfa94a39..8a1408fc5 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -363,7 +363,7 @@ public class TagTreeContextMenu extends JPopupMenu { replaceWithGifMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - mainPanel.replaceWithGifButtonActionPerformed(getCurrentItem()); + mainPanel.replaceSpriteWithGifButtonActionPerformed(getCurrentItem()); } }); replaceWithGifMenuItem.setIcon(View.getIcon("replacesprite16"));