diff --git a/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java b/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java deleted file mode 100644 index f05817aab..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/FrameInfo.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import java.awt.Color; -import java.util.Map; - -/** - * - * @author JPEXS - */ -public class FrameInfo { - - public int maxDepth; - public Map layers; - public Color backgroundColor; - public Map characters; - public int frame; -} diff --git a/trunk/src/com/jpexs/decompiler/flash/Layer.java b/trunk/src/com/jpexs/decompiler/flash/Layer.java deleted file mode 100644 index 399f972f0..000000000 --- a/trunk/src/com/jpexs/decompiler/flash/Layer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010-2014 JPEXS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.jpexs.decompiler.flash; - -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.filters.FILTER; -import java.io.Serializable; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class Layer implements Serializable { - - public MATRIX matrix; - public String instanceName = null; - public ColorTransform colorTransForm = null; - public boolean cacheAsBitmap = false; - public int blendMode = 0; - public List filters = null; - public boolean isVisible = true; - public RGBA backGroundColor = null; - public int characterId = -1; - public int ratio = -1; - public int time = 0; - public boolean visible = true; - public int clipDepth = -1; -} diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index b0c288fc6..1af376a19 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -91,6 +91,9 @@ import com.jpexs.decompiler.flash.tags.base.RemoveTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem; import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem; import com.jpexs.decompiler.flash.treeitems.FrameNodeItem; @@ -160,13 +163,14 @@ import java.util.logging.Logger; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; import javax.imageio.ImageIO; +import com.jpexs.decompiler.flash.timeline.Timelined; /** * Class representing SWF file * * @author JPEXS */ -public final class SWF implements TreeItem { +public final class SWF implements TreeItem,Timelined { /** * Default version of SWF file format @@ -229,6 +233,16 @@ public final class SWF implements TreeItem { public Map sourceFontsMap = new HashMap<>(); public static final double unitDivisor = 20; + private Timeline timeline; + + @Override + public Timeline getTimeline(){ + if(timeline == null){ + timeline = new Timeline(this); + } + return timeline; + } + /** * Gets all tags with specified id * @@ -2206,20 +2220,18 @@ public final class SWF implements TreeItem { return ret; } - public static SerializableImage frameToImage(int containerId, int frame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation, ColorTransform colorTransform) { - String key = "frame_" + frame + "_" + containerId + "_" + allTags.get(0).getSwf().hashCode(); + public static SerializableImage frameToImageGet(Timeline timeline,int frame, RECT displayRect, Stack visited, Matrix transformation, ColorTransform colorTransform) { + String key = "frame_" + frame + "_" + timeline.id + "_" + timeline.swf.hashCode(); SerializableImage image = getFromCache(key); if (image != null) { return image; } - List frameInfos = getFrameInfo(frame, frame, allTags, controlTags, totalFrameCount); - if (frameInfos.isEmpty()) { + + if (timeline.frames.isEmpty()) { return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB); } - FrameInfo fi = frameInfos.get(0); - RECT rect = displayRect; image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); @@ -2230,143 +2242,16 @@ public final class SWF implements TreeItem { g.fillRect(0, 0, image.getWidth(), image.getHeight()); Matrix m = new Matrix(); m.translate(-rect.Xmin, -rect.Ymin); - frameToImage(containerId, fi.maxDepth, fi.layers, fi.backgroundColor, fi.characters, fi.frame, allTags, controlTags, displayRect, visited, image, m, colorTransform); + frameToImage(timeline, frame, displayRect, visited, image, m, colorTransform); putToCache(key, image); return image; } - private static List getFrameInfo(int startFrame, int stopFrame, List allTags, List controlTags, int totalFrameCount) { - List ret = new ArrayList<>(); - if (startFrame > stopFrame) { - return ret; - } - if (totalFrameCount == 0) { - return ret; - } + - while (startFrame >= totalFrameCount) { - startFrame -= totalFrameCount; - } - - while (stopFrame >= totalFrameCount) { - stopFrame -= totalFrameCount; - } - - Map characters = new HashMap<>(); - for (Tag t : allTags) { - if (t instanceof CharacterTag) { - CharacterTag ch = (CharacterTag) t; - characters.put(ch.getCharacterId(), ch); - } - } - - Map layers = new HashMap<>(); - - int maxDepth = 0; - int f = 0; - Color backgroundColor = new Color(0, 0, 0, 0); - for (Tag t : controlTags) { - if (t instanceof SetBackgroundColorTag) { - SetBackgroundColorTag c = (SetBackgroundColorTag) t; - backgroundColor = new Color(c.backgroundColor.red, c.backgroundColor.green, c.backgroundColor.blue); - } - - if (t instanceof PlaceObjectTypeTag) { - PlaceObjectTypeTag po = (PlaceObjectTypeTag) t; - int depth = po.getDepth(); - if (depth > maxDepth) { - maxDepth = depth; - } - - if (!layers.containsKey(depth)) { - layers.put(depth, new Layer()); - } - Layer layer = layers.get(depth); - int characterId = po.getCharacterId(); - if (characterId != -1) { - layer.characterId = characterId; - } - layer.visible = po.isVisible(); - if (po.flagMove()) { - MATRIX matrix2 = po.getMatrix(); - if (matrix2 != null) { - layer.matrix = matrix2; - } - String instanceName = po.getInstanceName(); - if (instanceName != null) { - layer.instanceName = instanceName; - } - ColorTransform colorTransForm = po.getColorTransform(); - if (colorTransForm != null) { - layer.colorTransForm = colorTransForm; - } - if (po.cacheAsBitmap()) { - layer.cacheAsBitmap = true; - } - int blendMode = po.getBlendMode(); - if (blendMode != 0) { - layer.blendMode = blendMode; - } - List filters = po.getFilters(); - if (filters != null) { - layer.filters = filters; - } - int ratio = po.getRatio(); - if (ratio != -1) { - layer.ratio = ratio; - } - int clipDepth = po.getClipDepth(); - if (clipDepth != -1) { - layer.clipDepth = clipDepth; - } - } else { - layer.matrix = po.getMatrix(); - layer.instanceName = po.getInstanceName(); - layer.colorTransForm = po.getColorTransform(); - layer.cacheAsBitmap = po.cacheAsBitmap(); - layer.blendMode = po.getBlendMode(); - layer.filters = po.getFilters(); - layer.ratio = po.getRatio(); - layer.clipDepth = po.getClipDepth(); - layer.time = 0; - } - } - - if (t instanceof RemoveTag) { - RemoveTag rt = (RemoveTag) t; - layers.remove(rt.getDepth()); - - } - if (t instanceof ShowFrameTag) { - for (Layer l : layers.values()) { - l.time++; - } - if ((f >= startFrame) && (f <= stopFrame)) { - FrameInfo fi = new FrameInfo(); - fi.maxDepth = maxDepth; - fi.layers = layers; - fi.backgroundColor = backgroundColor; - fi.characters = characters; - fi.frame = f; - ret.add(fi); - if (f < stopFrame) { - layers = Helper.deepCopy(layers); - } - } - f++; - if (f > stopFrame) { - break; - } - } - } - - return ret; - } - - public static void framesToImage(int containerId, List ret, int startFrame, int stopFrame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation, ColorTransform colorTransform) { - List frameInfos = getFrameInfo(startFrame, stopFrame, allTags, controlTags, totalFrameCount); + public static void framesToImage(Timeline timeline, List ret, int startFrame, int stopFrame, RECT displayRect, int totalFrameCount, Stack visited, Matrix transformation, ColorTransform colorTransform) { RECT rect = displayRect; - for (FrameInfo fi : frameInfos) { + for (int f=0;f layers, Color backgroundColor, Map characters, int frame, List allTags, List controlTags, RECT displayRect, Stack visited, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { + public static void frameToImage(Timeline timeline, int frame,RECT displayRect, Stack visited, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { float unzoom = (float) SWF.unitDivisor; - + Frame frameObj = timeline.frames.get(frame); Graphics2D g = (Graphics2D) image.getGraphics(); - g.setPaint(backgroundColor); + g.setPaint(frameObj.backgroundColor.toColor()); g.fill(new Rectangle(image.getWidth(), image.getHeight())); g.setTransform(transformation.toTransform()); List clips = new ArrayList<>(); List prevClips = new ArrayList<>(); + - for (int i = 1; i <= maxDepth; i++) { - + for (int i = 1; i <= timeline.getMaxDepth(); i++) { for (int c = 0; c < clips.size(); c++) { if (clips.get(c).clipDepth == i) { g.setClip(prevClips.get(c)); @@ -2412,17 +2297,17 @@ public final class SWF implements TreeItem { clips.remove(c); } } - if (!layers.containsKey(i)) { + if (!frameObj.layers.containsKey(i)) { continue; } - Layer layer = layers.get(i); - if (!characters.containsKey(layer.characterId)) { + DepthState layer = frameObj.layers.get(i); + if (!timeline.characters.containsKey(layer.characterId)) { continue; } - if (!layer.visible) { + if (!layer.isVisible) { continue; } - CharacterTag character = characters.get(layer.characterId); + CharacterTag character = timeline.characters.get(layer.characterId); Matrix mat = new Matrix(layer.matrix); mat = mat.preConcatenate(transformation); @@ -2440,10 +2325,10 @@ public final class SWF implements TreeItem { DrawableTag drawable = (DrawableTag) character; SerializableImage img; Matrix drawMatrix = new Matrix(); - int dframe = 1 + layer.time % drawable.getNumFrames(); + int dframe = 0 + layer.time % drawable.getNumFrames(); if (drawable instanceof BoundedTag) { BoundedTag bounded = (BoundedTag) drawable; - RECT boundRect = bounded.getRect(characters, new Stack()); + RECT boundRect = bounded.getRect(timeline.characters, new Stack()); ExportRectangle rect = new ExportRectangle(boundRect); rect = mat.transform(rect); Matrix m = mat.clone(); @@ -2486,11 +2371,11 @@ public final class SWF implements TreeItem { gr.setComposite(AlphaComposite.Src); gr.setColor(new Color(0, 0, 0, 0f)); gr.fillRect(0, 0, img.getWidth(), img.getHeight()); - drawable.toImage(dframe, layer.ratio, allTags, characters, visited, img, m, clrTrans); + drawable.toImage(dframe, layer.ratio, timeline.swf.tags, timeline.characters, visited, img, m, clrTrans); } else if (drawable instanceof FontTag) { // only DefineFont tags - FontTag fontTag = (FontTag) drawable; - img = fontTag.toImage(dframe, layer.ratio, allTags, characters, visited, transformation, clrTrans); + FontTag fontTag = (FontTag) drawable; + img = fontTag.toImage(dframe, layer.ratio, timeline.swf.tags, timeline.characters, visited, transformation, clrTrans); } else { throw new Error("Unsupported drawable."); } @@ -2508,7 +2393,7 @@ public final class SWF implements TreeItem { drawMatrix.translateX /= unzoom; drawMatrix.translateY /= unzoom; AffineTransform trans = drawMatrix.toTransform(); - + switch (layer.blendMode) { case 0: case 1: @@ -2590,7 +2475,7 @@ public final class SWF implements TreeItem { BoundedTag b = (BoundedTag) character; g.setPaint(new Color(255, 255, 255, 128)); g.setComposite(BlendComposite.Invert); - RECT r = b.getRect(characters, visited); + RECT r = b.getRect(timeline.characters, visited); int div = (int) unzoom; g.drawString(character.toString(), r.Xmin / div + 3, r.Ymin / div + 15); g.draw(new Rectangle(r.Xmin / div, r.Ymin / div, r.getWidth() / div, r.getHeight() / div)); @@ -2602,14 +2487,6 @@ public final class SWF implements TreeItem { g.setTransform(AffineTransform.getScaleInstance(1, 1)); } - public static void frameToImage(int containerId, int frame, List allTags, List controlTags, RECT displayRect, int totalFrameCount, Stack visited, SerializableImage image, Matrix transformation, ColorTransform colorTransform) { - List frameInfos = getFrameInfo(frame, frame, allTags, controlTags, totalFrameCount); - if (!frameInfos.isEmpty()) { - FrameInfo fi = frameInfos.get(0); - frameToImage(containerId, fi.maxDepth, fi.layers, fi.backgroundColor, fi.characters, fi.frame, allTags, controlTags, displayRect, visited, image, transformation, colorTransform); - } - } - public void removeTagFromTimeline(Tag toRemove, List timeline) { int characterId = 0; if (toRemove instanceof CharacterTag) { diff --git a/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java index d97cbcee5..1866f2362 100644 --- a/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -168,7 +168,7 @@ public class Configuration { public static final ConfigurationItem locale = null; @ConfigurationDefaultString("_loc%d_") public static final ConfigurationItem registerNameFormat = null; - @ConfigurationDefaultInt(10) + @ConfigurationDefaultInt(8) public static final ConfigurationItem maxRecentFileCount = null; public static final ConfigurationItem recentFiles = null; public static final ConfigurationItem fontPairing = null; @@ -338,7 +338,7 @@ public class Configuration { recentFilesArray.remove(idx); } recentFilesArray.add(path); - while (recentFilesArray.size() > maxRecentFileCount.get()) { + while (recentFilesArray.size() >= maxRecentFileCount.get()) { recentFilesArray.remove(0); } recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 893e49520..34bd20a74 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -36,9 +36,11 @@ import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; +import java.util.Map; import java.util.Stack; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.ExecutorService; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JColorChooser; @@ -61,7 +63,7 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis private SWF swf; private HashMap characters; private boolean loaded; - + @Override public void setBackground(Color bg) { if (label != null) { @@ -162,7 +164,7 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis setImage(img); } return; - } + } play(); } @@ -212,19 +214,16 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis } } - private void drawFrame() { - if (drawable == null) { - return; - } - Matrix mat = new Matrix(); - mat.translateX = swf.displayRect.Xmin; - mat.translateY = swf.displayRect.Ymin; + private static SerializableImage getFrame(SWF swf,int frame,DrawableTag drawable,Map characters){ String key = "drawable_" + frame + "_" + drawable.hashCode(); SerializableImage img = SWF.getFromCache(key); if (img == null) { if (drawable instanceof BoundedTag) { BoundedTag bounded = (BoundedTag) drawable; RECT rect = bounded.getRect(characters, new Stack()); + if(rect == null){ //??? Why? + rect = new RECT(0,0,1,1); + } SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1, (int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB); //Make all pixels transparent @@ -243,7 +242,17 @@ public final class ImagePanel extends JPanel implements ActionListener, FlashDis } SWF.putToCache(key, img); } - ImageIcon icon = new ImageIcon(img.getBufferedImage()); + return img; + } + + private void drawFrame() { + if (drawable == null) { + return; + } + Matrix mat = new Matrix(); + mat.translateX = swf.displayRect.Xmin; + mat.translateY = swf.displayRect.Ymin; + ImageIcon icon = new ImageIcon(getFrame(swf,frame,drawable,characters).getBufferedImage()); label.setIcon(icon); } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 9e094fbc9..80fe94e03 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -94,6 +94,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; import com.jpexs.decompiler.flash.tags.text.ParseException; +import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.treeitems.FrameNodeItem; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.treenodes.ContainerNode; @@ -2466,13 +2467,15 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec int containerId = 0; RECT rect = swf.displayRect; int totalFrameCount = swf.frameCount; + Timeline timeline=swf.getTimeline(); if (fn.getParent() instanceof DefineSpriteTag) { controlTags = ((DefineSpriteTag) fn.getParent()).subTags; containerId = ((DefineSpriteTag) fn.getParent()).spriteId; rect = ((DefineSpriteTag) fn.getParent()).getRect(swf.characters, new Stack()); totalFrameCount = ((DefineSpriteTag) fn.getParent()).frameCount; + timeline = ((DefineSpriteTag)fn.getParent()).getTimeline(); } - previewImagePanel.setImage(SWF.frameToImage(containerId, fn.getFrame() - 1, swf.tags, controlTags, rect, totalFrameCount, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform())); + previewImagePanel.setImage(SWF.frameToImageGet(timeline, fn.getFrame() - 1, rect, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform())); } else if (((tagObj instanceof FrameNodeItem) && ((FrameNodeItem) tagObj).isDisplayed()) || ((tagObj instanceof CharacterTag) || (tagObj instanceof FontTag)) && (tagObj instanceof Tag)) { ((CardLayout) viewerCards.getLayout()).show(viewerCards, FLASH_VIEWER_CARD); createAndShowTempSwf(tagObj); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java index 8e395dc44..31112d45f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviewPanel.java @@ -71,7 +71,7 @@ public class SWFPreviewPanel extends JPanel implements FlashDisplay { @Override public void run() { buffering.setVisible(true); - SWF.framesToImage(0, frameImages, 0, swf.frameCount - 1, swf.tags, swf.tags, swf.displayRect, swf.frameCount, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); + SWF.framesToImage(swf.getTimeline(), frameImages, 0, swf.frameCount - 1, swf.displayRect, swf.frameCount, new Stack(), Matrix.getScaleInstance(1 / SWF.unitDivisor), new ColorTransform()); buffering.setVisible(false); } }.start(); diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index 751e5c0d9..c95c9985b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -16,7 +16,6 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.Layer; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; @@ -29,6 +28,10 @@ import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.Container; import com.jpexs.decompiler.flash.tags.base.ContainerItem; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; import com.jpexs.decompiler.flash.types.BUTTONRECORD; import com.jpexs.decompiler.flash.types.BasicType; @@ -60,7 +63,7 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class DefineButton2Tag extends CharacterTag implements Container, BoundedTag, ButtonTag { +public class DefineButton2Tag extends CharacterTag implements Container, BoundedTag, ButtonTag, Timelined { /** * ID for this character @@ -86,6 +89,8 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded public List actions = new ArrayList<>(); public static final int ID = 34; + private Timeline timeline; + @Override public int getCharacterId() { return buttonId; @@ -258,26 +263,10 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded return; } visited.push(buttonId); - HashMap layers = new HashMap<>(); - int maxDepth = 0; - for (BUTTONRECORD r : this.characters) { - if (r.buttonStateUp) { - Layer layer = new Layer(); - layer.colorTransForm = r.colorTransform; - layer.blendMode = r.blendMode; - layer.filters = r.filterList; - layer.matrix = r.placeMatrix; - layer.characterId = r.characterId; - if (r.placeDepth > maxDepth) { - maxDepth = r.placeDepth; - } - layers.put(r.placeDepth, layer); - } - } visited.pop(); RECT displayRect = getRect(characters, visited); visited.push(buttonId); - SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, image, transformation, colorTransform); + SWF.frameToImage(getTimeline(), frame, displayRect, visited, image, transformation, colorTransform); } @Override @@ -290,4 +279,31 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded public int getNumFrames() { return 1; } + + @Override + public Timeline getTimeline() { + if (timeline != null) { + return timeline; + } + timeline = new Timeline(swf, new ArrayList(), buttonId); + + int maxDepth = 0; + Frame fr = new Frame(); + for (BUTTONRECORD r : this.characters) { + if (r.buttonStateUp) { + DepthState layer = new DepthState(); + layer.colorTransForm = r.colorTransform; + layer.blendMode = r.blendMode; + layer.filters = r.filterList; + layer.matrix = r.placeMatrix; + layer.characterId = r.characterId; + if (r.placeDepth > maxDepth) { + maxDepth = r.placeDepth; + } + fr.layers.put(r.placeDepth, layer); + } + } + timeline.frames.add(fr); + return timeline; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 1fa905ed9..66d3b1317 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -1,23 +1,22 @@ /* * Copyright (C) 2010-2014 JPEXS - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.DisassemblyListener; -import com.jpexs.decompiler.flash.Layer; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; @@ -32,6 +31,10 @@ import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; +import com.jpexs.decompiler.flash.timeline.DepthState; +import com.jpexs.decompiler.flash.timeline.Frame; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BUTTONRECORD; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; @@ -64,7 +67,7 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedTag, ButtonTag { +public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedTag, ButtonTag, Timelined { /** * ID for this character @@ -89,6 +92,8 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT } private final long hdrSize; + private Timeline timeline; + @Override public List getRecords() { return characters; @@ -279,26 +284,11 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT return; } visited.push(buttonId); - HashMap layers = new HashMap<>(); - int maxDepth = 0; - for (BUTTONRECORD r : this.characters) { - if (r.buttonStateUp) { - Layer layer = new Layer(); - layer.colorTransForm = r.colorTransform; - layer.blendMode = r.blendMode; - layer.filters = r.filterList; - layer.matrix = r.placeMatrix; - layer.characterId = r.characterId; - if (r.placeDepth > maxDepth) { - maxDepth = r.placeDepth; - } - layers.put(r.placeDepth, layer); - } - } + visited.pop(); RECT displayRect = getRect(characters, visited); visited.push(buttonId); - SWF.frameToImage(buttonId, maxDepth, layers, new Color(0, 0, 0, 0), characters, 1, tags, tags, displayRect, visited, image, transformation, colorTransform); + SWF.frameToImage(getTimeline(), frame, displayRect, visited, image, transformation, colorTransform); visited.pop(); } @@ -332,4 +322,32 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT public String removePrefixAndSuffix(String source) { return source; } + + @Override + public Timeline getTimeline() { + if (timeline != null) { + return timeline; + } + timeline = new Timeline(swf, new ArrayList(), buttonId); + + int maxDepth = 0; + Frame fr = new Frame(); + for (BUTTONRECORD r : this.characters) { + if (r.buttonStateUp) { + DepthState layer = new DepthState(); + layer.colorTransForm = r.colorTransform; + layer.blendMode = r.blendMode; + layer.filters = r.filterList; + layer.matrix = r.placeMatrix; + layer.characterId = r.characterId; + if (r.placeDepth > maxDepth) { + maxDepth = r.placeDepth; + } + fr.layers.put(r.placeDepth, layer); + } + } + timeline.frames.add(fr); + return timeline; + } + } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 8197fb262..c32d59a97 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -29,6 +29,8 @@ import com.jpexs.decompiler.flash.tags.base.Container; import com.jpexs.decompiler.flash.tags.base.ContainerItem; import com.jpexs.decompiler.flash.tags.base.DrawableTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.timeline.Timeline; +import com.jpexs.decompiler.flash.timeline.Timelined; import com.jpexs.decompiler.flash.types.BasicType; import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; @@ -52,7 +54,7 @@ import java.util.Stack; /** * Defines a sprite character */ -public class DefineSpriteTag extends CharacterTag implements Container, BoundedTag, DrawableTag { +public class DefineSpriteTag extends CharacterTag implements Container, BoundedTag, DrawableTag, Timelined { /** * Character ID of sprite @@ -71,6 +73,16 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT public static final int ID = 39; + private Timeline timeline; + + @Override + public Timeline getTimeline() { + if (timeline == null) { + timeline = new Timeline(swf, subTags, spriteId); + } + return timeline; + } + @Override public int getCharacterId() { return spriteId; @@ -283,7 +295,7 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT } RECT rect = getRect(characters, visited); visited.push(spriteId); - SWF.frameToImage(spriteId, frame, tags, subTags, rect, frameCount, visited, image, transformation, colorTransform); + SWF.frameToImage(getTimeline(), frame, rect, visited, image, transformation, colorTransform); visited.pop(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java index 101e8e04e..0a58adadb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -42,6 +42,8 @@ public class DepthState { public CLIPACTIONS clipActions = null; public int ratio; public boolean key = false; + public int clipDepth; + public int time = 0; public DepthState() { @@ -59,5 +61,7 @@ public class DepthState { backGroundColor = obj.backGroundColor; clipActions = obj.clipActions; ratio = obj.ratio; + clipDepth = obj.clipDepth; + time = obj.time+1; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java index 23dcf5ed7..286a8b897 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Frame.java @@ -17,6 +17,8 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.types.RGB; +import com.jpexs.decompiler.flash.types.RGBA; import java.util.HashMap; import java.util.Map; @@ -28,6 +30,7 @@ public class Frame { public Map layers = new HashMap<>(); public DoActionTag action; + public RGB backgroundColor = new RGBA(0,0,0,0); public Frame() { diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java index c8655e1fb..03821b4ce 100644 --- a/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -18,8 +18,10 @@ package com.jpexs.decompiler.flash.timeline; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.RemoveTag; import com.jpexs.decompiler.flash.types.CLIPACTIONS; @@ -27,7 +29,9 @@ import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.filters.FILTER; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -36,6 +40,9 @@ import java.util.List; public class Timeline { public List frames = new ArrayList<>(); + public int id; + public Map characters = new HashMap<>(); + public SWF swf; public Timeline() { } @@ -56,9 +63,24 @@ public class Timeline { return frames.size(); } - public Timeline(SWF swf) { + public Timeline(SWF swf){ + this(swf,swf.tags,0); + } + + public Timeline(SWF swf,List tags,int id) { + this.id =id; + this.swf = swf; Frame frame = new Frame(); for (Tag t : swf.tags) { + if(t instanceof CharacterTag){ + CharacterTag c=(CharacterTag)t; + characters.put(c.getCharacterId(), c); + } + } + for (Tag t : tags) { + if(t instanceof SetBackgroundColorTag){ + frame.backgroundColor = ((SetBackgroundColorTag)t).backgroundColor; + } if (t instanceof PlaceObjectTypeTag) { PlaceObjectTypeTag po = (PlaceObjectTypeTag) t; int depth = po.getDepth(); @@ -103,6 +125,10 @@ public class Timeline { if (ratio2 > -1) { fl.ratio = ratio2; } + int clipDepth2 = po.getClipDepth(); + if(clipDepth2>-1){ + fl.clipDepth = clipDepth2; + } } else { fl.matrix = po.getMatrix(); fl.instanceName = po.getInstanceName(); @@ -112,6 +138,7 @@ public class Timeline { fl.filters = po.getFilters(); fl.ratio = po.getRatio(); fl.clipActions = po.getClipActions(); + fl.clipDepth = po.getClipDepth(); } fl.key = true; } diff --git a/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java b/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java new file mode 100644 index 000000000..c37772d4d --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/timeline/Timelined.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2014 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.jpexs.decompiler.flash.timeline; + +/** + * + * @author JPEXS + */ +public interface Timelined { + public Timeline getTimeline(); +}