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 419b8b799..97ea560fd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -484,14 +484,11 @@ public final class SWF implements SWFContainerItem, Timelined { return null; } - - public Map> getDependentCharacters() { - if (dependentCharacters == null) { - synchronized (this) { - if (dependentCharacters == null) { - Map> dep = new HashMap<>(); - for (Tag tag : getTags()) { - if (tag instanceof CharacterTag) { + + public void computeDependentCharacters() { + Map> dep = new HashMap<>(); + for (Tag tag : getTags()) { + if (tag instanceof CharacterTag) { int characterId = ((CharacterTag) tag).getCharacterId(); Set needed = new HashSet<>(); tag.getNeededCharacters(needed); @@ -507,7 +504,14 @@ public final class SWF implements SWFContainerItem, Timelined { } } - dependentCharacters = dep; + dependentCharacters = dep; + } + + public Map> getDependentCharacters() { + if (dependentCharacters == null) { + synchronized (this) { + if (dependentCharacters == null) { + computeDependentCharacters(); } } } @@ -3344,6 +3348,8 @@ public final class SWF implements SWFContainerItem, Timelined { assignClassesToSymbols(); clearImageCache(); updateCharacters(); + computeDependentCharacters(); + computeDependentFrames(); } @Override diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 0f0fda234..bc9e9758b 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -855,4 +855,6 @@ importing_as.finishedin = Imported in %time% work.deobfuscating_pcode = Deobfuscating pcode work.injecting_debuginfo = Injecting debug info -work.generating_swd = Generating SWD file \ No newline at end of file +work.generating_swd = Generating SWD file + +button.replaceRefs = Replace references with other character ID \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index c5c31be45..f362322e0 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -125,6 +125,8 @@ public class TagTreeContextMenu extends JPopupMenu { private JMenuItem replaceNoFillMenuItem; private JMenuItem replaceWithTagMenuItem; + + private JMenuItem replaceRefsWithTagMenuItem; private JMenuItem rawEditMenuItem; @@ -193,6 +195,10 @@ public class TagTreeContextMenu extends JPopupMenu { replaceWithTagMenuItem = new JMenuItem(mainPanel.translate("button.replaceWithTag")); replaceWithTagMenuItem.addActionListener(this::replaceWithTagActionPerformed); add(replaceWithTagMenuItem); + + replaceRefsWithTagMenuItem = new JMenuItem(mainPanel.translate("button.replaceRefs")); + replaceRefsWithTagMenuItem.addActionListener(this::replaceRefsWithTagActionPerformed); + add(replaceRefsWithTagMenuItem); rawEditMenuItem = new JMenuItem(mainPanel.translate("contextmenu.rawEdit")); rawEditMenuItem.addActionListener(this::rawEditActionPerformed); @@ -426,6 +432,7 @@ public class TagTreeContextMenu extends JPopupMenu { replaceMenuItem.setVisible(false); replaceNoFillMenuItem.setVisible(false); replaceWithTagMenuItem.setVisible(false); + replaceRefsWithTagMenuItem.setVisible(false); rawEditMenuItem.setVisible(false); jumpToCharacterMenuItem.setVisible(false); exportJavaSourceMenuItem.setVisible(allSelectedIsSwf); @@ -505,6 +512,7 @@ public class TagTreeContextMenu extends JPopupMenu { if (firstItem instanceof CharacterTag) { replaceWithTagMenuItem.setVisible(true); + replaceRefsWithTagMenuItem.setVisible(true); } addTagMenu.removeAll(); @@ -809,6 +817,54 @@ public class TagTreeContextMenu extends JPopupMenu { mainPanel.refreshTree(swf); } } + + private void replaceRefsWithTagActionPerformed(ActionEvent evt) { + TreeItem itemr = tagTree.getCurrentTreeItem(); + if (itemr == null) { + return; + } + + SWF swf = itemr.getSwf(); + CharacterTag characterTag = (CharacterTag) itemr; + int characterId = characterTag.getCharacterId(); + ReplaceCharacterDialog replaceCharacterDialog = new ReplaceCharacterDialog(Main.getDefaultDialogsOwner()); + if (replaceCharacterDialog.showDialog(swf, characterId) == AppDialog.OK_OPTION) { + int newCharacterId = replaceCharacterDialog.getCharacterId(); + + for (Tag tag : swf.getTags()) { + replaceRef(tag, characterId, newCharacterId); + } + + swf.assignExportNamesToSymbols(); + swf.assignClassesToSymbols(); + swf.clearImageCache(); + swf.updateCharacters(); + swf.computeDependentCharacters(); + swf.computeDependentFrames(); + mainPanel.refreshTree(swf); + } + } + + private void replaceRef(Tag tag, int characterId, int newCharacterId) { + if(tag instanceof DefineSpriteTag) { + DefineSpriteTag sprite = (DefineSpriteTag)tag; + for (Tag subTag : sprite.getTags()) { + replaceRef(subTag, characterId, newCharacterId); + } + sprite.clearReadOnlyListCache(); + } + if(tag instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag placeTag = (PlaceObjectTypeTag)tag; + if(placeTag.getCharacterId() == characterId) { + placeTag.setCharacterId(newCharacterId); + placeTag.setModified(true); + Timelined tim = placeTag.getTimelined(); + if(tim != null) { + tim.resetTimeline(); + } + } + } + } private void rawEditActionPerformed(ActionEvent evt) { TreeItem itemr = tagTree.getCurrentTreeItem();