Added FlashDevelop project export - option to export AIR project (select correct type in the file save dialog)

This commit is contained in:
Jindra Petřík
2024-08-27 09:43:40 +02:00
parent 58724dced5
commit 58e61907f2
12 changed files with 519 additions and 79 deletions
@@ -25,7 +25,9 @@ import java.util.Map;
*/
public class FlashPlayerVersion {
private static final Map<String, Integer> flashPlayerToSwfVersion = new HashMap<>();
private static final Map<String, Integer> airToSwfVersion = new HashMap<>();
private static final Map<Integer, String> swfVersionToFlashPlayer = new HashMap<>();
private static final Map<Integer, String> swfVersionToAir = new HashMap<>();
static {
flashPlayerToSwfVersion.put("9.0", 9); //9.0.115.0
flashPlayerToSwfVersion.put("10.0", 10);
@@ -66,6 +68,47 @@ public class FlashPlayerVersion {
flashPlayerToSwfVersion.put("33.0", 44);
flashPlayerToSwfVersion.put("33.1", 44);
flashPlayerToSwfVersion.put("50.0", 50);
flashPlayerToSwfVersion.put("51.0", 51);
airToSwfVersion.put("1.5", 10);
airToSwfVersion.put("2.0", 10);
airToSwfVersion.put("2.6", 11);
airToSwfVersion.put("2.7", 12);
airToSwfVersion.put("3.0", 13);
airToSwfVersion.put("3.1", 14);
airToSwfVersion.put("3.2", 15);
airToSwfVersion.put("3.3", 16);
airToSwfVersion.put("3.4", 17);
airToSwfVersion.put("3.5", 18);
airToSwfVersion.put("3.6", 19);
airToSwfVersion.put("3.7", 20);
airToSwfVersion.put("3.8", 21);
airToSwfVersion.put("3.9", 22);
airToSwfVersion.put("4.0", 23);
airToSwfVersion.put("13.0", 24);
airToSwfVersion.put("14.0", 25);
airToSwfVersion.put("15.0", 26);
airToSwfVersion.put("16.0", 27);
airToSwfVersion.put("17.0", 28);
airToSwfVersion.put("18.0", 29);
airToSwfVersion.put("19.0", 30);
airToSwfVersion.put("20.0", 31);
airToSwfVersion.put("21.0", 32);
airToSwfVersion.put("22.0", 33);
airToSwfVersion.put("23.0", 34);
airToSwfVersion.put("24.0", 35);
airToSwfVersion.put("25.0", 36);
airToSwfVersion.put("26.0", 37);
airToSwfVersion.put("27.0", 38);
airToSwfVersion.put("28.0", 39);
airToSwfVersion.put("29.0", 40);
airToSwfVersion.put("30.0", 41);
airToSwfVersion.put("31.0", 42);
airToSwfVersion.put("32.0", 43);
airToSwfVersion.put("33.0", 44);
airToSwfVersion.put("33.1", 44);
airToSwfVersion.put("50.0", 50);
airToSwfVersion.put("51.0", 51);
for (String flashPlayer : flashPlayerToSwfVersion.keySet()) {
int swfVersion = flashPlayerToSwfVersion.get(flashPlayer);
@@ -73,6 +116,13 @@ public class FlashPlayerVersion {
swfVersionToFlashPlayer.put(swfVersion, flashPlayer);
}
}
for (String air : airToSwfVersion.keySet()) {
int swfVersion = airToSwfVersion.get(air);
if (!swfVersionToAir.containsKey(swfVersion)) {
swfVersionToAir.put(swfVersion, air);
}
}
}
/**
@@ -81,8 +131,8 @@ public class FlashPlayerVersion {
* @return Flash player version or null if not found
*/
public static String getFlashPlayerBySwfVersion(int swfVersion) {
if (swfVersion > 50) {
return "50.0"; //??
if (swfVersion > 51) {
return "51.0"; //??
}
return swfVersionToFlashPlayer.get(swfVersion);
}
@@ -98,4 +148,29 @@ public class FlashPlayerVersion {
}
return flashPlayerToSwfVersion.get(flashPlayerVersion);
}
/**
* Gets Air version by SWF version
* @param swfVersion SWF version
* @return Air version or null if not found
*/
public static String getAirBySwfVersion(int swfVersion) {
if (swfVersion > 51) {
return "51.0"; //??
}
return swfVersionToFlashPlayer.get(swfVersion);
}
/**
* Gets SWF version by Air version.
* @param air Air version
* @return SWF version or -1 if not found
*/
public static int getSwfVersionByAir(String air) {
if (!airToSwfVersion.containsKey(air)) {
return -1;
}
return airToSwfVersion.get(air);
}
}
@@ -31,10 +31,13 @@ import com.jpexs.decompiler.flash.tags.StartSoundTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
/**
* Exports SWF to FlashDevelop project.
@@ -49,19 +52,17 @@ public class SwfFlashDevelopExporter {
}
//Cannot export if it has something on main timeline
for (Tag t : swf.getTags()) {
if (
(t instanceof PlaceObjectTypeTag)
if ((t instanceof PlaceObjectTypeTag)
|| (t instanceof SoundStreamBlockTag)
|| (t instanceof VideoFrameTag)
|| (t instanceof StartSoundTag)
|| (t instanceof StartSound2Tag)
) {
|| (t instanceof StartSound2Tag)) {
return false;
}
}
return true;
}
private static String doubleToString(double d) {
String ds = "" + d;
if (ds.endsWith(".0")) {
@@ -72,28 +73,32 @@ public class SwfFlashDevelopExporter {
/**
* Exports SWF to FlashDevelop project.
*
* @param swf SWF to export
* @param outFile Output file
* @param air
* @param handler Handler for abort, retry, ignore
* @throws IOException On I/O error
*/
public void exportFlashDevelopProject(SWF swf, File outFile, AbortRetryIgnoreHandler handler) throws IOException {
exportFlashDevelopProject(swf, outFile, handler, null);
public void exportFlashDevelopProject(SWF swf, File outFile, boolean air, AbortRetryIgnoreHandler handler) throws IOException {
exportFlashDevelopProject(swf, outFile, air, handler, null);
}
/**
* Exports SWF to FlashDevelop project.
*
* @param swf SWF to export
* @param outFile Output file
* @param air AIR
* @param handler Handler for abort, retry, ignore
* @param eventListener Event listener
* @throws IOException On I/O error
*/
public void exportFlashDevelopProject(SWF swf, File outFile, AbortRetryIgnoreHandler handler, EventListener eventListener) throws IOException {
public void exportFlashDevelopProject(SWF swf, File outFile, boolean air, AbortRetryIgnoreHandler handler, EventListener eventListener) throws IOException {
if (!swf.isAS3()) {
throw new IllegalArgumentException("SWF must be AS3");
}
if (!canExportSwf(swf)) {
throw new IllegalArgumentException("SWF must not contain main timeline");
}
@@ -103,79 +108,240 @@ public class SwfFlashDevelopExporter {
simpleName = simpleName.substring(0, simpleName.lastIndexOf("."));
}
String simpleNameNoSpaces = simpleName.replace(" ", "");
SetBackgroundColorTag bgColorTag = swf.getBackgroundColor();
String documentClass = swf.getDocumentClass();
String srcPath = "src";
String project;
String flashPlayerVersion = FlashPlayerVersion.getFlashPlayerBySwfVersion(swf.version);
String[] flashPlayerVersions = flashPlayerVersion.split("\\.");
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=\"" + doubleToString(swf.frameRate) + "\" />\n"
+ " <movie width=\"" + doubleToString(swf.displayRect.getWidth() / SWF.unitDivisor) + "\" />\n"
+ " <movie height=\"" + doubleToString(swf.displayRect.getHeight() / SWF.unitDivisor) + "\" />\n"
+ " <movie version=\"" + flashPlayerVersions[0] + "\" />\n"
+ " <movie minorVersion=\"" + flashPlayerVersions[1] + "\" />\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>";
String airVersion = FlashPlayerVersion.getAirBySwfVersion(swf.version);
String[] airVersions = airVersion.split("\\.");
if (air) {
project = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<project version=\"2\">\n"
+ " <!-- Output SWF options -->\n"
+ " <output>\n"
+ " <movie outputType=\"Application\" />\n"
+ " <movie input=\"\" />\n"
+ " <movie path=\"bin\\" + simpleNameNoSpaces + ".swf\" />\n"
+ " <movie fps=\"" + doubleToString(swf.frameRate) + "\" />\n"
+ " <movie width=\"" + doubleToString(swf.displayRect.getWidth() / SWF.unitDivisor) + "\" />\n"
+ " <movie height=\"" + doubleToString(swf.displayRect.getHeight() / SWF.unitDivisor) + "\" />\n"
+ " <movie version=\"" + airVersions[0] + "\" />\n"
+ " <movie minorVersion=\"" + airVersions[1] + "\" />\n"
+ " <movie platform=\"AIR\" />\n"
+ " <movie background=\"" + (bgColorTag == null ? "#FFFFFF" : bgColorTag.backgroundColor.toHexRGB()) + "\" />\n"
+ " <movie preferredSDK=\"\" />\n"
+ " </output>\n"
+ " <!-- Other classes to be compiled into your SWF -->\n"
+ " <classpaths>\n"
+ " <class path=\"src\" />\n"
+ " </classpaths>\n"
+ " <!-- Build options -->\n"
+ " <build>\n"
+ " <option accessible=\"False\" />\n"
+ " <option advancedTelemetry=\"False\" />\n"
+ " <option allowSourcePathOverlap=\"False\" />\n"
+ " <option benchmark=\"False\" />\n"
+ " <option es=\"False\" />\n"
+ " <option inline=\"False\" />\n"
+ " <option locale=\"\" />\n"
+ " <option loadConfig=\"\" />\n"
+ " <option optimize=\"True\" />\n"
+ " <option omitTraces=\"True\" />\n"
+ " <option showActionScriptWarnings=\"True\" />\n"
+ " <option showBindingWarnings=\"True\" />\n"
+ " <option showInvalidCSS=\"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 linkReport=\"\" />\n"
+ " <option loadExterns=\"\" />\n"
+ " <option staticLinkRSL=\"True\" />\n"
+ " <option additional=\"\" />\n"
+ " <option compilerConstants=\"\" />\n"
+ " <option minorVersion=\"\" />\n"
+ " </build>\n"
+ " <!-- SWC Include Libraries -->\n"
+ " <includeLibraries>\n"
+ " <!-- example: <element path=\"...\" /> -->\n"
+ " </includeLibraries>\n"
+ " <!-- SWC Libraries -->\n"
+ " <libraryPaths>\n"
+ " <!-- example: <element path=\"...\" /> -->\n"
+ " </libraryPaths>\n"
+ " <!-- External Libraries -->\n"
+ " <externalLibraryPaths>\n"
+ " <!-- example: <element path=\"...\" /> -->\n"
+ " </externalLibraryPaths>\n"
+ " <!-- Runtime Shared Libraries -->\n"
+ " <rslPaths>\n"
+ " <!-- example: <element path=\"...\" /> -->\n"
+ " </rslPaths>\n"
+ " <!-- Intrinsic Libraries -->\n"
+ " <intrinsics>\n"
+ " <!-- example: <element path=\"...\" /> -->\n"
+ " </intrinsics>\n"
+ " <!-- Assets to embed into the output SWF -->\n"
+ " <library>\n"
+ " <!-- example: <asset path=\"...\" id=\"...\" update=\"...\" glyphs=\"...\" mode=\"...\" place=\"...\" sharepoint=\"...\" /> -->\n"
+ " </library>\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"
+ " <hidden path=\"obj\" />\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=\"Custom\" />\n"
+ " <option testMovieCommand=\"bat\\RunApp.bat\" />\n"
+ " </options>\n"
+ " <!-- Plugin storage -->\n"
+ " <storage />\n"
+ "</project>";
} else {
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=\"" + doubleToString(swf.frameRate) + "\" />\n"
+ " <movie width=\"" + doubleToString(swf.displayRect.getWidth() / SWF.unitDivisor) + "\" />\n"
+ " <movie height=\"" + doubleToString(swf.displayRect.getHeight() / SWF.unitDivisor) + "\" />\n"
+ " <movie version=\"" + flashPlayerVersions[0] + "\" />\n"
+ " <movie minorVersion=\"" + flashPlayerVersions[1] + "\" />\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));
}
if (air) {
String applicationXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?> \n"
+ "<application xmlns=\"http://ns.adobe.com/air/application/" + airVersion + "\">\n"
+ " \n"
+ " <id>" + simpleNameNoSpaces + "</id> \n"
+ " <versionNumber>1.0</versionNumber> \n"
+ " <filename>" + simpleNameNoSpaces + "</filename> \n"
+ " \n"
+ " <name>" + simpleName + "</name> \n"
+ " <description></description> \n"
+ " <copyright></copyright> \n"
+ " \n"
+ " <initialWindow> \n"
+ " <title>" + simpleName + "</title> \n"
+ " <content>" + simpleNameNoSpaces + ".swf</content> \n"
+ " <systemChrome>standard</systemChrome> \n"
+ " <transparent>false</transparent> \n"
+ " <visible>true</visible> \n"
+ " <minimizable>true</minimizable> \n"
+ " <maximizable>true</maximizable> \n"
+ " <resizable>true</resizable> \n"
+ " </initialWindow> \n"
+ " \n"
+ " <!-- \n"
+ " More options:\n"
+ " http://livedocs.adobe.com/flex/3/html/File_formats_1.html#1043413\n"
+ " -->\n"
+ "</application>";
try (FileOutputStream fos = new FileOutputStream(outFile.toPath().getParent().resolve("application.xml").toFile())) {
fos.write(Utf8Helper.getBytes(applicationXml));
}
Path batDirPath = outFile.toPath().getParent().resolve("bat");
batDirPath.toFile().mkdir();
String[] batFiles = new String[]{
"CreateCertificate.bat",
"PackageApp.bat",
"Packager.bat",
"RunApp.bat",
"SetupApp.bat",
"SetupSDK.bat"
};
for (String batFile : batFiles) {
InputStream is = SwfFlashDevelopExporter.class.getResourceAsStream("/com/jpexs/helpers/resource/fd_air/bat/" + batFile);
byte[] data = Helper.readStream(is);
String strData = Utf8Helper.decode(data);
strData = strData.replace("<app_fullname>", simpleName);
strData = strData.replace("<app_nospaces>", simpleNameNoSpaces);
try (FileOutputStream fos = new FileOutputStream(batDirPath.resolve(batFile).toFile())) {
fos.write(Utf8Helper.getBytes(strData));
}
}
}
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);