diff --git a/CHANGELOG.md b/CHANGELOG.md index e9c21df58..51c1472fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added +- [#1414] Cancelling in-progress exportation + +### Fixed +- FLA export printing xxx string on exporting character with id 320 ## [16.1.0] - 2022-11-06 ### Added @@ -2376,7 +2381,8 @@ All notable changes to this project will be documented in this file. ### Added - Initial public release -[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.4...dev +[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.1.0...dev +[16.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.4...version16.1.0 [16.0.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.3...version16.0.4 [16.0.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.2...version16.0.3 [16.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version16.0.1...version16.0.2 @@ -2502,6 +2508,7 @@ All notable changes to this project will be documented in this file. [alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9 [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 +[#1414]: https://www.free-decompiler.com/flash/issues/1414 [#1459]: https://www.free-decompiler.com/flash/issues/1459 [#1832]: https://www.free-decompiler.com/flash/issues/1832 [#1849]: https://www.free-decompiler.com/flash/issues/1849 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/BinaryDataExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/BinaryDataExporter.java index b7ccde988..db4a5822b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/BinaryDataExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/BinaryDataExporter.java @@ -41,6 +41,10 @@ public class BinaryDataExporter { public List exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, BinaryDataExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -77,6 +81,10 @@ public class BinaryDataExporter { ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } + if (evl != null) { evl.handleExportedEvent("binarydata", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FontExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FontExporter.java index 89c1d6e7a..6aad531bd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FontExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FontExporter.java @@ -61,6 +61,10 @@ public class FontExporter { public List exportFonts(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final FontExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -98,6 +102,10 @@ public class FontExporter { ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } + if (evl != null) { evl.handleExportedEvent("font", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index 002fadcfc..f9d897bb6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -169,6 +169,10 @@ public class FrameExporter { public List exportFrames(AbortRetryIgnoreHandler handler, String outdir, final SWF swf, int containerId, List frames, final FrameExportSettings settings, final EventListener evl) throws IOException, InterruptedException { final List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (swf.getTags().isEmpty()) { return ret; } @@ -230,6 +234,10 @@ public class FrameExporter { } ret.add(f); }, handler).run(); + + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { Tag parentTag = tim.getParentTag(); @@ -398,6 +406,9 @@ public class FrameExporter { @Override public boolean hasNext() { + if (Thread.currentThread().isInterrupted()) { + return false; + } return fframes.size() > pos; } @@ -407,7 +418,7 @@ public class FrameExporter { } @Override - public BufferedImage next() { + public BufferedImage next() { if (!hasNext()) { return null; } @@ -421,7 +432,9 @@ public class FrameExporter { int fframe = fframes.get(pos++); BufferedImage result = SWF.frameToImageGet(tim, fframe, 0, null, 0, tim.displayRect, new Matrix(), null, fusesTransparency ? null : fbackgroundColor, settings.zoom).getBufferedImage(); - + if (Thread.currentThread().isInterrupted()) { + return null; + } if (evl != null) { evl.handleExportedEvent("frame", pos, fframes.size(), tagName); } @@ -443,7 +456,10 @@ public class FrameExporter { final int fi = i; new RetryTask(() -> { File f = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".bmp"); - BMPFile.saveBitmap(frameImages.next(), f); + BufferedImage img = frameImages.next(); + if (img != null) { + BMPFile.saveBitmap(img, f); + } ret.add(f); }, handler).run(); } @@ -453,8 +469,11 @@ public class FrameExporter { final int fi = i; new RetryTask(() -> { File file = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".png"); - ImageHelper.write(frameImages.next(), ImageFormat.PNG, file); - ret.add(file); + BufferedImage img = frameImages.next(); + if (img != null) { + ImageHelper.write(img, ImageFormat.PNG, file); + ret.add(file); + } }, handler).run(); } @@ -537,11 +556,10 @@ public class FrameExporter { ex.printStackTrace(); } g.dispose(); - /*if (frameImages.hasNext()) { - img = frameImages.next(); - } else { - break; - }*/ + + if (Thread.currentThread().isInterrupted()) { + return; + } pos++; } @@ -626,7 +644,11 @@ public class FrameExporter { try { out.write(0, img0, 1); while (images.hasNext()) { - out.write(0, images.next(), 1); + BufferedImage img = images.next(); + if (img == null) { + break; + } + out.write(0, img, 1); } } finally { out.close(); @@ -643,7 +665,11 @@ public class FrameExporter { encoder.start(file.getAbsolutePath()); encoder.setDelay((int) (1000.0 / frameRate)); while (images.hasNext()) { - encoder.addFrame(images.next()); + BufferedImage img = images.next(); + if (img == null) { + break; + } + encoder.addFrame(img); } encoder.finish(); @@ -660,7 +686,11 @@ public class FrameExporter { writer.writeToSequence(img0); while (images.hasNext()) { - writer.writeToSequence(images.next()); + BufferedImage img = images.next(); + if (img == null) { + break; + } + writer.writeToSequence(img); } writer.close(); @@ -682,6 +712,10 @@ public class FrameExporter { int maxDepth = timeline.getMaxDepth(); Stack clipDepths = new Stack<>(); for (int frame : frames) { + + if (Thread.currentThread().isInterrupted()) { + break; + } result.append("\t\tcase ").append(frame).append(":\r\n"); Frame frameObj = timeline.getFrame(frame); for (int i = 1; i <= maxDepth + 1; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ImageExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ImageExporter.java index 294899bc5..6ad6d7a1a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ImageExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ImageExporter.java @@ -45,6 +45,10 @@ public class ImageExporter { public List exportImages(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, ImageExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -103,6 +107,10 @@ public class ImageExporter { }, handler).run(); ret.add(file); } + + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { evl.handleExportedEvent("image", currentIndex, count, t.getName()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MorphShapeExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MorphShapeExporter.java index 1effaee1a..4d1d58418 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MorphShapeExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MorphShapeExporter.java @@ -57,6 +57,10 @@ public class MorphShapeExporter { //TODO: implement morphshape export. How to handle 65536 frames? public List exportMorphShapes(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, final MorphShapeExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -132,6 +136,9 @@ public class MorphShapeExporter { }, handler).run(); ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { evl.handleExportedEvent("morphshape", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java index 3c6314457..38e6417da 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java @@ -52,6 +52,9 @@ public class MovieExporter { public List exportMovies(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final MovieExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } if (tags.isEmpty()) { return ret; } @@ -85,6 +88,9 @@ public class MovieExporter { } }, handler).run(); + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { evl.handleExportedEvent("movie", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java index 084098ef1..9c4103bbb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/ShapeExporter.java @@ -65,6 +65,10 @@ public class ShapeExporter { public List exportShapes(AbortRetryIgnoreHandler handler, final String outdir, final SWF swf, ReadOnlyTagList tags, final ShapeExportSettings settings, EventListener evl, double unzoom) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -159,6 +163,9 @@ public class ShapeExporter { }, handler).run(); ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { evl.handleExportedEvent("shape", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java index 937cba08c..303cd6e0d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java @@ -53,6 +53,10 @@ public class SoundExporter { public List exportSounds(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -107,6 +111,10 @@ public class SoundExporter { ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } + if (evl != null) { evl.handleExportedEvent("sound", currentIndex, count, t.getName()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SymbolClassExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SymbolClassExporter.java index ddd1d6505..06fd53ab5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SymbolClassExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SymbolClassExporter.java @@ -45,6 +45,10 @@ public class SymbolClassExporter { public List exportNames(AbortRetryIgnoreHandler handler, final String outdir, ReadOnlyTagList tags, SymbolClassExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + int count = 0; for (Tag t : tags) { if (t instanceof ExportAssetsTag || t instanceof SymbolClassTag) { @@ -74,6 +78,9 @@ public class SymbolClassExporter { writer.append(sct.tags.get(i) + ";" + sct.names.get(i) + Helper.newLine); } } + if (Thread.currentThread().isInterrupted()) { + break; + } } } }, handler).run(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java index 15bf3c7d3..0008f84d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java @@ -51,6 +51,10 @@ public class TextExporter { public List exportTexts(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final TextExportSettings settings, EventListener evl) throws IOException, InterruptedException { List ret = new ArrayList<>(); + if (Thread.currentThread().isInterrupted()) { + return ret; + } + if (tags.isEmpty()) { return ret; } @@ -125,6 +129,9 @@ public class TextExporter { fos.write(Utf8Helper.getBytes(Helper.newLine + Configuration.textExportSingleFileSeparator.get() + Helper.newLine)); }, handler).run(); } + if (Thread.currentThread().isInterrupted()) { + break; + } } } ret.add(file); @@ -151,6 +158,9 @@ public class TextExporter { }, handler).run(); ret.add(file); + if (Thread.currentThread().isInterrupted()) { + break; + } if (evl != null) { evl.handleExportedEvent("text", currentIndex, count, t.getName()); } diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 3831243fe..b56ba581b 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -777,6 +777,14 @@ public class Main { public static void startWork(String name, CancellableWorker worker) { startWork(name, -1, worker); } + + public static void continueWork(String name) { + continueWork(name, -1); + } + + public static void continueWork(String name, final int percent) { + startWork(name, percent, mainFrame.getPanel().getCurrentWorker()); + } public static void startWork(final String name, final int percent, final CancellableWorker worker) { working = true; @@ -1075,7 +1083,7 @@ public class Main { text += " " + type; } - startWork(text + " " + index + "/" + count + " " + data, null); + continueWork(text + " " + index + "/" + count + " " + data); } @Override @@ -1085,7 +1093,7 @@ public class Main { text += " " + type; } - startWork(text + " " + index + "/" + count + " " + data, null); + continueWork(text + " " + index + "/" + count + " " + data); } @Override @@ -1094,16 +1102,16 @@ public class Main { throw new Error("Event is not supported by this handler."); } if (event.equals("getVariables")) { - startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data, null); + continueWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); } if (event.equals("deobfuscate")) { - startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data, null); + continueWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); } if (event.equals("deobfuscate_pcode")) { startWork(AppStrings.translate("work.deobfuscating_pcode") + "..." + (String) data, deobfuscatePCodeWorker); } if (event.equals("rename")) { - startWork(AppStrings.translate("work.renaming") + "..." + (String) data, null); + continueWork(AppStrings.translate("work.renaming") + "..." + (String) data); } if (event.equals("importing_as")) { startWork(AppStrings.translate("work.importing_as") + "..." + (String) data, importWorker); diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java b/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java index 7446371ac..973c11874 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameStatusPanel.java @@ -109,6 +109,10 @@ public class MainFrameStatusPanel extends JPanel { statusLabel.setText(s); } + public CancellableWorker getCurrentWorker() { + return currentWorker; + } + public void setWorkStatus(String s, CancellableWorker worker) { if (s.isEmpty()) { loadingPanel.setVisible(false); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 825ab67b4..d7ad40452 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -529,6 +529,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se statusPanel.setWorkStatus(s, worker); mainMenu.updateComponents(); } + + public CancellableWorker getCurrentWorker() { + return statusPanel.getCurrentWorker(); + } private JPanel createWelcomePanel() { JPanel welcomePanel = new JPanel();