Added #1290 Export to FlashDevelop project

This commit is contained in:
Jindra Petřík
2024-08-02 09:14:01 +02:00
parent 31099c64e8
commit c6790f70cf
24 changed files with 380 additions and 50 deletions

View File

@@ -327,6 +327,7 @@ public class ScriptPack extends AS3ClassTreeItem {
convertData.ignoreFrameScripts = exportSettings.ignoreFrameScripts;
convertData.exportEmbed = exportSettings.exportEmbed;
convertData.exportEmbedFlaMode = exportSettings.exportEmbedFlaMode;
convertData.assetsDir = exportSettings.assetsDir;
toSource(abcIndex, writer2, abc.script_info.get(scriptIndex).traits.traits, convertData, exportSettings.mode, parallel, exportSettings.ignoreFrameScripts);
} catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "The file path is probably too long", ex);

View File

@@ -38,6 +38,8 @@ public class ConvertData {
public boolean exportEmbed;
public boolean exportEmbedFlaMode;
public String assetsDir = "/_assets/";
public ConvertData() {
deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0;

View File

@@ -91,9 +91,9 @@ public class InstanceInfo {
return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames);
}
public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List<DottedChain> fullyQualifiedNames, boolean allowPrivate, boolean allowEmbed) {
public GraphTextWriter getClassHeaderStr(String assetsDir, GraphTextWriter writer, ABC abc, List<DottedChain> fullyQualifiedNames, boolean allowPrivate, boolean allowEmbed) {
final String ASSETS_DIR = "/_assets/";
final String ASSETS_DIR = assetsDir; // "/_assets/";
if (allowEmbed) {
if (abc.getSwf() != null) {
String className = getName(abc.constants).getNameWithNamespace(abc.constants, false).toRawString();
@@ -106,14 +106,15 @@ public class InstanceInfo {
fileName = Helper.makeFileName(fileName);
if (ct instanceof DefineBinaryDataTag) {
writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ".bin\", mimeType=\"application/octet-stream\")]").newLine();
DefineBinaryDataTag db = (DefineBinaryDataTag) ct;
writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + (db.innerSwf != null ? ".swf" : ".bin")+ "\", mimeType=\"application/octet-stream\")]").newLine();
}
if (ct instanceof ImageTag) {
ImageTag it = (ImageTag) ct;
writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + fileName + ((ImageTag) ct).getImageFormat().getExtension() + "\")]").newLine();
}
if (ct instanceof DefineSpriteTag) {
writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + "assets.swf\", symbol=\"" + Helper.escapeActionScriptString(className) + "\")]").newLine();
writer.appendNoHilight("[Embed(source=\"" + ASSETS_DIR + "assets.swf\", symbol=\"" + "symbol" + ct.getCharacterId() + "\")]").newLine();
}
if (ct instanceof DefineSoundTag) {
//should be mp3, otherwise it won't work. Should we convert this?

View File

@@ -108,7 +108,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
@Override
public GraphTextWriter toStringHeader(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel, boolean insideInterface) {
abc.instance_info.get(class_info).getClassHeaderStr(writer, abc, fullyQualifiedNames, false, false /*??*/);
abc.instance_info.get(class_info).getClassHeaderStr(convertData.assetsDir, writer, abc, fullyQualifiedNames, false, false /*??*/);
return writer;
}
@@ -170,7 +170,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
}
//class header
instanceInfo.getClassHeaderStr(writer, abc, fullyQualifiedNames, false, allowEmbed);
instanceInfo.getClassHeaderStr(convertData.assetsDir, writer, abc, fullyQualifiedNames, false, allowEmbed);
writer.endTrait();
writer.startBlock();
writer.startClass(class_info);

View File

@@ -70,6 +70,7 @@ import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.FileAttributesTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
@@ -485,7 +486,7 @@ public class AS3ScriptExporter {
return ret;
}
final String ASSETS_DIR = outdir + "/_assets/";
final String ASSETS_DIR = outdir + exportSettings.assetsDir;
List<Tag> exportTagList = new ArrayList<>();
List<DefineSpriteTag> spriteTagList = new ArrayList<>();
@@ -592,11 +593,9 @@ public class AS3ScriptExporter {
dbj2.writeTag(sos2);
} else {
ct.writeTag(sos2);
}
for (String cls : ct.getClassNames()) {
symbolClassIds.add(ct.getCharacterId());
symbolClassNames.add(cls);
}
}
symbolClassIds.add(ct.getCharacterId());
symbolClassNames.add("symbol" + ct.getCharacterId());
List<CharacterIdTag> cidTags = swf.getCharacterIdTags(n);
for (CharacterIdTag t : cidTags) {
if (t instanceof PlaceObjectTypeTag) {
@@ -609,10 +608,10 @@ public class AS3ScriptExporter {
}
}
SymbolClassTag sc = new SymbolClassTag(swf);
sc.names = symbolClassNames;
sc.tags = symbolClassIds;
sc.writeTag(sos2);
ExportAssetsTag ea = new ExportAssetsTag(swf);
ea.names = symbolClassNames;
ea.tags = symbolClassIds;
ea.writeTag(sos2);
new ShowFrameTag(swf).writeTag(sos2);
new EndTag(swf).writeTag(sos2);

View File

@@ -40,7 +40,9 @@ public class ScriptExportSettings {
public boolean exportEmbedFlaMode;
public boolean resampleWav;
public String assetsDir;
public ScriptExportSettings(
ScriptExportMode mode,
boolean singleFile,
@@ -48,6 +50,20 @@ public class ScriptExportSettings {
boolean exportEmbed,
boolean exportEmbedFlaMode,
boolean resampleWav
) {
this(mode, singleFile, ignoreFrameScripts, exportEmbed, exportEmbedFlaMode, resampleWav, "/_assets/");
}
public ScriptExportSettings(
ScriptExportMode mode,
boolean singleFile,
boolean ignoreFrameScripts,
boolean exportEmbed,
boolean exportEmbedFlaMode,
boolean resampleWav,
String assetsDir
) {
this.mode = mode;
this.singleFile = singleFile;
@@ -55,6 +71,7 @@ public class ScriptExportSettings {
this.exportEmbed = exportEmbed;
this.exportEmbedFlaMode = exportEmbedFlaMode;
this.resampleWav = resampleWav;
this.assetsDir = assetsDir;
}
public String getFileExtension() {

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2010-2024 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.swf;
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.xfl.XFLXmlWriter;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.XmlPrettyFormat;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.XMLStreamException;
/**
*
* @author JPEXS
*/
public class SwfFlashDevelopExporter {
private static String doubleToString(double d) {
String ds = "" + d;
if (ds.endsWith(".0")) {
ds = ds.substring(0, ds.length() - 2);
}
return ds;
}
public void exportFlashDevelopProject(SWF swf, File outFile, AbortRetryIgnoreHandler handler) throws IOException {
exportFlashDevelopProject(swf, outFile, handler, null);
}
public void exportFlashDevelopProject(SWF swf, File outFile, AbortRetryIgnoreHandler handler, EventListener eventListener) throws IOException {
if (!swf.isAS3()) {
throw new IllegalArgumentException("SWF must be AS3");
}
String simpleName = outFile.getName();
if (simpleName.contains(".")) {
simpleName = simpleName.substring(0, simpleName.lastIndexOf("."));
}
SetBackgroundColorTag bgColorTag = swf.getBackgroundColor();
String documentClass = swf.getDocumentClass();
String srcPath = "src";
String project = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<project version=\"2\">\n"
+ " <!-- Generated with " + ApplicationInfo.applicationVerName +" -->\n"
+ " <!-- Output SWF options -->\n"
+ " <output>\n"
+ " <movie outputType=\"Application\" />\n"
+ " <movie input=\"\" />\n"
+ " <movie path=\"" + simpleName + ".swf\" />\n"
+ " <movie fps=\"30\" />\n"
+ " <movie width=\"" + doubleToString(swf.displayRect.getWidth() / SWF.unitDivisor) + "\" />\n"
+ " <movie height=\"" + doubleToString(swf.displayRect.getHeight() / SWF.unitDivisor) + "\" />\n"
+ " <movie version=\"" + swf.version + "\" />\n"
+ " <movie minorVersion=\"0\" />\n"
+ " <movie platform=\"Flash Player\" />\n"
+ " <movie background=\"" + (bgColorTag == null ? "#FFFFFF" : bgColorTag.backgroundColor.toHexRGB()) + "\" />\n"
+ " </output>\n"
+ " <!-- Other classes to be compiled into your SWF -->\n"
+ " <classpaths>\n"
+ " <class path=\"" + srcPath + "\" />\n"
+ " </classpaths>\n"
+ " <!-- Build options -->\n"
+ " <build>\n"
+ " <option accessible=\"False\" />\n"
+ " <option allowSourcePathOverlap=\"False\" />\n"
+ " <option benchmark=\"False\" />\n"
+ " <option es=\"False\" />\n"
+ " <option loadConfig=\"\" />\n"
+ " <option optimize=\"True\" />\n"
+ " <option showActionScriptWarnings=\"True\" />\n"
+ " <option showBindingWarnings=\"True\" />\n"
+ " <option showDeprecationWarnings=\"True\" />\n"
+ " <option showUnusedTypeSelectorWarnings=\"True\" />\n"
+ " <option strict=\"True\" />\n"
+ " <option useNetwork=\"True\" />\n"
+ " <option useResourceBundleMetadata=\"True\" />\n"
+ " <option warnings=\"True\" />\n"
+ " <option verboseStackTraces=\"False\" />\n"
+ " <option additional=\"\" />\n"
+ " <option customSDK=\"\" />\n"
+ " </build>\n"
+ " <!-- Class files to compile (other referenced classes will automatically be included) -->\n"
+ " <compileTargets>\n"
+ (documentClass == null
? " <!-- example: <compile path=\"classes\\Main.as\" /> -->\n"
: "<compile path=\"" + srcPath + "/" + documentClass.replace(".", "/") + ".as\" />\n")
+ " </compileTargets>\n"
+ " <!-- Paths to exclude from the Project Explorer tree -->\n"
+ " <hiddenPaths>\n"
+ " <!-- example: <hidden path=\"...\" /> -->\n"
+ " </hiddenPaths>\n"
+ " <!-- Executed before build -->\n"
+ " <preBuildCommand />\n"
+ " <!-- Executed after build -->\n"
+ " <postBuildCommand alwaysRun=\"False\" />\n"
+ " <!-- Other project options -->\n"
+ " <options>\n"
+ " <option showHiddenPaths=\"False\" />\n"
+ " <option testMovie=\"Default\" />\n"
+ " </options>\n"
+ "</project>";
try (FileOutputStream fos = new FileOutputStream(outFile)) {
fos.write(Utf8Helper.getBytes(project));
}
boolean parallel = Configuration.parallelSpeedUp.get();
ScriptExportSettings scriptExportSettings = new ScriptExportSettings(ScriptExportMode.AS, false, false, true, false, false);
swf.exportActionScript(handler, outFile.toPath().getParent().resolve(srcPath).toFile().getAbsolutePath(), scriptExportSettings, parallel, eventListener);
}
}

View File

@@ -305,14 +305,17 @@ public class XFLXmlWriter implements XMLStreamWriter {
@Override
public void writeStartDocument() throws XMLStreamException {
writeStartDocument("utf-8", "1.0");
}
@Override
public void writeStartDocument(String version) throws XMLStreamException {
writeStartDocument(version, "utf-8");
}
@Override
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
append("<?xml version=\"" + escapeAttribute(version) + "\" encoding=\"" + escapeAttribute(encoding) + "\"?>");
}
public void writeCharactersRaw(String text) throws XMLStreamException {