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 e9b32696e..385a7cc7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -40,7 +40,6 @@ import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionGraphSource; import com.jpexs.decompiler.flash.action.ActionList; @@ -297,6 +296,9 @@ public final class SWF implements SWFContainerItem, Timelined { @Internal private volatile Map characters; + @Internal + private volatile Map> characterIdTags; + @Internal private volatile Map> dependentCharacters; @@ -363,6 +365,7 @@ public final class SWF implements SWFContainerItem, Timelined { public void updateCharacters() { characters = null; + characterIdTags = null; } public void clearTagSwfs() { @@ -426,8 +429,10 @@ public final class SWF implements SWFContainerItem, Timelined { synchronized (this) { if (characters == null) { Map chars = new HashMap<>(); - parseCharacters(getTags(), chars); + Map> charIdtags = new HashMap<>(); + parseCharacters(getTags(), chars, charIdtags); characters = Collections.unmodifiableMap(chars); + characterIdTags = Collections.unmodifiableMap(charIdtags); } } } @@ -435,6 +440,14 @@ public final class SWF implements SWFContainerItem, Timelined { return characters; } + public List getCharacterIdTags(int characterId) { + if (characterIdTags == null) { + getCharacters(); + } + + return characterIdTags.get(characterId); + } + public Map> getDependentCharacters() { if (dependentCharacters == null) { synchronized (this) { @@ -725,20 +738,28 @@ public final class SWF implements SWFContainerItem, Timelined { } } - private void parseCharacters(Iterable list, Map characters) { + private void parseCharacters(Iterable list, Map characters, Map> characterIdTags) { for (Tag t : list) { - if (t instanceof CharacterTag) { - int characterId = ((CharacterTag) t).getCharacterId(); - if (characters.containsKey(characterId)) { - logger.log(Level.SEVERE, "SWF already contains characterId={0}", characterId); - } + if (t instanceof CharacterIdTag) { + int characterId = ((CharacterIdTag) t).getCharacterId(); + if (t instanceof CharacterTag) { + if (characters.containsKey(characterId)) { + logger.log(Level.SEVERE, "SWF already contains characterId={0}", characterId); + } - if (characterId != 0) { - characters.put(characterId, (CharacterTag) t); + if (characterId != 0) { + characters.put(characterId, (CharacterTag) t); + characterIdTags.put(characterId, new ArrayList<>()); + } + } else { + if (characterIdTags.containsKey(characterId)) { + characterIdTags.get(characterId).add((CharacterIdTag) t); + } } } + if (t instanceof DefineSpriteTag) { - parseCharacters(((DefineSpriteTag) t).getTags(), characters); + parseCharacters(((DefineSpriteTag) t).getTags(), characters, characterIdTags); } } } @@ -2482,6 +2503,7 @@ public final class SWF implements SWFContainerItem, Timelined { public void clearAllCache() { characters = null; + characterIdTags = null; abcList = null; timeline = null; clearReadOnlyListCache(); @@ -3194,15 +3216,15 @@ public final class SWF implements SWFContainerItem, Timelined { timelined.setModified(true); timelined.resetTimeline(); } else // timeline should be always the swf here - if (removeDependencies) { - removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline()); + if (removeDependencies) { + removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline()); + timelined.setModified(true); + } else { + boolean modified = removeTagFromTimeline(tag, timelined.getTimeline()); + if (modified) { timelined.setModified(true); - } else { - boolean modified = removeTagFromTimeline(tag, timelined.getTimeline()); - if (modified) { - timelined.setModified(true); - } } + } } @Override @@ -3852,7 +3874,7 @@ public final class SWF implements SWFContainerItem, Timelined { String mainClassName = null; //currentDomain,preloader /*double width = 0; - double height = 0; + double height = 0; */ for (NameValuePair nvp : no.pairs) { if (nvp.name instanceof StringAVM2Item) { @@ -3883,11 +3905,11 @@ public final class SWF implements SWFContainerItem, Timelined { } break; /*case "width": - width = Double.parseDouble("" + nvp.value.getResult()); - break; - case "height": - height = Double.parseDouble("" + nvp.value.getResult()); - break;*/ + width = Double.parseDouble("" + nvp.value.getResult()); + break; + case "height": + height = Double.parseDouble("" + nvp.value.getResult()); + break;*/ case "mainClassName": mainClassName = "" + nvp.value.getResult(); break; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index 568984bc0..517c58f87 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -166,13 +166,6 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer { return actions; } - @Override - public void getNeededCharacters(Set needed) { - for (BUTTONRECORD r : characters) { - needed.add(r.characterId); - } - } - @Override public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { boolean modified = false; @@ -282,7 +275,6 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer { if (r.buttonStateHitTest) { frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false)); } - } timeline.addFrame(frameUp); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java index 923d2a298..d15f44c0d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonSoundTag.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; +import java.util.Set; /** * @@ -139,4 +140,20 @@ public class DefineButtonSoundTag extends Tag implements CharacterIdTag { public void setCharacterId(int characterId) { this.buttonId = characterId; } + + @Override + public void getNeededCharacters(Set needed) { + if (buttonSoundChar0 != 0) { + needed.add(buttonSoundChar0); + } + if (buttonSoundChar1 != 0) { + needed.add(buttonSoundChar1); + } + if (buttonSoundChar2 != 0) { + needed.add(buttonSoundChar2); + } + if (buttonSoundChar3 != 0) { + needed.add(buttonSoundChar3); + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 073cffd80..b5ebbd2a3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -219,13 +219,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData()); } - @Override - public void getNeededCharacters(Set needed) { - for (BUTTONRECORD r : characters) { - needed.add(r.characterId); - } - } - @Override public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { boolean modified = false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java index ec7fe65ed..1380ef7ef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonTag.java @@ -34,6 +34,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Set; /** * @@ -63,6 +64,18 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim public abstract boolean trackAsMenu(); + @Override + public void getNeededCharacters(Set needed) { + for (BUTTONRECORD r : getRecords()) { + needed.add(r.characterId); + } + + DefineButtonSoundTag sounds = getSounds(); + if (sounds != null) { + sounds.getNeededCharacters(needed); + } + } + @Override public RECT getRect() { return getRect(new HashSet<>()); @@ -89,7 +102,7 @@ public abstract class ButtonTag extends CharacterTag implements DrawableTag, Tim } public DefineButtonSoundTag getSounds() { - for (Tag t : swf.getTags()) { + for (CharacterIdTag t : swf.getCharacterIdTags(getCharacterId())) { if (t instanceof DefineButtonSoundTag) { DefineButtonSoundTag st = (DefineButtonSoundTag) t; if (st.buttonId == getCharacterId()) { diff --git a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java index 2b78537d3..60171d41b 100644 --- a/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/PreviewPanel.java @@ -52,6 +52,7 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.VideoFrameTag; import com.jpexs.decompiler.flash.tags.base.AloneTag; import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; @@ -620,6 +621,22 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel return t; } + private static void writeTag(Tag t, SWFOutputStream sos) throws IOException { + t = classicTag(t); + + t.writeTag(sos); + if (t instanceof CharacterIdTag) { + List chIdTags = t.getSwf().getCharacterIdTags(((CharacterIdTag) t).getCharacterId()); + if (chIdTags != null) { + for (CharacterIdTag chIdTag : chIdTags) { + if (!(chIdTag instanceof PlaceObjectTypeTag || chIdTag instanceof RemoveTag)) { + ((Tag) chIdTag).writeTag(sos); + } + } + } + } + } + public void createAndShowTempSwf(TreeItem treeItem) { SWF swf = null; try { @@ -741,7 +758,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel t.getNeededCharactersDeep(needed); for (int n : needed) { if (!doneCharacters.contains(n)) { - classicTag(swf.getCharacter(n)).writeTag(sos2); + writeTag(swf.getCharacter(n), sos2); doneCharacters.add(n); } } @@ -757,7 +774,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } } - classicTag(t).writeTag(sos2); + writeTag(t, sos2); } RECT r = parent.getRect(); @@ -772,7 +789,6 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel new ShowFrameTag(swf).writeTag(sos2); } else { - boolean isSprite = false; if (treeItem instanceof DefineSpriteTag) { isSprite = true; @@ -804,11 +820,11 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel } } - classicTag(characterTag).writeTag(sos2); + writeTag(characterTag, sos2); } } - classicTag((Tag) treeItem).writeTag(sos2); + writeTag((Tag) treeItem, sos2); MATRIX mat = new MATRIX(); mat.hasRotate = false;