diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 88a648464..80736b488 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -160,6 +160,7 @@ import java.util.Date; import java.util.EmptyStackException; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -262,6 +263,9 @@ public final class SWF implements SWFContainerItem, Timelined { @Internal private Map characters; + @Internal + private Map> dependentCharacters; + @Internal private List abcList; @@ -388,6 +392,71 @@ public final class SWF implements SWFContainerItem, Timelined { return characters; } + public Map> getDependentCharacters() { + if (dependentCharacters == null) { + synchronized (this) { + if (dependentCharacters == null) { + Map> dep = new HashMap<>(); + for (Tag tag : tags) { + if (tag instanceof CharacterTag) { + int characterId = ((CharacterTag) tag).getCharacterId(); + Set needed = new HashSet<>(); + tag.getNeededCharacters(needed); + for (Integer needed1 : needed) { + Set s = dep.get(needed1); + if (s == null) { + s = new HashSet<>(); + dep.put(needed1, s); + } + + s.add(characterId); + } + } + } + + dependentCharacters = dep; + } + } + } + + return dependentCharacters; + } + + public Set getDependentCharacters(int characterId) { + Set visited = new HashSet<>(); + + Set dependents2 = new LinkedHashSet<>(); + Set deps = getDependentCharacters().get(characterId); + if (deps != null) { + dependents2.addAll(deps); + } + + while (visited.size() != dependents2.size()) { + for (int chId : dependents2) { + if (!visited.contains(chId)) { + visited.add(chId); + if (getCharacters().containsKey(chId)) { + deps = getDependentCharacters().get(chId); + if (deps != null) { + dependents2.addAll(deps); + } + + break; + } + } + } + } + + Set dependents = new LinkedHashSet<>(); + for (Integer chId : dependents2) { + if (getCharacters().containsKey(chId)) { + dependents.add(chId); + } + } + + return dependents; + } + public CharacterTag getCharacter(int characterId) { return getCharacters().get(characterId); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java index e08ae44b6..1f5706d12 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/Tag.java @@ -660,17 +660,14 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable { tagInfo.addInfo("general", "neededCharacters", Helper.joinStrings(needed, ", ")); } - /* todo: add dependent characters, getDependentCharacters method is currently slow - if (this instanceof CharacterTag) { - Set dependent = new LinkedHashSet<>(); - int characterId = ((CharacterTag) this).getCharacterId(); - dependent.add(characterId); - getDependentCharacters(dependent); - dependent.remove(characterId); - - if (dependent.size() > 0) { - tagInfo.addInfo("general", "dependentCharacters", Helper.joinStrings(dependent, ", ")); - } - }*/ + if (this instanceof CharacterTag) { + int characterId = ((CharacterTag) this).getCharacterId(); + Set dependent = swf.getDependentCharacters(characterId); + if (dependent != null) { + if (dependent.size() > 0) { + tagInfo.addInfo("general", "dependentCharacters", Helper.joinStrings(dependent, ", ")); + } + } + } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 664581e1e..0da7e08fe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -117,6 +117,7 @@ public class Timeline { ensureInitialized(); frames.add(frame); maxDepth = getMaxDepthInternal(); + calculateMaxDepthFrames(); } public AS2Package getAS2RootPackage() { @@ -343,14 +344,7 @@ public class Timeline { // todo: enable again after TweenDetector.detectRanges implemented //detectTweens(); - for (int d = 1; d <= maxDepth; d++) { - for (int f = frames.size() - 1; f >= 0; f--) { - if (frames.get(f).layers.get(d) != null) { - depthMaxFrame.put(d, f + 1); - break; - } - } - } + calculateMaxDepthFrames(); createASPackages(); if (parentTag == null) { @@ -397,6 +391,18 @@ public class Timeline { } } + private void calculateMaxDepthFrames() { + depthMaxFrame.clear(); + for (int d = 1; d <= maxDepth; d++) { + for (int f = frames.size() - 1; f >= 0; f--) { + if (frames.get(f).layers.get(d) != null) { + depthMaxFrame.put(d, f + 1); + break; + } + } + } + } + private void createASPackages() { for (ASMSource asm : asmSources) { if (asm instanceof DoInitActionTag) { diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 69ea5f517..d50eef6f1 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -329,7 +329,7 @@ public class CommandLineArgumentParser { out.println(" ...Converts the XML to SWF file"); } - if (filter == null || filter.equals("proxy")) { + if (filter == null || filter.equals("extract")) { out.println(" " + (cnt++) + ") -extract [-o |] [nocheck] [(all|biggest|smallest|first|last)]"); out.println(" ...Extracts SWF files from ZIP or other binary files"); out.println(" ...-o parameter should contain a file path when \"biggest\" or \"first\" parameter is specified"); @@ -341,7 +341,7 @@ public class CommandLineArgumentParser { out.println(" ...Renames the invalid identifiers in and save it to "); } - if (filter == null || filter.equals("proxy")) { + if (filter == null || filter.equals("config")) { out.println(" " + (cnt++) + ") -config key=value[,key2=value2][,key3=value3...] [other parameters]"); out.print(" ...Sets configuration values. "); if (!webHelp) { @@ -407,8 +407,8 @@ public class CommandLineArgumentParser { } if (filter == null || filter.equals("replacecharacterid")) { - out.println(" " + (cnt++) + ") -replaceCharacterId ,,,... or"); - out.println(" " + (cnt++) + ") -replaceCharacterId (pack|sort)"); + out.println(" " + (cnt++) + ") -replaceCharacterId ,,,... or"); + out.println(" " + (cnt++) + ") -replaceCharacterId (pack|sort)"); out.println(" ...replaces the character id with "); out.println(" ...pack: removes the spaces between the character ids (1,4,3 => 1,3,2)"); out.println(" ...sort: assigns increasing IDs to the chatacter tags + pack (1,4,3 => 1,2,3)"); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 1adaf86d5..db2205126 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -2847,8 +2847,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se final SWF swf = getCurrentSwf(); if (swf != null) { TreeItem item = tagTree.getCurrentTreeItem(); - if (item instanceof DefineSpriteTag) { - timelineViewPanel.setTimelined((DefineSpriteTag) item); + if (item instanceof TagScript) { + item = ((TagScript) item).getTag(); + } + if (item instanceof Timelined) { + timelineViewPanel.setTimelined((Timelined) item); } else { timelineViewPanel.setTimelined(swf); }