mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-12 14:11:54 +00:00
Merge origin/master
Conflicts: libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.helpers.SwfHeaderStreamSearch;
|
||||
|
||||
@@ -69,6 +69,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.FramesExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.exporters.script.AS2ScriptExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
|
||||
import com.jpexs.decompiler.flash.exporters.settings.FramesExportSettings;
|
||||
@@ -82,8 +83,7 @@ import com.jpexs.decompiler.flash.exporters.shape.CanvasShapeExporter;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
|
||||
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.EndTag;
|
||||
@@ -117,16 +117,7 @@ import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
import com.jpexs.decompiler.flash.timeline.SvgClip;
|
||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.AS3PackageNodeItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.SWFList;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.decompiler.flash.treenodes.AS2PackageNode;
|
||||
import com.jpexs.decompiler.flash.treenodes.ContainerNode;
|
||||
import com.jpexs.decompiler.flash.treenodes.FrameNode;
|
||||
import com.jpexs.decompiler.flash.treenodes.TagNode;
|
||||
import com.jpexs.decompiler.flash.treenodes.TreeNode;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.MATRIX;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
@@ -212,7 +203,7 @@ import org.monte.media.avi.AVIWriter;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public final class SWF implements TreeItem, Timelined {
|
||||
public final class SWF implements SWFContainerItem, Timelined {
|
||||
|
||||
/**
|
||||
* Default version of SWF file format
|
||||
@@ -278,6 +269,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
private Timeline timeline;
|
||||
|
||||
public DumpInfoSwfNode dumpInfo;
|
||||
public DefineBinaryDataTag binaryData;
|
||||
|
||||
public void updateCharacters() {
|
||||
characters.clear();
|
||||
@@ -285,10 +277,8 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
|
||||
public void resetTimelines(Timelined timelined) {
|
||||
timelined.resetTimeline();
|
||||
List<Tag> tags = timelined.getTimeline().tags;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
Tag t = tags.get(i);
|
||||
timelined.getTimeline().reset();
|
||||
for (Tag t : timelined.getTimeline().tags) {
|
||||
if (t instanceof Timelined) {
|
||||
resetTimelines((Timelined) t);
|
||||
}
|
||||
@@ -344,11 +334,6 @@ public final class SWF implements TreeItem, Timelined {
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
timeline = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all tags with specified id
|
||||
*
|
||||
@@ -619,7 +604,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
ArrayList<ABCContainerTag> newAbcList = new ArrayList<>();
|
||||
getABCTags(objs, newAbcList);
|
||||
isAS3 = !newAbcList.isEmpty();
|
||||
isAS3 = (fileAttributes != null && fileAttributes.actionScript3) || (fileAttributes == null && !newAbcList.isEmpty());
|
||||
abcList = newAbcList;
|
||||
}
|
||||
|
||||
@@ -649,8 +634,10 @@ public final class SWF implements TreeItem, Timelined {
|
||||
if (t instanceof ExportAssetsTag) {
|
||||
ExportAssetsTag eat = (ExportAssetsTag) t;
|
||||
for (int i = 0; i < eat.tags.size(); i++) {
|
||||
if ((!exportNames.containsKey(eat.tags.get(i))) && (!exportNames.containsValue(eat.names.get(i)))) {
|
||||
exportNames.put(eat.tags.get(i), eat.names.get(i));
|
||||
Integer tagId = eat.tags.get(i);
|
||||
String name = eat.names.get(i);
|
||||
if ((!exportNames.containsKey(tagId)) && (!exportNames.containsValue(name))) {
|
||||
exportNames.put(tagId, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -821,19 +808,10 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
|
||||
public boolean exportAS3Class(String className, String outdir, ScriptExportMode exportMode, boolean parallel) throws Exception {
|
||||
List<ABCContainerTag> abcTags = new ArrayList<>();
|
||||
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
ABCContainerTag cnt = (ABCContainerTag) t;
|
||||
abcTags.add(cnt);
|
||||
}
|
||||
}
|
||||
|
||||
boolean exported = false;
|
||||
|
||||
for (int i = 0; i < abcTags.size(); i++) {
|
||||
ABC abc = abcTags.get(i).getABC();
|
||||
for (int i = 0; i < abcList.size(); i++) {
|
||||
ABC abc = abcList.get(i).getABC();
|
||||
List<ScriptPack> scrs = abc.findScriptPacksByPath(className);
|
||||
for (int j = 0; j < scrs.size(); j++) {
|
||||
ScriptPack scr = scrs.get(j);
|
||||
@@ -841,10 +819,10 @@ public final class SWF implements TreeItem, Timelined {
|
||||
if (scrs.size() > 1) {
|
||||
cnt = "script " + (j + 1) + "/" + scrs.size() + " ";
|
||||
}
|
||||
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ...";
|
||||
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcList.size() + " " + cnt + scr.getPath() + " ...";
|
||||
informListeners("exporting", exStr);
|
||||
scr.export(outdir, abcTags, exportMode, parallel);
|
||||
exStr = "Exported " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ...";
|
||||
scr.export(outdir, abcList, exportMode, parallel);
|
||||
exStr = "Exported " + "tag " + (i + 1) + "/" + abcList.size() + " " + cnt + scr.getPath() + " ...";
|
||||
informListeners("exported", exStr);
|
||||
exported = true;
|
||||
}
|
||||
@@ -868,11 +846,8 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
public List<MyEntry<ClassPath, ScriptPack>> getAS3Packs() {
|
||||
List<MyEntry<ClassPath, ScriptPack>> packs = new ArrayList<>();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
ABCContainerTag abcTag = (ABCContainerTag) t;
|
||||
packs.addAll(abcTag.getABC().getScriptPacks());
|
||||
}
|
||||
for (ABCContainerTag abcTag : abcList) {
|
||||
packs.addAll(abcTag.getABC().getScriptPacks());
|
||||
}
|
||||
return uniqueAS3Packs(packs);
|
||||
}
|
||||
@@ -932,28 +907,20 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
public List<File> exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel, EventListener evl) throws IOException {
|
||||
private List<File> exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel, EventListener evl) throws IOException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
List<ContainerItem> list2 = new ArrayList<>();
|
||||
list2.addAll(tags);
|
||||
List<TreeNode> list = createASTagList(list2, this);
|
||||
Map<String, ASMSource> asms = getASMs();
|
||||
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
outdir += File.separator;
|
||||
}
|
||||
outdir += "scripts" + File.separator;
|
||||
ret.addAll(TagNode.exportNodeAS(handler, list, list, outdir, exportMode, evl));
|
||||
ret.addAll(new AS2ScriptExporter().exportAS2ScriptsTimeout(handler, outdir, asms.values(), exportMode, evl));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<File> exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportMode exportMode, final boolean parallel) {
|
||||
private List<File> exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ScriptExportMode exportMode, final boolean parallel) {
|
||||
final AtomicInteger cnt = new AtomicInteger(1);
|
||||
final List<ABCContainerTag> abcTags = new ArrayList<>();
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
abcTags.add((ABCContainerTag) t);
|
||||
}
|
||||
}
|
||||
|
||||
final List<File> ret = new ArrayList<>();
|
||||
final List<MyEntry<ClassPath, ScriptPack>> packs = getAS3Packs();
|
||||
@@ -964,7 +931,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
for (MyEntry<ClassPath, ScriptPack> item : packs) {
|
||||
ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcTags, exportMode, parallel);
|
||||
ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcList, exportMode, parallel);
|
||||
ret.add(task.call());
|
||||
}
|
||||
return null;
|
||||
@@ -979,7 +946,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Configuration.parallelThreadCount.get());
|
||||
List<Future<File>> futureResults = new ArrayList<>();
|
||||
for (MyEntry<ClassPath, ScriptPack> item : packs) {
|
||||
Future<File> future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcTags, exportMode, parallel));
|
||||
Future<File> future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.getKey(), item.getValue(), outdir, abcList, exportMode, parallel));
|
||||
futureResults.add(future);
|
||||
}
|
||||
|
||||
@@ -1009,7 +976,6 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
|
||||
public List<File> exportActionScript(AbortRetryIgnoreHandler handler, String outdir, ScriptExportMode exportMode, boolean parallel) throws Exception {
|
||||
boolean asV3Found = false;
|
||||
List<File> ret = new ArrayList<>();
|
||||
final EventListener evl = new EventListener() {
|
||||
@Override
|
||||
@@ -1019,13 +985,8 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
}
|
||||
};
|
||||
for (Tag t : tags) {
|
||||
if (t instanceof ABCContainerTag) {
|
||||
asV3Found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (asV3Found) {
|
||||
if (isAS3) {
|
||||
ret.addAll(exportActionScript3(handler, outdir, exportMode, parallel));
|
||||
} else {
|
||||
ret.addAll(exportActionScript2(handler, outdir, exportMode, parallel, evl));
|
||||
@@ -1033,160 +994,30 @@ public final class SWF implements TreeItem, Timelined {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static List<TreeNode> createASTagList(List<? extends ContainerItem> list, Timelined parent) {
|
||||
List<TreeNode> ret = new ArrayList<>();
|
||||
int frame = 0;
|
||||
List<TreeNode> frames = new ArrayList<>();
|
||||
|
||||
for (ContainerItem t : list) {
|
||||
TreeNode addNode = null;
|
||||
if (t instanceof ShowFrameTag) {
|
||||
// do not add PlaceObjects (+etc) to script nodes
|
||||
FrameNode tti = new FrameNode(new FrameNodeItem(t.getSwf(), frame, parent, false), null, true);
|
||||
|
||||
for (int r = ret.size() - 1; r >= 0; r--) {
|
||||
TreeNode node = ret.get(r);
|
||||
TreeItem item = node.getItem();
|
||||
if (!(item instanceof DefineSpriteTag
|
||||
|| item instanceof DefineButtonTag
|
||||
|| item instanceof DefineButton2Tag
|
||||
|| item instanceof DoInitActionTag
|
||||
|| item instanceof AS2PackageNodeItem)) {
|
||||
tti.subNodes.add(node);
|
||||
ret.remove(r);
|
||||
}
|
||||
}
|
||||
frame++;
|
||||
frames.add(tti);
|
||||
} else if (t instanceof ASMSource) {
|
||||
ContainerNode tti = new ContainerNode(t);
|
||||
addNode = tti;
|
||||
} else if (t instanceof Container) {
|
||||
if (((Container) t).getItemCount() > 0) {
|
||||
|
||||
ContainerNode tti = new ContainerNode(t);
|
||||
List<ContainerItem> subItems = ((Container) t).getSubItems();
|
||||
|
||||
Timelined timelined = t instanceof Timelined ? (Timelined) t : null;
|
||||
tti.subNodes = createASTagList(subItems, timelined);
|
||||
addNode = tti;
|
||||
}
|
||||
}
|
||||
if (addNode != null) {
|
||||
if (addNode.getItem() instanceof CharacterIdTag) {
|
||||
CharacterIdTag cit = (CharacterIdTag) addNode.getItem();
|
||||
String path = cit.getExportName();
|
||||
if (path == null) {
|
||||
path = "";
|
||||
}
|
||||
String[] pathParts = path.contains(".") ? path.split("\\.") : new String[]{path};
|
||||
List<TreeNode> items = ret;
|
||||
for (int pos = 0; pos < pathParts.length - 1; pos++) {
|
||||
String pathPart = pathParts[pos];
|
||||
TreeNode selNode = null;
|
||||
for (TreeNode node : items) {
|
||||
if (node.getItem() instanceof AS2PackageNodeItem) {
|
||||
AS2PackageNodeItem pkg = (AS2PackageNodeItem) node.getItem();
|
||||
if (pkg.packageName.equals(pathPart)) {
|
||||
selNode = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int pkgCount = 0;
|
||||
for (; pkgCount < items.size(); pkgCount++) {
|
||||
if (items.get(pkgCount).getItem() instanceof AS3PackageNodeItem) {
|
||||
AS3PackageNodeItem pkg = (AS3PackageNodeItem) items.get(pkgCount).getItem();
|
||||
if (pkg.packageName.compareTo(pathPart) > 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (selNode == null) {
|
||||
items.add(pkgCount, selNode = new AS2PackageNode(new AS2PackageNodeItem(pathPart, t.getSwf())));
|
||||
}
|
||||
pos++;
|
||||
items = selNode.subNodes;
|
||||
}
|
||||
|
||||
int clsCount = 0;
|
||||
String addNodeName = addNode.getItem().getClass().getName() + "_" + pathParts[pathParts.length - 1];
|
||||
for (; clsCount < items.size(); clsCount++) {
|
||||
if (items.get(clsCount).getItem() instanceof CharacterIdTag) {
|
||||
CharacterIdTag ct = (CharacterIdTag) items.get(clsCount).getItem();
|
||||
String expName = ct.getExportName();
|
||||
if (expName == null) {
|
||||
expName = "";
|
||||
}
|
||||
if (expName.contains(".")) {
|
||||
expName = expName.substring(expName.lastIndexOf('.') + 1);
|
||||
}
|
||||
if ((ct.getClass().getName() + "_" + expName).compareTo(addNodeName) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
items.add(clsCount, addNode);
|
||||
} else {
|
||||
ret.add(addNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ret.addAll(frames);
|
||||
for (int i = ret.size() - 1; i >= 0; i--) {
|
||||
TreeNode node = ret.get(i);
|
||||
TreeItem item = node.getItem();
|
||||
if (item instanceof ASMSource) {
|
||||
ASMSource ass = (ASMSource) item;
|
||||
if (ass.containsSource()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (node.subNodes.isEmpty()) {
|
||||
ret.remove(i);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Map<String, ASMSource> getASMs() {
|
||||
List<TreeNode> list = createASTagList(tags, this);
|
||||
Map<String, ASMSource> asms = new HashMap<>();
|
||||
getASMs("", list, asms);
|
||||
return asms;
|
||||
Map<String, ASMSource> asms2 = new HashMap<>();
|
||||
getASMs("", tags, asms2);
|
||||
return asms2;
|
||||
}
|
||||
|
||||
private static void getASMs(String path, List<TreeNode> nodes, Map<String, ASMSource> result) {
|
||||
for (TreeNode n : nodes) {
|
||||
String subPath = path + "/" + n.toString();
|
||||
if (n.getItem() instanceof ASMSource) {
|
||||
//cacheScript((ASMSource) n.tag);
|
||||
private static void getASMs(String path, List<? extends ContainerItem> items, Map<String, ASMSource> asms) {
|
||||
for (ContainerItem item : items) {
|
||||
String subPath = path + "/" + item.toString();
|
||||
if (item instanceof ASMSource) {
|
||||
String npath = subPath;
|
||||
int ppos = 1;
|
||||
while (result.containsKey(npath)) {
|
||||
while (asms.containsKey(npath)) {
|
||||
ppos++;
|
||||
npath = subPath + "[" + ppos + "]";
|
||||
}
|
||||
result.put(npath, (ASMSource) n.getItem());
|
||||
asms.put(npath, (ASMSource) item);
|
||||
}
|
||||
if (item instanceof Container) {
|
||||
getASMs(subPath, ((Container) item).getSubItems(), asms);
|
||||
}
|
||||
|
||||
getASMs(subPath, n.subNodes, result);
|
||||
}
|
||||
}
|
||||
|
||||
public static void getTagsFromTreeNodes(List<TreeNode> treeNodes, List<Tag> result) {
|
||||
for (TreeNode treeNode : treeNodes) {
|
||||
TreeItem treeItem = treeNode.getItem();
|
||||
if (treeItem instanceof Tag) {
|
||||
result.add((Tag) treeItem);
|
||||
}
|
||||
getTagsFromTreeNodes(treeNode.subNodes, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final HashSet<EventListener> listeners = new HashSet<>();
|
||||
|
||||
public final void addEventListener(EventListener listener) {
|
||||
@@ -1401,7 +1232,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
path = File.separator + Helper.makeFileName(characters.get(containerId).getExportFileName());
|
||||
}
|
||||
if (frames == null) {
|
||||
int frameCnt = tim.frames.size();
|
||||
int frameCnt = tim.getFrames().size();
|
||||
frames = new ArrayList<>();
|
||||
for (int i = 0; i < frameCnt; i++) {
|
||||
frames.add(i);
|
||||
@@ -2253,7 +2084,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
Stack<Integer> clipDepths = new Stack<>();
|
||||
for (int frame : frames) {
|
||||
sb.append("\t\tcase ").append(frame).append(":\r\n");
|
||||
Frame frameObj = timeline.frames.get(frame);
|
||||
Frame frameObj = timeline.getFrames().get(frame);
|
||||
for (int i = 1; i <= maxDepth + 1; i++) {
|
||||
while (!clipDepths.isEmpty() && clipDepths.peek() <= i) {
|
||||
clipDepths.pop();
|
||||
@@ -2467,10 +2298,10 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
|
||||
public static void frameToSvg(Timeline timeline, int frame, int time, DepthState stateUnderCursor, int mouseButton, SVGExporter exporter, ColorTransform colorTransform, int level, double zoom) throws IOException {
|
||||
if (timeline.frames.size() <= frame) {
|
||||
if (timeline.getFrames().size() <= frame) {
|
||||
return;
|
||||
}
|
||||
Frame frameObj = timeline.frames.get(frame);
|
||||
Frame frameObj = timeline.getFrames().get(frame);
|
||||
List<SvgClip> clips = new ArrayList<>();
|
||||
List<String> prevClips = new ArrayList<>();
|
||||
|
||||
@@ -2570,7 +2401,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
if (timeline.frames.isEmpty()) {
|
||||
if (timeline.getFrames().isEmpty()) {
|
||||
return new SerializableImage(1, 1, SerializableImage.TYPE_INT_ARGB);
|
||||
}
|
||||
|
||||
@@ -2595,7 +2426,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
public static void framesToImage(Timeline timeline, List<SerializableImage> ret, int startFrame, int stopFrame, DepthState stateUnderCursor, int mouseButton, RECT displayRect, int totalFrameCount, Stack<Integer> visited, Matrix transformation, ColorTransform colorTransform, double zoom) {
|
||||
RECT rect = displayRect;
|
||||
for (int f = 0; f < timeline.frames.size(); f++) {
|
||||
for (int f = 0; f < timeline.getFrames().size(); f++) {
|
||||
SerializableImage image = new SerializableImage((int) (rect.getWidth() / SWF.unitDivisor) + 1,
|
||||
(int) (rect.getHeight() / SWF.unitDivisor) + 1, SerializableImage.TYPE_INT_ARGB);
|
||||
image.fillTransparent();
|
||||
@@ -2608,10 +2439,10 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
public static void frameToImage(Timeline timeline, int frame, int time, DepthState stateUnderCursor, int mouseButton, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
|
||||
double unzoom = SWF.unitDivisor;
|
||||
if (timeline.frames.size() <= frame) {
|
||||
if (timeline.getFrames().size() <= frame) {
|
||||
return;
|
||||
}
|
||||
Frame frameObj = timeline.frames.get(frame);
|
||||
Frame frameObj = timeline.getFrames().get(frame);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setPaint(frameObj.backgroundColor.toColor());
|
||||
g.fill(new Rectangle(image.getWidth(), image.getHeight()));
|
||||
@@ -2958,7 +2789,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
tags = this.tags;
|
||||
}
|
||||
tags.remove(t);
|
||||
timelined.resetTimeline();
|
||||
timelined.getTimeline().reset();
|
||||
} else {
|
||||
// timeline should be always the swf here
|
||||
if (removeDependencies) {
|
||||
@@ -2971,4 +2802,9 @@ public final class SWF implements TreeItem, Timelined {
|
||||
updateCharacters();
|
||||
clearImageCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getShortFileName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
* Copyright (C) 2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -12,13 +12,16 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface TreeElementItem extends TreeItem {
|
||||
|
||||
public interface SWFContainerItem extends TreeItem {
|
||||
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.helpers.Helper;
|
||||
|
||||
@@ -1207,7 +1207,7 @@ public class ABC {
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isDocumentClass = documentClass.equals(pack.getPath().toString());
|
||||
boolean isDocumentClass = documentClass.equals(pack.getClassPath().toString());
|
||||
|
||||
ScriptInfo si = script_info.get(oldIndex);
|
||||
si.delete(this, true);
|
||||
|
||||
@@ -245,7 +245,7 @@ public class ABCInputStream implements AutoCloseable {
|
||||
return is.available();
|
||||
}
|
||||
|
||||
private final long readLong() throws IOException {
|
||||
private long readLong() throws IOException {
|
||||
byte[] readBuffer = safeRead(8);
|
||||
return (((long) readBuffer[7] << 56)
|
||||
+ ((long) (readBuffer[6] & 255) << 48)
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
|
||||
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
@@ -46,7 +46,7 @@ import java.util.logging.Logger;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ScriptPack implements TreeElementItem {
|
||||
public class ScriptPack extends AS3ClassTreeItem {
|
||||
|
||||
public final ABC abc;
|
||||
public final int scriptIndex;
|
||||
@@ -58,11 +58,12 @@ public class ScriptPack implements TreeElementItem {
|
||||
return abc.swf;
|
||||
}
|
||||
|
||||
public ClassPath getPath() {
|
||||
public ClassPath getClassPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public ScriptPack(ClassPath path, ABC abc, int scriptIndex, List<Integer> traitIndices) {
|
||||
super(path.className, path.toString());
|
||||
this.abc = abc;
|
||||
this.scriptIndex = scriptIndex;
|
||||
this.traitIndices = traitIndices;
|
||||
@@ -178,7 +179,7 @@ public class ScriptPack implements TreeElementItem {
|
||||
public File export(String directory, List<ABCContainerTag> abcList, ScriptExportMode exportMode, boolean parallel) throws IOException {
|
||||
String scriptName = getPathScriptName();
|
||||
String packageName = getPathPackage();
|
||||
File outDir = new File(directory + File.separatorChar + makeDirPath(packageName));
|
||||
File outDir = new File(directory + File.separatorChar + "scripts" + File.separatorChar + makeDirPath(packageName));
|
||||
if (!outDir.exists()) {
|
||||
if (!outDir.mkdirs()) {
|
||||
if (!outDir.exists()) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class Multiname {
|
||||
public List<Integer> params; //for TypeName
|
||||
public boolean deleted;
|
||||
|
||||
public boolean validType() {
|
||||
private boolean validType() {
|
||||
boolean cnt = false;
|
||||
for (int i = 0; i < multinameKinds.length; i++) {
|
||||
if (multinameKinds[i] == kind) {
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS2ScriptExporter {
|
||||
|
||||
public List<File> exportAS2ScriptsTimeout(final AbortRetryIgnoreHandler handler, final String outdir, final Collection<ASMSource> asms, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
|
||||
try {
|
||||
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
|
||||
|
||||
@Override
|
||||
public List<File> call() throws Exception {
|
||||
return exportAS2Scripts(handler, outdir, asms, exportMode, ev);
|
||||
}
|
||||
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
|
||||
return result;
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private List<File> exportAS2Scripts(AbortRetryIgnoreHandler handler, String outdir, Collection<ASMSource> asms, ScriptExportMode exportMode, EventListener ev) throws IOException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
outdir += File.separator;
|
||||
}
|
||||
|
||||
outdir += "scripts" + File.separator;
|
||||
|
||||
Map<String, List<String>> existingNamesMap = new HashMap<>();
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
for (ASMSource asm : asms) {
|
||||
String currentOutDir = outdir + getFilePath(asm) + File.separator;
|
||||
currentOutDir = new File(currentOutDir).getParentFile().toString() + File.separator;
|
||||
|
||||
List<String> existingNames = existingNamesMap.get(currentOutDir);
|
||||
if (existingNames == null) {
|
||||
existingNames = new ArrayList<>();
|
||||
existingNamesMap.put(currentOutDir, existingNames);
|
||||
}
|
||||
|
||||
String name = Helper.makeFileName(asm.getExportFileName());
|
||||
int i = 1;
|
||||
String baseName = name;
|
||||
while (existingNames.contains(name)) {
|
||||
i++;
|
||||
name = baseName + "_" + i;
|
||||
}
|
||||
existingNames.add(name);
|
||||
|
||||
File f = exportAS2Script(handler, currentOutDir, asm, exportMode, ev, cnt, asms.size(), name);
|
||||
if (f != null) {
|
||||
ret.add(f);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private File exportAS2Script(AbortRetryIgnoreHandler handler, String outdir, ASMSource asm, ScriptExportMode exportMode, EventListener ev, AtomicInteger index, int count, String name) throws IOException {
|
||||
boolean retry;
|
||||
do {
|
||||
retry = false;
|
||||
try {
|
||||
int currentIndex = index.getAndIncrement();
|
||||
|
||||
File dir = new File(outdir);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdirs()) {
|
||||
if (!dir.exists()) {
|
||||
throw new IOException("Cannot create directory " + outdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String f = outdir + name + ".as";
|
||||
if (ev != null) {
|
||||
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
File file = new File(f);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
|
||||
if (exportMode == ScriptExportMode.HEX) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getActionBytesAsHex(writer);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else if (exportMode != ScriptExportMode.AS) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getASMSource(exportMode, writer, null);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else {
|
||||
List<Action> as = asm.getActions();
|
||||
Action.setActionsAddresses(as, 0);
|
||||
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
|
||||
}
|
||||
}
|
||||
|
||||
long stopTime = System.currentTimeMillis();
|
||||
|
||||
if (ev != null) {
|
||||
long time = stopTime - startTime;
|
||||
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
|
||||
}
|
||||
|
||||
return file;
|
||||
} catch (InterruptedException ex) {
|
||||
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
|
||||
Logger.getLogger(AS2ScriptExporter.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
|
||||
if (handler != null) {
|
||||
int action = handler.getNewInstance().handle(ex);
|
||||
switch (action) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
case AbortRetryIgnoreHandler.RETRY:
|
||||
retry = true;
|
||||
break;
|
||||
case AbortRetryIgnoreHandler.IGNORE:
|
||||
retry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// todo: honfika: get the path from the tree
|
||||
private String getFilePath(ASMSource asm) {
|
||||
if (asm instanceof DoInitActionTag) {
|
||||
String exportName = ((DoInitActionTag) asm).getExportName();
|
||||
|
||||
if (exportName != null) {
|
||||
String path = "";
|
||||
StringTokenizer st = new StringTokenizer(exportName, ".");
|
||||
while (st.hasMoreTokens()) {
|
||||
String pathElement = st.nextToken();
|
||||
if (path.length() > 0) {
|
||||
path += File.separator;
|
||||
}
|
||||
|
||||
path += Helper.makeFileName(pathElement);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(asm instanceof Tag)) {
|
||||
return Helper.makeFileName(asm.getSourceTag().getExportFileName()) + File.separator + Helper.makeFileName(asm.getExportFileName());
|
||||
} else {
|
||||
String result = "";
|
||||
Timelined timelined = asm.getSourceTag().getTimelined();
|
||||
if (timelined instanceof Tag) {
|
||||
result += Helper.makeFileName(((Tag) timelined).getExportFileName()) + File.separator;
|
||||
}
|
||||
|
||||
Timeline timeline = timelined.getTimeline();
|
||||
int frame = timeline.getFrameForAction(asm);
|
||||
if (frame != -1) {
|
||||
result += "frame_" + (frame + 1) + File.separator;
|
||||
}
|
||||
|
||||
return result + Helper.makeFileName(asm.getExportFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,12 @@ public class FileTextWriter extends GraphTextWriter implements AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter hilightSpecial(String text, String type, int index, Map<String, String> data) {
|
||||
writeToFile(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileTextWriter append(String str) {
|
||||
writeToFile(str);
|
||||
|
||||
@@ -12,13 +12,16 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
@@ -39,6 +42,9 @@ public class DefineBinaryDataTag extends CharacterTag {
|
||||
|
||||
public static final int ID = 87;
|
||||
|
||||
@Internal
|
||||
public SWF innerSwf;
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
|
||||
@@ -255,13 +255,13 @@ public class DefineButton2Tag extends ButtonTag implements Container {
|
||||
if (timeline != null) {
|
||||
return timeline;
|
||||
}
|
||||
timeline = new Timeline(swf, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
|
||||
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
|
||||
|
||||
int maxDepth = 0;
|
||||
Frame frameUp = new Frame(timeline);
|
||||
Frame frameDown = new Frame(timeline);
|
||||
Frame frameOver = new Frame(timeline);
|
||||
Frame frameHit = new Frame(timeline);
|
||||
Frame frameUp = new Frame(timeline, 0);
|
||||
Frame frameDown = new Frame(timeline, 0);
|
||||
Frame frameOver = new Frame(timeline, 0);
|
||||
Frame frameHit = new Frame(timeline, 0);
|
||||
for (BUTTONRECORD r : this.characters) {
|
||||
|
||||
DepthState layer = new DepthState(swf, null);
|
||||
@@ -288,24 +288,19 @@ public class DefineButton2Tag extends ButtonTag implements Container {
|
||||
}
|
||||
|
||||
}
|
||||
timeline.frames.add(frameUp);
|
||||
timeline.getFrames().add(frameUp);
|
||||
if (frameOver.layers.isEmpty()) {
|
||||
frameOver = frameUp;
|
||||
}
|
||||
timeline.frames.add(frameOver);
|
||||
timeline.getFrames().add(frameOver);
|
||||
if (frameDown.layers.isEmpty()) {
|
||||
frameDown = frameOver;
|
||||
}
|
||||
timeline.frames.add(frameDown);
|
||||
timeline.getFrames().add(frameDown);
|
||||
if (frameHit.layers.isEmpty()) {
|
||||
frameHit = frameUp;
|
||||
}
|
||||
timeline.frames.add(frameHit);
|
||||
timeline.getFrames().add(frameHit);
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
timeline = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
if (timeline != null) {
|
||||
return timeline;
|
||||
}
|
||||
timeline = new Timeline(swf, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
|
||||
timeline = new Timeline(swf, this, new ArrayList<Tag>(), buttonId, getRect(new HashSet<BoundedTag>()));
|
||||
|
||||
ColorTransform clrTrans = null;
|
||||
for (Tag t : swf.tags) {
|
||||
@@ -336,10 +336,10 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
}
|
||||
}
|
||||
int maxDepth = 0;
|
||||
Frame frameUp = new Frame(timeline);
|
||||
Frame frameDown = new Frame(timeline);
|
||||
Frame frameOver = new Frame(timeline);
|
||||
Frame frameHit = new Frame(timeline);
|
||||
Frame frameUp = new Frame(timeline, 0);
|
||||
Frame frameDown = new Frame(timeline, 0);
|
||||
Frame frameOver = new Frame(timeline, 0);
|
||||
Frame frameHit = new Frame(timeline, 0);
|
||||
for (BUTTONRECORD r : this.characters) {
|
||||
|
||||
DepthState layer = new DepthState(swf, null);
|
||||
@@ -366,28 +366,23 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
}
|
||||
|
||||
}
|
||||
timeline.frames.add(frameUp);
|
||||
timeline.getFrames().add(frameUp);
|
||||
if (frameOver.layers.isEmpty()) {
|
||||
frameOver = frameUp;
|
||||
}
|
||||
timeline.frames.add(frameOver);
|
||||
timeline.getFrames().add(frameOver);
|
||||
if (frameDown.layers.isEmpty()) {
|
||||
frameDown = frameOver;
|
||||
}
|
||||
timeline.frames.add(frameDown);
|
||||
timeline.getFrames().add(frameDown);
|
||||
if (frameHit.layers.isEmpty()) {
|
||||
frameHit = frameUp;
|
||||
}
|
||||
timeline.frames.add(frameHit);
|
||||
timeline.getFrames().add(frameHit);
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
timeline = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getSourceTag() {
|
||||
return this;
|
||||
|
||||
@@ -263,7 +263,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
fontBoundsTable.add(sis.readRECT("rect"));
|
||||
}
|
||||
int kerningCount = sis.readUI16("kerningCount");
|
||||
fontKerningTable = new ArrayList<KERNINGRECORD>();
|
||||
fontKerningTable = new ArrayList<>();
|
||||
for (int i = 0; i < kerningCount; i++) {
|
||||
fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record"));
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
fontBoundsTable.add(sis.readRECT("rect"));
|
||||
}
|
||||
int kerningCount = sis.readUI16("kerningCount");
|
||||
fontKerningTable = new ArrayList<KERNINGRECORD>();
|
||||
fontKerningTable = new ArrayList<>();
|
||||
for (int i = 0; i < kerningCount; i++) {
|
||||
fontKerningTable.add(sis.readKERNINGRECORD(fontFlagsWideCodes, "record"));
|
||||
}
|
||||
|
||||
@@ -84,16 +84,11 @@ public class DefineSpriteTag extends CharacterTag implements Container, Drawable
|
||||
@Override
|
||||
public Timeline getTimeline() {
|
||||
if (timeline == null) {
|
||||
timeline = new Timeline(swf, subTags, spriteId, getRect(new HashSet<BoundedTag>()));
|
||||
timeline = new Timeline(swf, this, subTags, spriteId, getRect(new HashSet<BoundedTag>()));
|
||||
}
|
||||
return timeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeline() {
|
||||
timeline = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return spriteId;
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags;
|
||||
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
@@ -199,5 +200,4 @@ public class DoActionTag extends Tag implements ASMSource {
|
||||
public Tag getSourceTag() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
|
||||
public String getExportFileName() {
|
||||
String expName = getExportName();
|
||||
if ((expName == null) || expName.isEmpty()) {
|
||||
return super.toString();
|
||||
return super.getExportFileName();
|
||||
}
|
||||
String[] pathParts;
|
||||
if (expName.contains(".")) {
|
||||
@@ -229,5 +229,4 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
|
||||
public Tag getSourceTag() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
@@ -21,7 +22,6 @@ import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ import java.util.List;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public interface ASMSource extends Exportable {
|
||||
|
||||
/**
|
||||
* Converts actions to ASM source
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public interface Exportable extends TreeItem {
|
||||
|
||||
public String getExportFileName();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS2Package implements TreeItem {
|
||||
|
||||
private final SWF swf;
|
||||
private final String name;
|
||||
private final AS2Package parent;
|
||||
|
||||
public Map<String, AS2Package> subPackages = new TreeMap<>();
|
||||
|
||||
public Map<String, ASMSource> scripts = new TreeMap<>();
|
||||
|
||||
public AS2Package(String name, AS2Package parent, SWF swf) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
this.swf = swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
public TreeItem getChild(int index) {
|
||||
if (index < subPackages.size()) {
|
||||
for (AS2Package subPackage : subPackages.values()) {
|
||||
if (index == 0) {
|
||||
return subPackage;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
index -= subPackages.size();
|
||||
|
||||
for (ASMSource pack : scripts.values()) {
|
||||
if (index == 0) {
|
||||
return pack;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChildCount() {
|
||||
return subPackages.size() + scripts.size();
|
||||
}
|
||||
|
||||
public int getIndexOfChild(TreeItem child) {
|
||||
int res = 0;
|
||||
if (child instanceof AS2Package) {
|
||||
for (AS2Package pkg : subPackages.values()) {
|
||||
if (pkg.equals(child)) {
|
||||
break;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
res = subPackages.size();
|
||||
for (ASMSource pack : scripts.values()) {
|
||||
if (pack.equals(child)) {
|
||||
break;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS3Package extends AS3ClassTreeItem {
|
||||
|
||||
private final SWF swf;
|
||||
public String packageName;
|
||||
public Map<String, AS3Package> subPackages = new TreeMap<>();
|
||||
public Map<String, ScriptPack> scripts = new TreeMap<>();
|
||||
|
||||
public AS3Package(String packageName, SWF swf) {
|
||||
super(packageName, null);
|
||||
this.swf = swf;
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
public AS3ClassTreeItem getChild(int index) {
|
||||
if (index < subPackages.size()) {
|
||||
for (AS3Package subPackage : subPackages.values()) {
|
||||
if (index == 0) {
|
||||
return subPackage;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
index -= subPackages.size();
|
||||
|
||||
for (ScriptPack pack : scripts.values()) {
|
||||
if (index == 0) {
|
||||
return pack;
|
||||
}
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChildCount() {
|
||||
return subPackages.size() + scripts.size();
|
||||
}
|
||||
|
||||
public int getIndexOfChild(AS3ClassTreeItem child) {
|
||||
int res = 0;
|
||||
if (child instanceof AS3Package) {
|
||||
for (AS3Package pkg : subPackages.values()) {
|
||||
if (pkg.equals(child)) {
|
||||
break;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
res = subPackages.size();
|
||||
for (ScriptPack pack : scripts.values()) {
|
||||
if (pack.equals(child)) {
|
||||
break;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packageName;
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,15 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
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.ShowFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import java.util.ArrayList;
|
||||
@@ -28,22 +31,25 @@ import java.util.TreeMap;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public class Frame implements TreeItem {
|
||||
|
||||
public final int frame;
|
||||
public TreeMap<Integer, DepthState> layers = new TreeMap<>();
|
||||
public TreeMap<Integer, DepthState> layers = new TreeMap<>();
|
||||
public RGB backgroundColor = new RGBA(0, 0, 0, 0);
|
||||
public Timeline timeline;
|
||||
public List<Integer> sounds = new ArrayList<>();
|
||||
public List<String> soundClasses = new ArrayList<>();
|
||||
public List<DoActionTag> actions = new ArrayList<>();
|
||||
public List<Tag> innerTags = new ArrayList<>();
|
||||
public ShowFrameTag showFrameTag = null; // can be null for the last frame
|
||||
|
||||
|
||||
public Frame(Timeline timeline, int frame) {
|
||||
this.timeline = timeline;
|
||||
this.frame = frame;
|
||||
}
|
||||
|
||||
|
||||
public Frame(Frame obj, int frame) {
|
||||
this.frame = frame;
|
||||
layers = new TreeMap<>();
|
||||
backgroundColor = obj.backgroundColor;
|
||||
timeline = obj.timeline;
|
||||
@@ -52,4 +58,14 @@ public class Frame {
|
||||
}
|
||||
//Do not copy sounds
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return timeline.swf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "frame " + (frame + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,31 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS2PackageNodeItem implements TreeItem {
|
||||
public class FrameScript implements TreeItem {
|
||||
|
||||
private final SWF swf;
|
||||
public String packageName;
|
||||
private final Frame frame;
|
||||
|
||||
public AS2PackageNodeItem(String packageName, SWF swf) {
|
||||
public FrameScript(SWF swf, Frame frame) {
|
||||
this.swf = swf;
|
||||
this.packageName = packageName;
|
||||
this.frame = frame;
|
||||
}
|
||||
|
||||
|
||||
public Frame getFrame() {
|
||||
return frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
@@ -38,6 +44,6 @@ public class AS2PackageNodeItem implements TreeItem {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packageName;
|
||||
return frame.toString();
|
||||
}
|
||||
}
|
||||
@@ -14,49 +14,44 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class FrameNodeItem implements TreeItem {
|
||||
|
||||
public class TagScript implements TreeItem {
|
||||
|
||||
private final SWF swf;
|
||||
private final int frame;
|
||||
private final Timelined parent;
|
||||
private final boolean display;
|
||||
|
||||
public FrameNodeItem(SWF swf, int frame, Timelined parent, boolean display) {
|
||||
private final Tag tag;
|
||||
private final List<TreeItem> frames;
|
||||
|
||||
public TagScript(SWF swf, Tag tag, List<TreeItem> frames) {
|
||||
this.swf = swf;
|
||||
this.frame = frame;
|
||||
this.parent = parent;
|
||||
this.display = display;
|
||||
this.tag = tag;
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public List<TreeItem> getFrames() {
|
||||
return frames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
}
|
||||
|
||||
public boolean isDisplayed() {
|
||||
return display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "frame " + (frame + 1);
|
||||
}
|
||||
|
||||
public int getFrame() {
|
||||
return frame;
|
||||
}
|
||||
|
||||
public Timelined getParent() {
|
||||
return parent;
|
||||
return tag.toString();
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,13 @@ package com.jpexs.decompiler.flash.timeline;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.tags.DoActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
|
||||
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.StartSound2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.StartSoundTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
@@ -52,15 +54,59 @@ import java.util.Stack;
|
||||
*/
|
||||
public class Timeline {
|
||||
|
||||
public List<Frame> frames = new ArrayList<>();
|
||||
public int id;
|
||||
public SWF swf;
|
||||
public RECT displayRect;
|
||||
public int frameRate;
|
||||
public Timelined timelined;
|
||||
public Tag parentTag;
|
||||
public List<Tag> tags;
|
||||
public Map<Integer, Integer> depthMaxFrame = new HashMap<>();
|
||||
|
||||
public int getMaxDepth() {
|
||||
private final List<Frame> frames = new ArrayList<>();
|
||||
private final Map<Integer, Integer> depthMaxFrame = new HashMap<>();
|
||||
private final List<ASMSource> asmSources = new ArrayList<>();
|
||||
private final Map<ASMSource, Integer> actionFrames = new HashMap<>();
|
||||
private AS2Package as2RootPackage;
|
||||
private final List<Tag> otherTags = new ArrayList<>();
|
||||
private boolean initialized = false;
|
||||
|
||||
private void ensureInitialized() {
|
||||
if (!initialized) {
|
||||
initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Frame> getFrames() {
|
||||
ensureInitialized();
|
||||
return frames;
|
||||
}
|
||||
|
||||
public AS2Package getAS2RootPackage() {
|
||||
ensureInitialized();
|
||||
return as2RootPackage;
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> getDepthMaxFrame() {
|
||||
ensureInitialized();
|
||||
return depthMaxFrame;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
initialized = false;
|
||||
frames.clear();
|
||||
depthMaxFrame.clear();
|
||||
asmSources.clear();
|
||||
actionFrames.clear();
|
||||
otherTags.clear();
|
||||
as2RootPackage = new AS2Package(null, null, swf);
|
||||
}
|
||||
|
||||
public final int getMaxDepth() {
|
||||
ensureInitialized();
|
||||
return getMaxDepthInternal();
|
||||
}
|
||||
|
||||
public final int getMaxDepthInternal() {
|
||||
int max_depth = 0;
|
||||
for (Frame f : frames) {
|
||||
for (int depth : f.layers.keySet()) {
|
||||
@@ -76,39 +122,49 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public int getFrameCount() {
|
||||
return frames.size();
|
||||
return getFrames().size();
|
||||
}
|
||||
|
||||
public int getFrameForAction(ASMSource asm) {
|
||||
Integer frame = actionFrames.get(asm);
|
||||
if (frame == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public Timeline(SWF swf) {
|
||||
this(swf, swf.tags, 0, swf.displayRect);
|
||||
this(swf, null, swf.tags, 0, swf.displayRect);
|
||||
}
|
||||
|
||||
public Timeline(SWF swf, List<Tag> tags, int id, RECT displayRect) {
|
||||
public Timeline(SWF swf, Tag parentTag, List<Tag> tags, int id, RECT displayRect) {
|
||||
this.id = id;
|
||||
this.swf = swf;
|
||||
this.displayRect = displayRect;
|
||||
this.frameRate = swf.frameRate;
|
||||
this.timelined = parentTag == null ? swf : (Timelined) parentTag;
|
||||
this.parentTag = parentTag;
|
||||
this.tags = tags;
|
||||
Frame frame = new Frame(this);
|
||||
as2RootPackage = new AS2Package(null, null, swf);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
int frameIdx = 0;
|
||||
Frame frame = new Frame(this, frameIdx++);
|
||||
boolean tagAdded = false;
|
||||
for (Tag t : tags) {
|
||||
tagAdded = true;
|
||||
if (ShowFrameTag.isNestedTagType(t.getId())) {
|
||||
frame.innerTags.add(t);
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof StartSoundTag) {
|
||||
frame.sounds.add(((StartSoundTag) t).soundId);
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof StartSound2Tag) {
|
||||
} else if (t instanceof StartSound2Tag) {
|
||||
frame.soundClasses.add(((StartSound2Tag) t).soundClassName);
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof SetBackgroundColorTag) {
|
||||
} else if (t instanceof SetBackgroundColorTag) {
|
||||
frame.backgroundColor = ((SetBackgroundColorTag) t).backgroundColor;
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
} else if (t instanceof PlaceObjectTypeTag) {
|
||||
PlaceObjectTypeTag po = (PlaceObjectTypeTag) t;
|
||||
int depth = po.getDepth();
|
||||
if (!frame.layers.containsKey(depth)) {
|
||||
@@ -168,30 +224,30 @@ public class Timeline {
|
||||
fl.clipDepth = po.getClipDepth();
|
||||
}
|
||||
fl.key = true;
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof RemoveTag) {
|
||||
} else if (t instanceof RemoveTag) {
|
||||
RemoveTag r = (RemoveTag) t;
|
||||
int depth = r.getDepth();
|
||||
frame.layers.remove(depth);
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof DoActionTag) {
|
||||
frame.action = (DoActionTag) t;
|
||||
tagAdded = true;
|
||||
}
|
||||
if (t instanceof ShowFrameTag) {
|
||||
} else if (t instanceof DoActionTag) {
|
||||
frame.actions.add((DoActionTag) t);
|
||||
actionFrames.put((DoActionTag) t, frame.frame);
|
||||
} else if (t instanceof ShowFrameTag) {
|
||||
frame.showFrameTag = (ShowFrameTag) t;
|
||||
frames.add(frame);
|
||||
frame = new Frame(frame);
|
||||
frame = new Frame(frame, frameIdx++);
|
||||
tagAdded = false;
|
||||
} else if (t instanceof ASMSource) {
|
||||
asmSources.add((ASMSource) t);
|
||||
} else {
|
||||
otherTags.add(t);
|
||||
}
|
||||
}
|
||||
if (tagAdded) {
|
||||
frames.add(frame);
|
||||
}
|
||||
|
||||
detectTweens();
|
||||
for (int d = 1; d <= getMaxDepth(); d++) {
|
||||
for (int d = 1; d <= getMaxDepthInternal(); d++) {
|
||||
for (int f = frames.size() - 1; f >= 0; f--) {
|
||||
if (frames.get(f).layers.get(d) != null) {
|
||||
depthMaxFrame.put(d, f + 1);
|
||||
@@ -199,6 +255,10 @@ public class Timeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createASPackages();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private boolean compare(int a, int b, int c, int tolerance) {
|
||||
@@ -206,7 +266,7 @@ public class Timeline {
|
||||
}
|
||||
|
||||
private void detectTweens() {
|
||||
for (int d = 1; d <= getMaxDepth(); d++) {
|
||||
for (int d = 1; d <= getMaxDepthInternal(); d++) {
|
||||
int characterId = -1;
|
||||
int len = 0;
|
||||
for (int f = 0; f <= frames.size(); f++) {
|
||||
@@ -237,6 +297,33 @@ public class Timeline {
|
||||
}
|
||||
}
|
||||
|
||||
private void createASPackages() {
|
||||
for (ASMSource asm : asmSources) {
|
||||
if (asm instanceof DoInitActionTag) {
|
||||
DoInitActionTag initAction = (DoInitActionTag) asm;
|
||||
String path = initAction.getExportName();
|
||||
if (path == null || path.isEmpty()) {
|
||||
path = initAction.getExportFileName();
|
||||
}
|
||||
|
||||
String[] pathParts = path.contains(".") ? path.split("\\.") : new String[]{path};
|
||||
AS2Package pkg = as2RootPackage;
|
||||
for (int pos = 0; pos < pathParts.length - 1; pos++) {
|
||||
String pathPart = pathParts[pos];
|
||||
AS2Package subPkg = pkg.subPackages.get(pathPart);
|
||||
if (subPkg == null) {
|
||||
subPkg = new AS2Package(pathPart, pkg, swf);
|
||||
pkg.subPackages.put(pathPart, subPkg);
|
||||
}
|
||||
|
||||
pkg = subPkg;
|
||||
}
|
||||
|
||||
pkg.scripts.put(pathParts[pathParts.length - 1], asm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getNeededCharacters(Set<Integer> usedCharacters) {
|
||||
for (int i = 0; i < getFrameCount(); i++) {
|
||||
getNeededCharacters(i, usedCharacters);
|
||||
@@ -244,13 +331,13 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public void getNeededCharacters(List<Integer> frames, Set<Integer> usedCharacters) {
|
||||
for (int frame = 0; frame < frames.size(); frame++) {
|
||||
for (int frame = 0; frame < getFrameCount(); frame++) {
|
||||
getNeededCharacters(frame, usedCharacters);
|
||||
}
|
||||
}
|
||||
|
||||
public void getNeededCharacters(int frame, Set<Integer> usedCharacters) {
|
||||
Frame frameObj = frames.get(frame);
|
||||
Frame frameObj = getFrames().get(frame);
|
||||
for (int depth : frameObj.layers.keySet()) {
|
||||
DepthState layer = frameObj.layers.get(depth);
|
||||
if (layer.characterId != -1) {
|
||||
@@ -285,10 +372,10 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public void getSounds(int frame, int time, DepthState stateUnderCursor, int mouseButton, List<Integer> sounds, List<String> soundClasses) {
|
||||
Frame fr = this.frames.get(frame);
|
||||
Frame fr = getFrames().get(frame);
|
||||
sounds.addAll(fr.sounds);
|
||||
soundClasses.addAll(fr.soundClasses);
|
||||
int maxDepth = this.getMaxDepth();
|
||||
int maxDepth = getMaxDepthInternal();
|
||||
for (int d = maxDepth; d >= 0; d--) {
|
||||
DepthState ds = fr.layers.get(d);
|
||||
if (ds != null) {
|
||||
@@ -317,9 +404,9 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public void getObjectsOutlines(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation, List<DepthState> objs, List<Shape> outlines) {
|
||||
Frame fr = this.frames.get(frame);
|
||||
Frame fr = getFrames().get(frame);
|
||||
Stack<Clip> clips = new Stack<>();
|
||||
int maxDepth = this.getMaxDepth();
|
||||
int maxDepth = getMaxDepthInternal();
|
||||
for (int d = maxDepth; d >= 0; d--) {
|
||||
Clip currentClip = null;
|
||||
for (int i = clips.size() - 1; i >= 0; i--) {
|
||||
@@ -386,10 +473,10 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public Shape getOutline(int frame, int time, int ratio, DepthState stateUnderCursor, int mouseButton, Matrix transformation) {
|
||||
Frame fr = this.frames.get(frame);
|
||||
Frame fr = getFrames().get(frame);
|
||||
Area area = new Area();
|
||||
Stack<Clip> clips = new Stack<>();
|
||||
int maxDepth = this.getMaxDepth();
|
||||
int maxDepth = getMaxDepthInternal();
|
||||
for (int d = maxDepth; d >= 0; d--) {
|
||||
Clip currentClip = null;
|
||||
for (int i = clips.size() - 1; i >= 0; i--) {
|
||||
@@ -448,7 +535,7 @@ public class Timeline {
|
||||
}
|
||||
|
||||
public boolean isSingleFrame() {
|
||||
for (int i = 0; i < frames.size(); i++) {
|
||||
for (int i = 0; i < getFrameCount(); i++) {
|
||||
if (!isSingleFrame(i)) {
|
||||
return false;
|
||||
}
|
||||
@@ -458,7 +545,7 @@ public class Timeline {
|
||||
|
||||
private boolean isSingleFrame(int frame) {
|
||||
Frame frameObj = frames.get(frame);
|
||||
int maxDepth = this.getMaxDepth();
|
||||
int maxDepth = getMaxDepthInternal();
|
||||
for (int i = 1; i <= maxDepth; i++) {
|
||||
if (!frameObj.layers.containsKey(i)) {
|
||||
continue;
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.timeline;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
@@ -24,6 +25,4 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
public interface Timelined extends BoundedTag {
|
||||
|
||||
public Timeline getTimeline();
|
||||
public Timeline getTimeline();
|
||||
|
||||
}
|
||||
|
||||
@@ -12,32 +12,34 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
*/
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS3PackageNodeItem implements TreeElementItem {
|
||||
public abstract class AS3ClassTreeItem implements TreeItem {
|
||||
|
||||
private final String name;
|
||||
private final String path;
|
||||
|
||||
private final SWF swf;
|
||||
public String packageName;
|
||||
|
||||
public AS3PackageNodeItem(String packageName, SWF swf) {
|
||||
this.swf = swf;
|
||||
this.packageName = packageName;
|
||||
public AS3ClassTreeItem(String name, String path) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SWF getSwf() {
|
||||
return swf;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return packageName;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -12,25 +12,29 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
*/
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class StringItem implements TreeItem {
|
||||
public class FolderItem implements TreeItem {
|
||||
|
||||
public SWF swf;
|
||||
private final String str;
|
||||
private final String name;
|
||||
public final List<TreeItem> subItems;
|
||||
|
||||
public StringItem(String str, String name, SWF swf) {
|
||||
public FolderItem(String str, String name, SWF swf, List<TreeItem> subItems) {
|
||||
this.swf = swf;
|
||||
this.str = str;
|
||||
this.name = name;
|
||||
this.subItems = subItems;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -41,5 +41,4 @@ public class HeaderItem implements TreeItem {
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFContainerItem;
|
||||
import com.jpexs.decompiler.flash.SWFSourceInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -27,7 +29,7 @@ import java.util.ListIterator;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
*/
|
||||
public class SWFList implements List<SWF>, SWFContainerItem {
|
||||
|
||||
public String name;
|
||||
public boolean isBundle;
|
||||
@@ -39,6 +41,11 @@ public class SWFList implements List<SWF>, TreeItem {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<SWF> iterator() {
|
||||
return swfs.iterator();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface ScriptContainer {
|
||||
|
||||
public Map<String, TreeItem> getInnerScripts();
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treeitems;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.treeitems.AS2PackageNodeItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AS2PackageNode extends TreeNode {
|
||||
|
||||
public AS2PackageNode(AS2PackageNodeItem item) {
|
||||
super(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AS2PackageNodeItem getItem() {
|
||||
return (AS2PackageNodeItem) item;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ContainerNode extends TreeNode {
|
||||
|
||||
public ContainerNode(ContainerItem item) {
|
||||
super(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerItem getItem() {
|
||||
return (ContainerItem) item;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.treeitems.FrameNodeItem;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class FrameNode extends TreeNode {
|
||||
|
||||
public boolean scriptsNode = false;
|
||||
|
||||
public FrameNode(FrameNodeItem item, List<Tag> innerTags, boolean scriptsNode) {
|
||||
super(item);
|
||||
this.scriptsNode = scriptsNode;
|
||||
if (innerTags != null) {
|
||||
for (Tag tag : innerTags) {
|
||||
subNodes.add(new TagNode(tag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameNodeItem getItem() {
|
||||
return (FrameNodeItem) item;
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.treeitems.HeaderItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class HeaderNode extends TreeNode {
|
||||
|
||||
public HeaderNode(HeaderItem item) {
|
||||
super(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderItem getItem() {
|
||||
return (HeaderItem) item;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.Exportable;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TagNode extends ContainerNode {
|
||||
|
||||
public TagNode(Tag tag) {
|
||||
super(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getItem() {
|
||||
return (Tag) item;
|
||||
}
|
||||
|
||||
public static int getTagCountRecursive(List<TreeNode> nodeList) {
|
||||
int count = 0;
|
||||
|
||||
for (TreeNode node : nodeList) {
|
||||
if (node.item instanceof ASMSource) {
|
||||
count += 1;
|
||||
}
|
||||
if (!node.subNodes.isEmpty()) {
|
||||
count += getTagCountRecursive(node.subNodes);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static List<File> exportNodeAS(final AbortRetryIgnoreHandler handler, final List<TreeNode> nodesList, final List<TreeNode> nodesToExport, final String outdir, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
|
||||
try {
|
||||
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
|
||||
|
||||
@Override
|
||||
public List<File> call() throws Exception {
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
int totalCount = TagNode.getTagCountRecursive(nodesToExport);
|
||||
return exportNodeAS(handler, nodesList, nodesToExport, false, outdir, exportMode, cnt, totalCount, ev);
|
||||
}
|
||||
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
|
||||
return result;
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private static List<File> exportNodeAS(AbortRetryIgnoreHandler handler, List<TreeNode> nodesList, List<TreeNode> nodesToExport, boolean exportAll, String outdir, ScriptExportMode exportMode, AtomicInteger index, int count, EventListener ev) throws IOException {
|
||||
File dir = new File(outdir);
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
outdir += File.separator;
|
||||
}
|
||||
List<String> existingNames = new ArrayList<>();
|
||||
for (TreeNode node : nodesList) {
|
||||
String name = "";
|
||||
if (node.item instanceof Exportable) {
|
||||
name = Helper.makeFileName(((Exportable) node.item).getExportFileName());
|
||||
} else {
|
||||
name = Helper.makeFileName(node.item.toString());
|
||||
}
|
||||
int i = 1;
|
||||
String baseName = name;
|
||||
while (existingNames.contains(name)) {
|
||||
i++;
|
||||
name = baseName + "_" + i;
|
||||
}
|
||||
existingNames.add(name);
|
||||
boolean exportNode = nodesToExport.contains(node);
|
||||
if (node.item instanceof ASMSource && (exportAll || exportNode)) {
|
||||
boolean retry;
|
||||
do {
|
||||
retry = false;
|
||||
try {
|
||||
int currentIndex = index.getAndIncrement();
|
||||
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdirs()) {
|
||||
if (!dir.exists()) {
|
||||
throw new IOException("Cannot create directory " + outdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String f = outdir + name + ".as";
|
||||
if (ev != null) {
|
||||
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
File file = new File(f);
|
||||
ASMSource asm = ((ASMSource) node.item);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
|
||||
if (exportMode == ScriptExportMode.HEX) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getActionBytesAsHex(writer);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else if (exportMode != ScriptExportMode.AS) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getASMSource(exportMode, writer, null);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else {
|
||||
List<Action> as = asm.getActions();
|
||||
Action.setActionsAddresses(as, 0);
|
||||
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
|
||||
}
|
||||
}
|
||||
|
||||
long stopTime = System.currentTimeMillis();
|
||||
|
||||
if (ev != null) {
|
||||
long time = stopTime - startTime;
|
||||
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
|
||||
}
|
||||
|
||||
ret.add(file);
|
||||
} catch (InterruptedException ex) {
|
||||
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
|
||||
Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
|
||||
if (handler != null) {
|
||||
int action = handler.getNewInstance().handle(ex);
|
||||
switch (action) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
case AbortRetryIgnoreHandler.RETRY:
|
||||
retry = true;
|
||||
break;
|
||||
case AbortRetryIgnoreHandler.IGNORE:
|
||||
retry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
}
|
||||
if (!node.subNodes.isEmpty()) {
|
||||
ret.addAll(exportNodeAS(handler, node.subNodes, nodesToExport, exportAll || exportNode, outdir + name, exportMode, index, count, ev));
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class TreeNode {
|
||||
|
||||
protected TreeItem item;
|
||||
public List<TreeNode> subNodes;
|
||||
|
||||
public TreeNode(TreeItem item) {
|
||||
if (item == null) {
|
||||
throw new Error("TreeItem should not be null.");
|
||||
}
|
||||
this.item = item;
|
||||
this.subNodes = new ArrayList<>();
|
||||
}
|
||||
|
||||
public TreeItem getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (item == null) {
|
||||
Logger.getLogger(TreeNode.class.getName()).log(Level.FINE, "Tree item is null");
|
||||
return null;
|
||||
}
|
||||
return item.toString();
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.types;
|
||||
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
|
||||
@@ -284,5 +284,4 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S
|
||||
public Tag getSourceTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.NeedsCharacters;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
|
||||
@@ -59,7 +59,7 @@ public abstract class GraphTargetItem implements Serializable {
|
||||
public List<GraphSourceItemPos> moreSrc = new ArrayList<>();
|
||||
public GraphPart firstPart;
|
||||
public GraphTargetItem value;
|
||||
protected Map<String,String> srcData = new HashMap<String, String>();
|
||||
protected Map<String,String> srcData = new HashMap<>();
|
||||
|
||||
public GraphPart getFirstPart() {
|
||||
if (value == null) {
|
||||
|
||||
Reference in New Issue
Block a user