mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-12 15:20:08 +00:00
Frame dependencies
Show needed characters for a frame and frames depending on a character in the "Basic tag info" box
This commit is contained in:
@@ -304,6 +304,9 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
@Internal
|
||||
private volatile Map<Integer, Set<Integer>> dependentCharacters;
|
||||
|
||||
@Internal
|
||||
private volatile Map<Integer, Set<Integer>> dependentFrames;
|
||||
|
||||
@Internal
|
||||
private volatile List<ABCContainerTag> abcList;
|
||||
|
||||
@@ -488,21 +491,21 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
Map<Integer, Set<Integer>> dep = new HashMap<>();
|
||||
for (Tag tag : getTags()) {
|
||||
if (tag instanceof CharacterTag) {
|
||||
int characterId = ((CharacterTag) tag).getCharacterId();
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
tag.getNeededCharacters(needed);
|
||||
for (Integer needed1 : needed) {
|
||||
Set<Integer> s = dep.get(needed1);
|
||||
if (s == null) {
|
||||
s = new HashSet<>();
|
||||
dep.put(needed1, s);
|
||||
}
|
||||
|
||||
s.add(characterId);
|
||||
}
|
||||
}
|
||||
int characterId = ((CharacterTag) tag).getCharacterId();
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
tag.getNeededCharacters(needed);
|
||||
for (Integer needed1 : needed) {
|
||||
Set<Integer> s = dep.get(needed1);
|
||||
if (s == null) {
|
||||
s = new HashSet<>();
|
||||
dep.put(needed1, s);
|
||||
}
|
||||
|
||||
s.add(characterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependentCharacters = dep;
|
||||
}
|
||||
}
|
||||
@@ -545,6 +548,38 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
return dependents;
|
||||
}
|
||||
|
||||
public void computeDependentFrames() {
|
||||
Map<Integer, Set<Integer>> dep = new HashMap<>();
|
||||
for (int i = 0; i < timeline.getFrameCount(); i++) {
|
||||
Frame frame = timeline.getFrame(i);
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
frame.getNeededCharacters(needed);
|
||||
for (Integer needed1 : needed) {
|
||||
Set<Integer> s = dep.get(needed1);
|
||||
if (s == null) {
|
||||
s = new HashSet<>();
|
||||
dep.put(needed1, s);
|
||||
}
|
||||
|
||||
s.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
dependentFrames = dep;
|
||||
}
|
||||
|
||||
public Set<Integer> getDependentFrames(int characterId) {
|
||||
if (dependentFrames == null) {
|
||||
synchronized (this) {
|
||||
if (dependentFrames == null) {
|
||||
computeDependentFrames();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependentFrames.get(characterId);
|
||||
}
|
||||
|
||||
public CharacterTag getCharacter(int characterId) {
|
||||
return getCharacters().get(characterId);
|
||||
@@ -1446,7 +1481,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
public void assignExportNamesToSymbols() {
|
||||
public void assignExportNamesToSymbols() {
|
||||
HashMap<Integer, String> exportNames = new HashMap<>();
|
||||
for (Tag t : getTags()) {
|
||||
if (t instanceof ExportAssetsTag) {
|
||||
|
||||
@@ -684,6 +684,11 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
|
||||
tagInfo.addInfo("general", "dependentCharacters", Helper.joinStrings(dependent, ", "));
|
||||
}
|
||||
}
|
||||
|
||||
Set<Integer> dependent2 = swf.getDependentFrames(characterId);
|
||||
if(dependent2 != null && dependent2.size() > 0) {
|
||||
tagInfo.addInfo("general", "dependentFrames", Helper.joinStrings(dependent2, ", "));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.tags.ShowFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer;
|
||||
import com.jpexs.decompiler.flash.tags.base.Exportable;
|
||||
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
@@ -29,6 +30,7 @@ import com.jpexs.decompiler.flash.types.SOUNDINFO;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
@@ -133,4 +135,13 @@ public class Frame implements TreeItem, Exportable {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
for (Tag t : innerTags) {
|
||||
if(t instanceof PlaceObjectTypeTag) {
|
||||
needed.add(((PlaceObjectTypeTag)t).getCharacterId());
|
||||
}
|
||||
}
|
||||
needed.remove(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,7 +1120,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
tagTree.clearSelection();
|
||||
for (TreeItem n : nodes) {
|
||||
if (n instanceof ClassesListTreeModel) {
|
||||
String filterText = filterField.getText();
|
||||
String filterText = filterField.getText();
|
||||
((ClassesListTreeModel) n).setFilter(filterText);
|
||||
TagTreeModel tm = tagTree.getModel();
|
||||
TreePath path = tm.getTreePath(n);
|
||||
@@ -3723,6 +3723,20 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
} else {
|
||||
showDetail(DETAILCARDEMPTYPANEL);
|
||||
}
|
||||
} else if (treeItem instanceof Frame) {
|
||||
Frame frame = (Frame) treeItem;
|
||||
Set<Integer> needed = new LinkedHashSet<>();
|
||||
|
||||
frame.getNeededCharacters(needed);
|
||||
|
||||
if (!needed.isEmpty()) {
|
||||
TagInfo tagInfo = new TagInfo();
|
||||
tagInfo.addInfo("general", "neededCharacters", Helper.joinStrings(needed, ", "));
|
||||
tagInfoPanel.setTagInfos(tagInfo);
|
||||
showDetail(DETAILCARDTAGINFO);
|
||||
} else {
|
||||
showDetail(DETAILCARDEMPTYPANEL);
|
||||
}
|
||||
} else {
|
||||
showDetail(DETAILCARDEMPTYPANEL);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.tags.TagInfo;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -62,11 +65,25 @@ public class TagInfoPanel extends JPanel {
|
||||
public void hyperlinkUpdate(HyperlinkEvent hyperLink) {
|
||||
|
||||
if (HyperlinkEvent.EventType.ACTIVATED.equals(hyperLink.getEventType())) {
|
||||
String url = hyperLink.getDescription();
|
||||
String strId = url.substring(7);
|
||||
Integer id = Integer.parseInt(strId);
|
||||
URI url;
|
||||
try {
|
||||
url = new URI(hyperLink.getDescription());
|
||||
} catch (Exception ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentSwf().getCharacter(id));
|
||||
String scheme = url.getScheme();
|
||||
String strId = url.getHost();
|
||||
Integer id = Integer.parseInt(strId);
|
||||
SWF swf = mainPanel.getCurrentSwf();
|
||||
|
||||
TreeItem item = null;
|
||||
if ("char".equals(scheme)) {
|
||||
item = swf.getCharacter(id);
|
||||
} else if ("frame".equals(scheme)) {
|
||||
item = swf.getTimeline().getFrame(id);
|
||||
}
|
||||
mainPanel.setTagTreeSelectedNode(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,16 +109,17 @@ public class TagInfoPanel extends JPanel {
|
||||
} else {
|
||||
result += "</tr>";
|
||||
}
|
||||
result += "<td width='50%' style='text-align:center;'>";
|
||||
result += mainPanel.translate("tagInfo.header.name");
|
||||
result += "</td>";
|
||||
result += "<td width='50%' style='text-align:center;'>";
|
||||
result += mainPanel.translate("tagInfo.header.value");
|
||||
result += "</td>";
|
||||
result += String.format(
|
||||
"<td width='50%%' style='text-align:center;'>%s</td>",
|
||||
mainPanel.translate("tagInfo.header.name")
|
||||
);
|
||||
result += String.format(
|
||||
"<td width='50%%' style='text-align:center;'>%s</td>",
|
||||
mainPanel.translate("tagInfo.header.value")
|
||||
);
|
||||
result += "</tr>";
|
||||
|
||||
for (TagInfo.TagInfoItem item : items) {
|
||||
Boolean convertToCharacterList;
|
||||
|
||||
flipFlop = !flipFlop;
|
||||
|
||||
@@ -114,7 +132,8 @@ public class TagInfoPanel extends JPanel {
|
||||
String name = item.getName();
|
||||
String key = "tagInfo." + name;
|
||||
|
||||
convertToCharacterList = name.equals("dependentCharacters") || name.equals("neededCharacters");
|
||||
boolean frameList = name.equals("dependentFrames");
|
||||
boolean convertToLinkList = name.equals("dependentCharacters") || name.equals("neededCharacters") || frameList;
|
||||
|
||||
try {
|
||||
name = mainPanel.translate(key);
|
||||
@@ -130,11 +149,10 @@ public class TagInfoPanel extends JPanel {
|
||||
if (value instanceof Boolean) {
|
||||
boolean boolValue = (boolean) value;
|
||||
value = boolValue ? AppStrings.translate("yes") : AppStrings.translate("no");
|
||||
} else if (convertToCharacterList) {
|
||||
String strValue = (String) value;
|
||||
String[] strIds = strValue.split(", ");
|
||||
} else if (convertToLinkList) {
|
||||
String[] strIds = ((String) value).split(", ");
|
||||
List<Integer> sortedIds = new ArrayList<>();
|
||||
strValue = "";
|
||||
String strValue = "";
|
||||
|
||||
for (String strId : strIds) {
|
||||
sortedIds.add(Integer.parseInt(strId));
|
||||
@@ -142,8 +160,11 @@ public class TagInfoPanel extends JPanel {
|
||||
|
||||
Collections.sort(sortedIds);
|
||||
|
||||
String scheme = frameList ? "frame" : "char";
|
||||
|
||||
for (int id : sortedIds) {
|
||||
strValue += "<a href='jump://" + id + "'>" + id + "</a>, ";
|
||||
int displayId = frameList ? id + 1 : id;
|
||||
strValue += String.format("<a href='%s://%d'>%d</a>, ", scheme, id, displayId);
|
||||
}
|
||||
|
||||
value = strValue.substring(0, strValue.length() - 2);
|
||||
|
||||
@@ -844,4 +844,6 @@ message.info.importSymbolClass = During importing Symbol-Class, you need to sele
|
||||
This is the same filename as it is used when exported.
|
||||
|
||||
message.info.importXml = For XML importing, you need a XML file in special format - the format in which FFDec exports.\r\n \
|
||||
The best way to create such XML file is to export XML from existing SWF first.
|
||||
The best way to create such XML file is to export XML from existing SWF first.
|
||||
|
||||
tagInfo.dependentFrames = Dependent Frames
|
||||
Reference in New Issue
Block a user