diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d2561d99..8bc54509f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - AS3 Debugging - export/import ByteArray variable data - [#2123] FLA export - show some progress info - Label that flex compiler is used (when it's enabled in settings) +- [#2119] Option to export assets with names like their assigned classes via SymbolClass, without character id ### Fixed - [#2021], [#2000] Caret position in editors when using tabs and / or unicode @@ -3281,6 +3282,7 @@ Major version of SWF to XML export changed to 2. [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 [#2100]: https://www.free-decompiler.com/flash/issues/2100 [#2123]: https://www.free-decompiler.com/flash/issues/2123 +[#2119]: https://www.free-decompiler.com/flash/issues/2119 [#2021]: https://www.free-decompiler.com/flash/issues/2021 [#2000]: https://www.free-decompiler.com/flash/issues/2000 [#2116]: https://www.free-decompiler.com/flash/issues/2116 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index 29cf1f263..8a80733ef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; @@ -98,12 +99,18 @@ public class InstanceInfo { String className = getName(abc.constants).getNameWithNamespace(abc.constants, false).toRawString(); CharacterTag ct = abc.getSwf().getCharacterByClass(className); if (ct != null) { + String fileName = ct.getCharacterExportFileName(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get()) { + fileName = getName(abc.constants).getNameWithNamespace(abc.constants, false).toRawString(); + } + fileName = Helper.makeFileName(fileName); + if (ct instanceof DefineBinaryDataTag) { - writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + Helper.makeFileName(ct.getCharacterExportFileName()) + ".bin\", mimeType=\"application/octet-stream\")]").newLine(); + writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ".bin\", mimeType=\"application/octet-stream\")]").newLine(); } if (ct instanceof ImageTag) { ImageTag it = (ImageTag) ct; - writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + Helper.makeFileName(ct.getCharacterExportFileName()) + ((ImageTag) ct).getImageFormat().getExtension() + "\")]").newLine(); + writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ((ImageTag) ct).getImageFormat().getExtension() + "\")]").newLine(); } if (ct instanceof DefineSpriteTag) { writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + "assets.swf\", symbol=\"" + Helper.escapeActionScriptString(className) + "\")]").newLine(); @@ -111,7 +118,7 @@ public class InstanceInfo { if (ct instanceof DefineSoundTag) { //should be mp3, otherwise it won't work. Should we convert this? DefineSoundTag st = (DefineSoundTag) ct; - writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + Helper.makeFileName(ct.getCharacterExportFileName()) + "." + (st.getSoundFormat().formatId == SoundFormat.FORMAT_MP3 ? "mp3" : "wav") + "\")]").newLine(); + writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + "." + (st.getSoundFormat().formatId == SoundFormat.FORMAT_MP3 ? "mp3" : "wav") + "\")]").newLine(); } if (ct instanceof FontTag) { FontTag ft = (FontTag) ct; @@ -125,7 +132,7 @@ public class InstanceInfo { } } - writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + Helper.makeFileName(ct.getCharacterExportFileName()) + ".ttf\",").newLine(); + writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ".ttf\",").newLine(); writer.appendNoHilight("fontName=\"" + Helper.escapeActionScriptString(ft.getFontNameIntag()) + "\",").newLine(); writer.appendNoHilight("fontFamily=\"" + Helper.escapeActionScriptString(ft.getFontName()) + "\",").newLine(); writer.appendNoHilight("mimeType=\"application/x-font\",").newLine(); @@ -174,7 +181,7 @@ public class InstanceInfo { if (ct instanceof DefineFont4Tag) { DefineFont4Tag ft4 = (DefineFont4Tag) ct; - writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + Helper.makeFileName(ct.getCharacterExportFileName()) + ".cff\",").newLine(); + writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ".cff\",").newLine(); writer.appendNoHilight("fontName=\"" + Helper.escapeActionScriptString(ft4.fontName) + "\",").newLine(); writer.appendNoHilight("mimeType=\"application/x-font\",").newLine(); writer.appendNoHilight("fontWeight=\"" + (ft4.fontFlagsBold ? "bold" : "normal") + "\",").newLine(); 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 d2b64e886..84686edc9 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 @@ -982,6 +982,10 @@ public final class Configuration { @ConfigurationDefaultInt(1000) @ConfigurationCategory("limit") public static ConfigurationItem boxBlurPixelsLimit = null; + + @ConfigurationDefaultBoolean(false) + @ConfigurationCategory("export") + public static ConfigurationItem as3ExportNamesUseClassNamesOnly = null; private enum OSId { WINDOWS, OSX, UNIX 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 0cc622c3f..38245d29d 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 @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; import com.jpexs.decompiler.flash.tags.Tag; @@ -30,8 +31,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * @@ -78,8 +82,20 @@ public class BinaryDataExporter { fos.write(bdt.binaryData.getRangeData()); } }, handler).run(); - - ret.add(file); + + Set classNames = bdt.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext)); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } if (Thread.currentThread().isInterrupted()) { break; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/Font4Exporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/Font4Exporter.java index a5ca1340d..940da11c3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/Font4Exporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/Font4Exporter.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.Font4ExportMode; import com.jpexs.decompiler.flash.exporters.settings.Font4ExportSettings; import com.jpexs.decompiler.flash.tags.DefineFont4Tag; @@ -32,8 +33,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -84,7 +88,19 @@ public class Font4Exporter { exportFont(st, settings.mode, file); }, handler).run(); - ret.add(file); + Set classNames = st.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext)); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } if (Thread.currentThread().isInterrupted()) { break; 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 ad525244f..77783a817 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 @@ -46,6 +46,8 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; @@ -100,9 +102,21 @@ public class FontExporter { new RetryTask(() -> { exportFont(st, settings.mode, file); }, handler).run(); - - ret.add(file); - + + Set classNames = st.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext)); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } + if (Thread.currentThread().isInterrupted()) { break; } 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 62f325ec7..1cc4677a6 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 @@ -166,6 +166,75 @@ public class FrameExporter { FrameExportSettings fes = new FrameExportSettings(fem, settings.zoom); return exportFrames(handler, outdir, swf, containerId, frames, fes, evl); } + + private class MyFrameIterator implements Iterator { + + private int pos = 0; + private final Timeline tim; + private final List fframes; + private final EventListener evl; + private final boolean usesTransparency; + private final Color backgroundColor; + private final FrameExportSettings settings; + + public MyFrameIterator( + Timeline tim, + List fframes, + final EventListener evl, + boolean usesTransparency, + Color backgroundColor, + FrameExportSettings settings + ) { + this.tim = tim; + this.fframes = fframes; + this.evl = evl; + this.usesTransparency = usesTransparency; + this.backgroundColor = backgroundColor; + this.settings = settings; + } + + public void reset() { + pos = 0; + } + + @Override + public boolean hasNext() { + if (Thread.currentThread().isInterrupted()) { + return false; + } + return fframes.size() > pos; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public BufferedImage next() { + if (!hasNext()) { + return null; + } + + Tag parentTag = tim.getParentTag(); + String tagName = parentTag == null ? "" : parentTag.getName(); + + if (evl != null) { + evl.handleExportingEvent("frame", pos + 1, fframes.size(), tagName); + } + + int fframe = fframes.get(pos++); + BufferedImage result = SWF.frameToImageGet(tim, fframe, 0, null, 0, tim.displayRect, new Matrix(), null, usesTransparency ? null : backgroundColor, settings.zoom, true).getBufferedImage(); + if (Thread.currentThread().isInterrupted()) { + return null; + } + if (evl != null) { + evl.handleExportedEvent("frame", pos, fframes.size(), tagName); + } + + return result; + } + } 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<>(); @@ -177,12 +246,21 @@ public class FrameExporter { return ret; } Timeline tim0; - String path = ""; + List paths = new ArrayList<>(); if (containerId == 0) { tim0 = swf.getTimeline(); + paths.add(""); } else { tim0 = ((Timelined) swf.getCharacter(containerId)).getTimeline(); - path = File.separator + Helper.makeFileName(swf.getCharacter(containerId).getExportFileName()); + + Set classNames = swf.getCharacter(containerId).getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + paths.add(File.separator + Helper.makeFileName(className)); + } + } else { + paths.add(File.separator + Helper.makeFileName(swf.getCharacter(containerId).getExportFileName())); + } } final Timeline tim = tim0; @@ -195,8 +273,14 @@ public class FrameExporter { } } - final File foutdir = new File(outdir + path); - Path.createDirectorySafe(foutdir); + final List foutdirs = new ArrayList<>(); + + for (String path : paths) { + File foutdir = new File(outdir + path); + foutdirs.add(foutdir); + Path.createDirectorySafe(foutdir); + } + final List fframes = frames; @@ -215,25 +299,27 @@ public class FrameExporter { final int fi = i; final Color fbackgroundColor = null; - new RetryTask(() -> { - int frame = fframes.get(fi); - File f = new File(foutdir + File.separator + (frame + 1) + ".svg"); - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { - ExportRectangle rect = new ExportRectangle(tim.displayRect); - rect.xMax *= settings.zoom; - rect.yMax *= settings.zoom; - rect.xMin *= settings.zoom; - rect.yMin *= settings.zoom; - SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame"); - if (fbackgroundColor != null) { - exporter.setBackGroundColor(fbackgroundColor); - } + for (File foutdir : foutdirs) { + new RetryTask(() -> { + int frame = fframes.get(fi); + File f = new File(foutdir + File.separator + (frame + 1) + ".svg"); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { + ExportRectangle rect = new ExportRectangle(tim.displayRect); + rect.xMax *= settings.zoom; + rect.yMax *= settings.zoom; + rect.xMin *= settings.zoom; + rect.yMin *= settings.zoom; + SVGExporter exporter = new SVGExporter(rect, settings.zoom, "frame"); + if (fbackgroundColor != null) { + exporter.setBackGroundColor(fbackgroundColor); + } - tim.toSVG(frame, 0, null, 0, exporter, null, 0); - fos.write(Utf8Helper.getBytes(exporter.getSVG())); - } - ret.add(f); - }, handler).run(); + tim.toSVG(frame, 0, null, 0, exporter, null, 0); + fos.write(Utf8Helper.getBytes(exporter.getSVG())); + } + ret.add(f); + }, handler).run(); + } if (Thread.currentThread().isInterrupted()) { break; @@ -257,104 +343,106 @@ public class FrameExporter { final Timeline ftim = tim; final Color fbackgroundColor = null; final SWF fswf = swf; - new RetryTask(() -> { - File fcanvas = new File(foutdir + File.separator + "canvas.js"); - Helper.saveStream(SWF.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/canvas.js"), fcanvas); - ret.add(fcanvas); + for (File foutdir : foutdirs) { + new RetryTask(() -> { + File fcanvas = new File(foutdir + File.separator + "canvas.js"); + Helper.saveStream(SWF.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/canvas.js"), fcanvas); + ret.add(fcanvas); - File f = new File(foutdir + File.separator + "frames.js"); - File fmin = new File(foutdir + File.separator + "frames.min.js"); - int width = (int) (ftim.displayRect.getWidth() * settings.zoom / SWF.unitDivisor); - int height = (int) (ftim.displayRect.getHeight() * settings.zoom / SWF.unitDivisor); - try (final OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { - fos.write(Utf8Helper.getBytes("\r\n")); - fos.write(Utf8Helper.getBytes("var scalingGrids = {};\r\nvar boundRects = {};\r\n")); - Set library = new HashSet<>(); - ftim.getNeededCharacters(fframes, library); + File f = new File(foutdir + File.separator + "frames.js"); + File fmin = new File(foutdir + File.separator + "frames.min.js"); + int width = (int) (ftim.displayRect.getWidth() * settings.zoom / SWF.unitDivisor); + int height = (int) (ftim.displayRect.getHeight() * settings.zoom / SWF.unitDivisor); + try (final OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { + fos.write(Utf8Helper.getBytes("\r\n")); + fos.write(Utf8Helper.getBytes("var scalingGrids = {};\r\nvar boundRects = {};\r\n")); + Set library = new HashSet<>(); + ftim.getNeededCharacters(fframes, library); - SWF.libraryToHtmlCanvas(fswf, library, fos); + SWF.libraryToHtmlCanvas(fswf, library, fos); - String currentName = ftim.id == 0 ? "main" : SWF.getTypePrefix(fswf.getCharacter(ftim.id)) + ftim.id; + String currentName = ftim.id == 0 ? "main" : SWF.getTypePrefix(fswf.getCharacter(ftim.id)) + ftim.id; - StringBuilder sb = new StringBuilder(); - sb.append("function ").append(currentName).append("(ctx,ctrans,frame,ratio,time){\r\n"); - sb.append("\tctx.save();\r\n"); - sb.append("\tctx.transform(1,0,0,1,").append(-ftim.displayRect.Xmin * settings.zoom / SWF.unitDivisor).append(",").append(-ftim.displayRect.Ymin * settings.zoom / SWF.unitDivisor).append(");\r\n"); - framesToHtmlCanvas(sb, SWF.unitDivisor / settings.zoom, ftim, fframes, 0, null, 0, ftim.displayRect, null, fbackgroundColor); - sb.append("\tctx.restore();\r\n"); - sb.append("}\r\n\r\n"); + StringBuilder sb = new StringBuilder(); + sb.append("function ").append(currentName).append("(ctx,ctrans,frame,ratio,time){\r\n"); + sb.append("\tctx.save();\r\n"); + sb.append("\tctx.transform(1,0,0,1,").append(-ftim.displayRect.Xmin * settings.zoom / SWF.unitDivisor).append(",").append(-ftim.displayRect.Ymin * settings.zoom / SWF.unitDivisor).append(");\r\n"); + framesToHtmlCanvas(sb, SWF.unitDivisor / settings.zoom, ftim, fframes, 0, null, 0, ftim.displayRect, null, fbackgroundColor); + sb.append("\tctx.restore();\r\n"); + sb.append("}\r\n\r\n"); - sb.append("var frame = -1;\r\n"); - sb.append("var time = 0;\r\n"); - sb.append("var frames = [];\r\n"); - for (int i : fframes) { - sb.append("frames.push(").append(i).append(");\r\n"); - } - sb.append("\r\n"); - RGB backgroundColor1 = new RGB(255, 255, 255); - if (setBgColorTag != null) { - backgroundColor1 = setBgColorTag.backgroundColor; + sb.append("var frame = -1;\r\n"); + sb.append("var time = 0;\r\n"); + sb.append("var frames = [];\r\n"); + for (int i : fframes) { + sb.append("frames.push(").append(i).append(");\r\n"); + } + sb.append("\r\n"); + RGB backgroundColor1 = new RGB(255, 255, 255); + if (setBgColorTag != null) { + backgroundColor1 = setBgColorTag.backgroundColor; + } + + sb.append("var backgroundColor = \"").append(backgroundColor1.toHexRGB()).append("\";\r\n"); + sb.append("var originalWidth = ").append(width).append(";\r\n"); + sb.append("var originalHeight= ").append(height).append(";\r\n"); + sb.append("function nextFrame(ctx,ctrans){\r\n"); + sb.append("\tvar oldframe = frame;\r\n"); + sb.append("\tframe = (frame+1)%frames.length;\r\n"); + sb.append("\tif(frame==oldframe){time++;}else{time=0;};\r\n"); + sb.append("\tdrawFrame();\r\n"); + sb.append("}\r\n\r\n"); + + sb.append("function drawFrame(){\r\n"); + sb.append("\tctx.fillStyle = backgroundColor;\r\n"); + sb.append("\tctx.fillRect(0,0,canvas.width,canvas.height);\r\n"); + sb.append("\tctx.save();\r\n"); + sb.append("\tctx.transform(canvas.width/originalWidth,0,0,canvas.height/originalHeight,0,0);\r\n"); + sb.append("\t").append(currentName).append("(ctx,ctrans,frames[frame],0,time);\r\n"); + sb.append("\tctx.restore();\r\n"); + sb.append("}\r\n\r\n"); + if (ftim.swf.frameRate > 0) { + sb.append("window.setInterval(function(){nextFrame(ctx,ctrans);},").append((int) (1000.0 / ftim.swf.frameRate)).append(");\r\n"); + } + sb.append("nextFrame(ctx,ctrans);\r\n"); + fos.write(Utf8Helper.getBytes(sb.toString())); } - sb.append("var backgroundColor = \"").append(backgroundColor1.toHexRGB()).append("\";\r\n"); - sb.append("var originalWidth = ").append(width).append(";\r\n"); - sb.append("var originalHeight= ").append(height).append(";\r\n"); - sb.append("function nextFrame(ctx,ctrans){\r\n"); - sb.append("\tvar oldframe = frame;\r\n"); - sb.append("\tframe = (frame+1)%frames.length;\r\n"); - sb.append("\tif(frame==oldframe){time++;}else{time=0;};\r\n"); - sb.append("\tdrawFrame();\r\n"); - sb.append("}\r\n\r\n"); - - sb.append("function drawFrame(){\r\n"); - sb.append("\tctx.fillStyle = backgroundColor;\r\n"); - sb.append("\tctx.fillRect(0,0,canvas.width,canvas.height);\r\n"); - sb.append("\tctx.save();\r\n"); - sb.append("\tctx.transform(canvas.width/originalWidth,0,0,canvas.height/originalHeight,0,0);\r\n"); - sb.append("\t").append(currentName).append("(ctx,ctrans,frames[frame],0,time);\r\n"); - sb.append("\tctx.restore();\r\n"); - sb.append("}\r\n\r\n"); - if (ftim.swf.frameRate > 0) { - sb.append("window.setInterval(function(){nextFrame(ctx,ctrans);},").append((int) (1000.0 / ftim.swf.frameRate)).append(");\r\n"); - } - sb.append("nextFrame(ctx,ctrans);\r\n"); - fos.write(Utf8Helper.getBytes(sb.toString())); - } - - boolean packed = false; - if (Configuration.packJavaScripts.get()) { - try { - JPacker.main(new String[]{"-q", "-b", "62", "-o", fmin.getAbsolutePath(), f.getAbsolutePath()}); - f.delete(); - packed = true; - } catch (Exception | Error e) { // Something wrong in the packer - logger.log(Level.WARNING, "JPacker: Cannot minimize script"); + boolean packed = false; + if (Configuration.packJavaScripts.get()) { + try { + JPacker.main(new String[]{"-q", "-b", "62", "-o", fmin.getAbsolutePath(), f.getAbsolutePath()}); + f.delete(); + packed = true; + } catch (Exception | Error e) { // Something wrong in the packer + logger.log(Level.WARNING, "JPacker: Cannot minimize script"); + f.renameTo(fmin); + } + } else { f.renameTo(fmin); } - } else { - f.renameTo(fmin); - } - File fh = new File(foutdir + File.separator + "frames.html"); - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fh)); FileInputStream fis = new FileInputStream(fmin)) { - fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getHtmlPrefix(width, height))); - fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getJsPrefix())); - byte[] buf = new byte[1000]; - int cnt; - while ((cnt = fis.read(buf)) > 0) { - fos.write(buf, 0, cnt); + File fh = new File(foutdir + File.separator + "frames.html"); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fh)); FileInputStream fis = new FileInputStream(fmin)) { + fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getHtmlPrefix(width, height))); + fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getJsPrefix())); + byte[] buf = new byte[1000]; + int cnt; + while ((cnt = fis.read(buf)) > 0) { + fos.write(buf, 0, cnt); + } + if (packed) { + fos.write(Utf8Helper.getBytes(";")); + } + fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getJsSuffix())); + fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getHtmlSuffix())); } - if (packed) { - fos.write(Utf8Helper.getBytes(";")); - } - fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getJsSuffix())); - fos.write(Utf8Helper.getBytes(CanvasShapeExporter.getHtmlSuffix())); - } - fmin.delete(); + fmin.delete(); - ret.add(f); - }, handler).run(); + ret.add(f); + }, handler).run(); + } if (evl != null) { Tag parentTag = tim.getParentTag(); @@ -366,28 +454,13 @@ public class FrameExporter { if (settings.mode == FrameExportMode.SWF) { Color fBackgroundColor = backgroundColor; if (exportAll) { - new RetryTask(() -> { - File f = new File(foutdir + File.separator + "frames.swf"); - - try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { - try { - new PreviewExporter().exportSwf(fos, swf.getCharacter(containerId), fBackgroundColor, 0, false); - } catch (ActionParseException ex) { - Logger.getLogger(MorphShapeExporter.class.getName()).log(Level.SEVERE, null, ex); - } - } - - ret.add(f); - }, handler).run(); - } else { - for (Integer frame : fframes) { + for (File foutdir : foutdirs) { new RetryTask(() -> { - File f = new File(foutdir + File.separator + (frame + 1) + ".swf"); - Frame fn = (Frame) tim.getFrame(frame); + File f = new File(foutdir + File.separator + "frames.swf"); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { try { - new PreviewExporter().exportSwf(fos, fn, fBackgroundColor, 0, false); + new PreviewExporter().exportSwf(fos, swf.getCharacter(containerId), fBackgroundColor, 0, false); } catch (ActionParseException ex) { Logger.getLogger(MorphShapeExporter.class.getName()).log(Level.SEVERE, null, ex); } @@ -396,184 +469,175 @@ public class FrameExporter { ret.add(f); }, handler).run(); } + } else { + for (Integer frame : fframes) { + for (File foutdir : foutdirs) { + new RetryTask(() -> { + File f = new File(foutdir + File.separator + (frame + 1) + ".swf"); + Frame fn = (Frame) tim.getFrame(frame); + + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) { + try { + new PreviewExporter().exportSwf(fos, fn, fBackgroundColor, 0, false); + } catch (ActionParseException ex) { + Logger.getLogger(MorphShapeExporter.class.getName()).log(Level.SEVERE, null, ex); + } + } + + ret.add(f); + }, handler).run(); + } + } } } final Color fbackgroundColor = backgroundColor; - final boolean fusesTransparency = settings.mode == FrameExportMode.PNG || settings.mode == FrameExportMode.GIF; - final Iterator frameImages = new Iterator() { - private int pos = 0; - - @Override - public boolean hasNext() { - if (Thread.currentThread().isInterrupted()) { - return false; - } - return fframes.size() > pos; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - @Override - public BufferedImage next() { - if (!hasNext()) { - return null; - } - - Tag parentTag = tim.getParentTag(); - String tagName = parentTag == null ? "" : parentTag.getName(); - - if (evl != null) { - evl.handleExportingEvent("frame", pos + 1, fframes.size(), tagName); - } - - int fframe = fframes.get(pos++); - BufferedImage result = SWF.frameToImageGet(tim, fframe, 0, null, 0, tim.displayRect, new Matrix(), null, fusesTransparency ? null : fbackgroundColor, settings.zoom, true).getBufferedImage(); - if (Thread.currentThread().isInterrupted()) { - return null; - } - if (evl != null) { - evl.handleExportedEvent("frame", pos, fframes.size(), tagName); - } - - return result; - } - }; + final boolean usesTransparency = settings.mode == FrameExportMode.PNG || settings.mode == FrameExportMode.GIF; + final MyFrameIterator frameImages = new MyFrameIterator(tim, fframes, evl, usesTransparency, backgroundColor, settings); switch (settings.mode) { case GIF: - new RetryTask(() -> { - File f = new File(foutdir + File.separator + "frames.gif"); - makeGIF(frameImages, swf.frameRate, f, evl); - ret.add(f); - }, handler).run(); - break; - case BMP: - for (int i = 0; frameImages.hasNext(); i++) { - final int fi = i; + for (File foutdir : foutdirs) { + frameImages.reset(); new RetryTask(() -> { - File f = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".bmp"); - BufferedImage img = frameImages.next(); - if (img != null) { - BMPFile.saveBitmap(img, f); - } + File f = new File(foutdir + File.separator + "frames.gif"); + makeGIF(frameImages, swf.frameRate, f, evl); ret.add(f); }, handler).run(); } break; + case BMP: + for (File foutdir : foutdirs) { + frameImages.reset(); + for (int i = 0; frameImages.hasNext(); i++) { + final int fi = i; + new RetryTask(() -> { + File f = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".bmp"); + BufferedImage img = frameImages.next(); + if (img != null) { + BMPFile.saveBitmap(img, f); + } + ret.add(f); + }, handler).run(); + } + } + break; case PNG: - for (int i = 0; frameImages.hasNext(); i++) { - final int fi = i; - new RetryTask(() -> { - File file = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".png"); - BufferedImage img = frameImages.next(); - if (img != null) { - ImageHelper.write(img, ImageFormat.PNG, file); - ret.add(file); - } - }, handler).run(); + for (File foutdir : foutdirs) { + frameImages.reset(); + for (int i = 0; frameImages.hasNext(); i++) { + final int fi = i; + new RetryTask(() -> { + File file = new File(foutdir + File.separator + (fframes.get(fi) + 1) + ".png"); + BufferedImage img = frameImages.next(); + if (img != null) { + ImageHelper.write(img, ImageFormat.PNG, file); + ret.add(file); + } + }, handler).run(); + } } - - //ShapeExporterBase.clearCache(); break; case PDF: if (frameImages.hasNext()) { - new RetryTask(() -> { - File f = new File(foutdir + File.separator + "frames.pdf"); - PDFJob job = new PDFJob(new BufferedOutputStream(new FileOutputStream(f))); - PageFormat pf = new PageFormat(); - pf.setOrientation(PageFormat.PORTRAIT); - Paper p = new Paper(); - /*BufferedImage img = frameImages.next(); - p.setSize(img.getWidth() + 10, img.getHeight() + 10);*/ + for (File foutdir : foutdirs) { + new RetryTask(() -> { + File f = new File(foutdir + File.separator + "frames.pdf"); + PDFJob job = new PDFJob(new BufferedOutputStream(new FileOutputStream(f))); + PageFormat pf = new PageFormat(); + pf.setOrientation(PageFormat.PORTRAIT); + Paper p = new Paper(); + /*BufferedImage img = frameImages.next(); + p.setSize(img.getWidth() + 10, img.getHeight() + 10);*/ - int pos = 0; - RECT rect = tim.displayRect; + int pos = 0; + RECT rect = tim.displayRect; - double w = (rect.getWidth() * settings.zoom / SWF.unitDivisor); - double h = (rect.getHeight() * settings.zoom / SWF.unitDivisor); - p.setSize(w, h); - pf.setPaper(p); - double zoom = settings.zoom; - Matrix m = new Matrix(); - m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); - m.scale(zoom); - Matrix transformation = m; - Map existingFonts = new HashMap<>(); + double w = (rect.getWidth() * settings.zoom / SWF.unitDivisor); + double h = (rect.getHeight() * settings.zoom / SWF.unitDivisor); + p.setSize(w, h); + pf.setPaper(p); + double zoom = settings.zoom; + Matrix m = new Matrix(); + m.translate(-rect.Xmin * zoom, -rect.Ymin * zoom); + m.scale(zoom); + Matrix transformation = m; + Map existingFonts = new HashMap<>(); - while (pos < fframes.size()) { + while (pos < fframes.size()) { - if (evl != null) { - Tag parentTag = tim.getParentTag(); - String tagName = parentTag == null ? "" : parentTag.getName(); - evl.handleExportingEvent("frame", pos + 1, fframes.size(), tagName); - } - int fframe = fframes.get(pos); - final Graphics2D g = (Graphics2D) job.getGraphics(pf); - //g.drawImage(img, 5, 5, img.getWidth(), img.getHeight(), null); + if (evl != null) { + Tag parentTag = tim.getParentTag(); + String tagName = parentTag == null ? "" : parentTag.getName(); + evl.handleExportingEvent("frame", pos + 1, fframes.size(), tagName); + } + int fframe = fframes.get(pos); + final Graphics2D g = (Graphics2D) job.getGraphics(pf); + //g.drawImage(img, 5, 5, img.getWidth(), img.getHeight(), null); - SerializableImage image = new SerializableImage((int) w + 1, (int) h + 1, SerializableImage.TYPE_INT_ARGB_PRE) { + SerializableImage image = new SerializableImage((int) w + 1, (int) h + 1, SerializableImage.TYPE_INT_ARGB_PRE) { - private Graphics2D compositeGraphics; + private Graphics2D compositeGraphics; - @Override - public Graphics getGraphics() { - if (compositeGraphics != null) { + @Override + public Graphics getGraphics() { + if (compositeGraphics != null) { + return compositeGraphics; + } + final Graphics2D parentGraphics = (Graphics2D) super.getGraphics(); + compositeGraphics = new DualPdfGraphics2D(parentGraphics, (PDFGraphics) g, existingFonts); return compositeGraphics; } - final Graphics2D parentGraphics = (Graphics2D) super.getGraphics(); - compositeGraphics = new DualPdfGraphics2D(parentGraphics, (PDFGraphics) g, existingFonts); - return compositeGraphics; + + @Override + public void fillTransparent() { + + } + + }; + //if (backGroundColor == null) { + // image.fillTransparent(); + int imgWidth = (int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1; + int imgHeight = (int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1; + if (!usesTransparency && fbackgroundColor != null) { + g.setComposite(AlphaComposite.Src); + g.setColor(fbackgroundColor); + g.fill(new Rectangle(imgWidth, imgHeight)); } - @Override - public void fillTransparent() { + RenderContext renderContext = new RenderContext(); + renderContext.cursorPosition = new Point(-1, -1); + renderContext.mouseButton = 0; + renderContext.stateUnderCursor = new ArrayList<>(); + try { + tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true); + } catch (Exception ex) { + ex.printStackTrace(); } + g.dispose(); - }; - //if (backGroundColor == null) { - // image.fillTransparent(); - int imgWidth = (int) (rect.getWidth() * zoom / SWF.unitDivisor) + 1; - int imgHeight = (int) (rect.getHeight() * zoom / SWF.unitDivisor) + 1; - if (!fusesTransparency && fbackgroundColor != null) { - g.setComposite(AlphaComposite.Src); - g.setColor(fbackgroundColor); - g.fill(new Rectangle(imgWidth, imgHeight)); + if (Thread.currentThread().isInterrupted()) { + return; + } + pos++; } - RenderContext renderContext = new RenderContext(); - renderContext.cursorPosition = new Point(-1, -1); - renderContext.mouseButton = 0; - renderContext.stateUnderCursor = new ArrayList<>(); - - try { - tim.toImage(fframe, fframe, renderContext, image, image, false, m, new Matrix(), m, null, zoom, true, new ExportRectangle(rect), m, true, Timeline.DRAW_MODE_ALL, 0, true); - } catch (Exception ex) { - ex.printStackTrace(); - } - g.dispose(); - - if (Thread.currentThread().isInterrupted()) { - return; - } - pos++; - } - - job.end(); - ret.add(f); - }, handler).run(); + job.end(); + ret.add(f); + }, handler).run(); + } } break; case AVI: - new RetryTask(() -> { - File f = new File(foutdir + File.separator + "frames.avi"); - makeAVI(frameImages, swf.frameRate, f, evl); - ret.add(f); - }, handler).run(); + for (File foutdir : foutdirs) { + frameImages.reset(); + new RetryTask(() -> { + File f = new File(foutdir + File.separator + "frames.avi"); + makeAVI(frameImages, swf.frameRate, f, evl); + ret.add(f); + }, handler).run(); + } break; } 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 7def04b68..3eff16887 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 @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode; import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings; import com.jpexs.decompiler.flash.helpers.BMPFile; @@ -38,8 +39,12 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.CopyOption; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; +import java.util.Set; import javax.imageio.ImageIO; /** @@ -118,7 +123,6 @@ public class ImageExporter { } }, handler).run(); - final File alphaBinFile = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + ".alpha.bin")); final File alphaPngFile = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + ".alpha.png")); if ((imageTag instanceof HasSeparateAlphaChannel) @@ -145,7 +149,26 @@ public class ImageExporter { }, handler).run(); } } - ret.add(file); + Set classNames = imageTag.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + "." + ImageHelper.getImageFormatString(fileFormat))); + File classAlphaPngFile = new File(outdir + File.separator + Helper.makeFileName(className + ".alpha.png")); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + if (alphaPngFile.exists()) { + Files.copy(alphaPngFile.toPath(), classAlphaPngFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + ret.add(classFile); + } + file.delete(); + if (alphaPngFile.exists()) { + alphaPngFile.delete(); + } + } else { + ret.add(file); + } if (Thread.currentThread().isInterrupted()) { break; 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 a47728f78..144e90f35 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 @@ -22,11 +22,11 @@ import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; import com.jpexs.decompiler.flash.exporters.modes.MorphShapeExportMode; -import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; import com.jpexs.decompiler.flash.exporters.morphshape.CanvasMorphShapeExporter; import com.jpexs.decompiler.flash.exporters.settings.MorphShapeExportSettings; import com.jpexs.decompiler.flash.helpers.BMPFile; @@ -53,6 +53,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -106,8 +108,9 @@ public class MorphShapeExporter { final File file = new File(outdir + File.separator + characterID + settings.getFileExtension()); final File fileStart = new File(outdir + File.separator + characterID + ".start" + settings.getFileExtension()); final File fileEnd = new File(outdir + File.separator + characterID + ".end" + settings.getFileExtension()); + MorphShapeTag mst = (MorphShapeTag) t; + new RetryTask(() -> { - MorphShapeTag mst = (MorphShapeTag) t; switch (settings.mode) { case SVG_START_END: try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fileStart))) { @@ -218,8 +221,42 @@ public class MorphShapeExporter { break; } }, handler).run(); - ret.add(file); - + + + Set classNames = mst.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + settings.getFileExtension())); + File classFileStart = new File(outdir + File.separator + Helper.makeFileName(className + ".start" + settings.getFileExtension())); + File classFileEnd = new File(outdir + File.separator + Helper.makeFileName(className + ".end" + settings.getFileExtension())); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + + if (fileStart.exists()) { + new RetryTask(() -> { + Files.copy(fileStart.toPath(), classFileStart.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + } + + if (fileEnd.exists()) { + new RetryTask(() -> { + Files.copy(fileEnd.toPath(), classFileEnd.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + } + } + file.delete(); + if (fileStart.exists()) { + fileStart.delete(); + } + if (fileEnd.exists()) { + fileEnd.delete(); + } + } else { + ret.add(file); + } + if (Thread.currentThread().isInterrupted()) { break; } 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 4046eed00..016244049 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 @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.RetryTask; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; import com.jpexs.decompiler.flash.exporters.settings.MovieExportSettings; import com.jpexs.decompiler.flash.flv.FLVOutputStream; @@ -40,11 +41,14 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * @@ -90,6 +94,20 @@ public class MovieExporter { } }, handler).run(); + Set classNames = videoStream.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ".flv")); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } + if (Thread.currentThread().isInterrupted()) { break; } 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 a2feeca5a..04c585c77 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 @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; @@ -50,6 +51,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -161,7 +164,20 @@ public class ShapeExporter { break; } }, handler).run(); - ret.add(file); + + Set classNames = st.getClassNames(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + settings.getFileExtension())); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } if (Thread.currentThread().isInterrupted()) { break; 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 6464d77cf..ca7b96582 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 @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.ReadOnlyTagList; import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings; import com.jpexs.decompiler.flash.flv.AUDIODATA; @@ -28,6 +29,7 @@ import com.jpexs.decompiler.flash.flv.FLVTAG; import com.jpexs.decompiler.flash.tags.DefineSoundTag; import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound; @@ -43,9 +45,13 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * @@ -86,32 +92,44 @@ public class SoundExporter { final SoundTag st = (SoundTag) t; - String ext = "wav"; + String ext = ".wav"; SoundFormat fmt = st.getSoundFormat(); switch (fmt.getNativeExportFormat()) { case MP3: if (settings.mode.hasMP3()) { - ext = "mp3"; + ext = ".mp3"; } break; case FLV: if (settings.mode.hasFlv()) { - ext = "flv"; + ext = ".flv"; } break; } if (settings.mode == SoundExportMode.FLV) { - ext = "flv"; + ext = ".flv"; } - final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName()) + "." + ext); + final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName()) + ext); new RetryTask(() -> { try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) { exportSound(os, st, settings.mode); } }, handler).run(); - ret.add(file); + Set classNames = (st instanceof CharacterTag) ? ((CharacterTag)st).getClassNames() : new HashSet<>(); + if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) { + for (String className : classNames) { + File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext)); + new RetryTask(() -> { + Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + },handler).run(); + ret.add(classFile); + } + file.delete(); + } else { + ret.add(file); + } if (Thread.currentThread().isInterrupted()) { break; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ShapeExportSettings.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ShapeExportSettings.java index 55e5c3f73..eda24543d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ShapeExportSettings.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/ShapeExportSettings.java @@ -48,7 +48,7 @@ public class ShapeExportSettings { case SWF: return ".swf"; default: - throw new Error("Unsupported morphshape export mode: " + mode); + throw new Error("Unsupported shape export mode: " + mode); } } } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index 48b59df43..ff65886a9 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -751,3 +751,6 @@ config.description.formatting.tab.size = Number of spaces per tab config.name.boxBlurPixelsLimit = Box blur filter pixels limit config.description.boxBlurPixelsLimit = Maximum number of pixels to calculate boxblur filter. The actual limit is this number multiplied by 10000. If the number of pixels is greater, then blurX and blurY is decreased. + +config.name.as3ExportNamesUseClassNamesOnly = Exported assets have names bases on classes only (AS3) +config.description.as3ExportNamesUseClassNamesOnly = Exported asset files (images, sound, ...) take names only from SymbolClass tag - their assigned classes. No character id is added. Also when multiple classes is assigned to same asset, it is exported multiple times. (For ActionScript 3 SWFs) diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties index bf84afac5..8b767368d 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties @@ -741,3 +741,6 @@ config.description.formatting.tab.size = Po\u010det mezer v tabel\u00e1toru config.name.boxBlurPixelsLimit = Limit pixel\u016f box blur filtru config.description.boxBlurPixelsLimit = Maxim\u00e1ln\u00ed po\u010det pixel\u016f pro v\u00fdpo\u010det boxblur filtru. Aktu\u00e1ln\u00ed limit je toto \u010d\u00edslo kr\u00e1t 10000. Pokud je po\u010det pixel\u016f v\u011bt\u0161\u00ed, je zmen\u0161en blurX, blurY. + +config.name.as3ExportNamesUseClassNamesOnly = Exportovan\u00e9 zdroje maj\u00ed n\u00e1zvy zalo\u017een\u00e9 pouze na n\u00e1zvech t\u0159\u00edd (AS3) +config.description.as3ExportNamesUseClassNamesOnly = Exportovan\u00e9 soubory zdroj\u016f (obr\u00e1zky, zvuky, ...) p\u0159eberou n\u00e1zvy z SymbolClass tagu - jejich p\u0159i\u0159azen\u00e9 t\u0159\u00eddy. Id charakteru nebude p\u0159id\u00e1no. Tak\u00e9 pokud bude v\u00edce t\u0159\u00edd p\u0159i\u0159azeno jednomu assetu, bude exportov\u00e1n v\u00edcekr\u00e1t. (Pro ActionScript 3 SWF soubory)