AS3 Add class

This commit is contained in:
Jindra Petřík
2021-02-15 18:55:38 +01:00
parent e12eb2af6e
commit a738171637
4 changed files with 119 additions and 11 deletions

View File

@@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file.
- #1202 Check for modifications outside FFDec and ask user to reload
- #1155, #1602 AS3 remove trait button
- #1260, #1438 AS1/2 direct editing on(xxx), onClipEvent(xxx) handlers
- AS1/2 Add script (context menu on scripts folder)
- #1409, #1429, #1573, #1598 AS1/2/3 Add script/class (context menu on scripts folder)
### Fixed
- #1298 AS1/2 properly decompiled setProperty/getProperty

View File

@@ -783,4 +783,6 @@ button.removetrait = Remove trait
message.confirm.removetrait = Do you really want to remove selected trait?
contextmenu.addScript = Add script
contextmenu.addScript = Add script
contextmenu.addClass = Add class

View File

@@ -761,4 +761,6 @@ button.removetrait = Odstranit vlastnost
message.confirm.removetrait = Opravdu chcete odstranit vybranou vlastnost?
contextmenu.addScript = P\u0159idat skript
contextmenu.addScript = P\u0159idat skript
contextmenu.addClass = P\u0159idat t\u0159\u00eddu

View File

@@ -16,8 +16,12 @@
*/
package com.jpexs.decompiler.flash.gui.tagtree;
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser;
@@ -26,11 +30,15 @@ import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.MainPanel;
import com.jpexs.decompiler.flash.gui.ReplaceCharacterDialog;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
import com.jpexs.decompiler.flash.gui.action.AddScriptDialog;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
import com.jpexs.decompiler.flash.tags.DoABCTag;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
@@ -50,6 +58,7 @@ import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.FrameScript;
import com.jpexs.decompiler.flash.timeline.TagScript;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
import com.jpexs.decompiler.flash.treeitems.FolderItem;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
@@ -58,6 +67,7 @@ import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD;
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.Helper;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
@@ -131,13 +141,13 @@ public class TagTreeContextMenu extends JPopupMenu {
private JMenuItem openSWFInsideTagMenuItem;
private JMenuItem addScriptMenuItem;
private JMenuItem addAs12ScriptMenuItem;
private JMenuItem addAs3ClassMenuItem;
public TagTreeContextMenu(final TagTree tagTree, MainPanel mainPanel) {
this.mainPanel = mainPanel;
this.tagTree = tagTree;
expandRecursiveMenuItem = new JMenuItem(mainPanel.translate("contextmenu.expandAll"));
expandRecursiveMenuItem.addActionListener(this::expandRecursiveActionPerformed);
add(expandRecursiveMenuItem);
@@ -214,9 +224,14 @@ public class TagTreeContextMenu extends JPopupMenu {
add(openSWFInsideTagMenuItem);
openSWFInsideTagMenuItem.addActionListener(this::openSwfInsideActionPerformed);
addScriptMenuItem = new JMenuItem(mainPanel.translate("contextmenu.addScript"));
addScriptMenuItem.addActionListener(this::addScriptActionPerformed);
add(addScriptMenuItem);
addAs12ScriptMenuItem = new JMenuItem(mainPanel.translate("contextmenu.addScript"));
addAs12ScriptMenuItem.addActionListener(this::addAs12ScriptActionPerformed);
add(addAs12ScriptMenuItem);
addAs3ClassMenuItem = new JMenuItem(mainPanel.translate("contextmenu.addClass"));
addAs3ClassMenuItem.addActionListener(this::addAs3ClassActionPerformed);
add(addAs3ClassMenuItem);
tagTree.addMouseListener(new MouseAdapter() {
@Override
@@ -341,7 +356,8 @@ public class TagTreeContextMenu extends JPopupMenu {
copyTagMenu.setVisible(false);
copyTagWithDependenciesMenu.setVisible(false);
openSWFInsideTagMenuItem.setVisible(false);
addScriptMenuItem.setVisible(false);
addAs12ScriptMenuItem.setVisible(false);
addAs3ClassMenuItem.setVisible(false);
if (allSelectedIsTag) {
boolean canUndo = false;
@@ -391,9 +407,12 @@ public class TagTreeContextMenu extends JPopupMenu {
if (firstItem instanceof FolderItem) {
if (((FolderItem) firstItem).getName().equals(TagTreeModel.FOLDER_SCRIPTS)) {
addScriptMenuItem.setVisible(true);
addAs12ScriptMenuItem.setVisible(true);
}
}
if (firstItem instanceof ClassesListTreeModel) {
addAs3ClassMenuItem.setVisible(true);
}
if (firstItem instanceof CharacterTag) {
replaceWithTagMenuItem.setVisible(true);
@@ -729,7 +748,92 @@ public class TagTreeContextMenu extends JPopupMenu {
View.expandTreeNodes(tagTree, path, true);
}
private void addScriptActionPerformed(ActionEvent evt) {
private void addAs3ClassActionPerformed(ActionEvent evt) {
List<TreeItem> sel = tagTree.getSelected();
if (!sel.isEmpty()) {
if (sel.get(0) instanceof ClassesListTreeModel) {
String className = View.showInputDialog(AppDialog.translateForDialog("classname", AddScriptDialog.class), "");
if (className == null || className.isEmpty()) {
return;
}
ClassesListTreeModel cl = (ClassesListTreeModel) sel.get(0);
SWF swf = cl.getSwf();
DoABC2Tag doAbc = new DoABC2Tag(swf);
doAbc.name = className;
List<ABC> abcs = new ArrayList<>();
for (ABCContainerTag ct : swf.getAbcList()) {
abcs.add(ct.getABC());
}
ReadOnlyTagList tags = swf.getTags();
int insertPos = -1;
for (int i = 0; i < tags.size(); i++) {
if (tags.get(i) instanceof ShowFrameTag) {
insertPos = i;
break;
}
}
if (insertPos == -1) {
insertPos = tags.size();
}
swf.addTag(insertPos, doAbc);
String pkg = className.contains(".") ? className.substring(0, className.lastIndexOf(".")) : "";
String classSimpleName = className.contains(".") ? className.substring(className.lastIndexOf(".") + 1) : className;
String fileName = className.replace(".", "/");
String pkgParts[] = new String[0];
if (!pkg.isEmpty()) {
if (pkg.contains(".")) {
pkgParts = pkg.split("\\.");
} else {
pkgParts = new String[]{pkg};
}
}
try {
ActionScript3Parser parser = new ActionScript3Parser(doAbc.getABC(), abcs);
DottedChain dc = new DottedChain(pkgParts, "");
String script = "package " + dc.toPrintableString(true) + " {"
+ "public class " + IdentifiersDeobfuscation.printIdentifier(true, classSimpleName) + " {"
+ " }"
+ "}";
parser.addScript(script, false, fileName, 0, 0);
} catch (IOException | InterruptedException | AVM2ParseException | CompilationException ex) {
Logger.getLogger(TagTreeContextMenu.class.getName()).log(Level.SEVERE, "Error during script compilation", ex);
}
doAbc.setModified(true);
swf.clearAllCache();
swf.setModified(true);
mainPanel.refreshTree(swf);
Object item = mainPanel.tagTree.getModel().getScriptsNode(swf);
String parts[] = className.contains(".") ? className.split("\\.") : new String[]{className};
TreePath selection = mainPanel.tagTree.getSelectionPath();
TreePath swfPath = selection.getParentPath();
TreePath scriptsPath = swfPath.pathByAddingChild(item);
TreePath classPath = scriptsPath;
for (int i = 0; i < parts.length; i++) {
for (TreeItem ti : tagTree.getModel().getAllChildren(item)) {
if (ti instanceof AS3ClassTreeItem) {
AS3ClassTreeItem cti = (AS3ClassTreeItem) ti;
if (parts[i].equals(cti.getNameWithNamespaceSuffix())) {
classPath = classPath.pathByAddingChild(ti);
item = ti;
break;
}
}
}
}
mainPanel.tagTree.setSelectionPath(classPath);
}
}
}
private void addAs12ScriptActionPerformed(ActionEvent evt) {
List<TreeItem> sel = tagTree.getSelected();
if (!sel.isEmpty()) {
if (sel.get(0) instanceof FolderItem) {