diff --git a/src/com/jpexs/decompiler/flash/console/NewCommandLine.java b/src/com/jpexs/decompiler/flash/console/NewCommandLine.java index e70a4b6b1..37a68603a 100644 --- a/src/com/jpexs/decompiler/flash/console/NewCommandLine.java +++ b/src/com/jpexs/decompiler/flash/console/NewCommandLine.java @@ -31,6 +31,7 @@ public class NewCommandLine { args = new String[] {"--cli", "help", "export"}; //args = new String[] {"--help"}; + //args = new String[] {"--cli", "export", "script:as,image:png", "C:/out/", "C:/in/myfile.swf"}; int exitCode = new CommandLine(new Main()).execute(args); diff --git a/src/com/jpexs/decompiler/flash/console/commands/Export.java b/src/com/jpexs/decompiler/flash/console/commands/Export.java index 3d9e108d8..4140b1c95 100644 --- a/src/com/jpexs/decompiler/flash/console/commands/Export.java +++ b/src/com/jpexs/decompiler/flash/console/commands/Export.java @@ -15,10 +15,21 @@ * along with this program. If not, see . */ package com.jpexs.decompiler.flash.console.commands; +import com.jpexs.decompiler.flash.console.commands.types.ConfigConverter; +import com.jpexs.decompiler.flash.console.commands.types.ExportObject; +import com.jpexs.decompiler.flash.console.commands.types.ExportObjectFormat; +import com.jpexs.decompiler.flash.console.commands.types.ExportObjectFormatConverter; +import com.jpexs.decompiler.flash.console.commands.types.Selection; +import com.jpexs.decompiler.flash.console.commands.types.SelectionConverter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; +import picocli.CommandLine.ParentCommand; /** * @@ -27,84 +38,119 @@ import picocli.CommandLine.Parameters; @Command(name = "export", header = "Export sources to directory" ) -public class Export { +public class Export implements Runnable { + @ParentCommand + private Main parent; + + @Option(names = "--frame", + paramLabel = "", + converter = SelectionConverter.class, + description = { + "Selected frame(s) to export.", + "Sample values: 1-5 or 2,4 or 2-5,7,9-" + } + ) + private Selection frames = new Selection(); + + @Option(names = "--character-id", + paramLabel = "", + converter = SelectionConverter.class, + description = { + "Selected character id(s) to export.", + "Sample values: 27 or 2-5 or 12,24 or 2-5,10,9-" + } + ) + private Selection characterIds = new Selection(); + + @Option(names = "--class", + paramLabel = "", + split = ",", + description = { + "Selected scripts to export by classname (ActionScript 3 ONLY).", + "Sample values:", + "com.example.MyClass", + "com.example.+ (all classes in package \"com.example\")", + "com.++,net.company.MyClass (all classes in package \"com\" and all subpackages, class net.company.MyClass)", + }) + private List classes = new ArrayList<>(); + + @Option(names = "--embed", + description = { + "Enables exporting embedded assets via [Embed tag].", + "For script:as exports." + } + ) + private boolean useEmbed = false; + + + @Parameters(index = "0", split = ",", - paramLabel = "", - description = {"Types to export:", - "script - Scripts (Default format: ActionScript source)", - "image - Images (Default format: PNG/JPEG)", - "shape - Shapes (Default format: SVG)", - "morphshape - MorphShapes (Default format: SVG)", - "movie - Movies (Default format: FLV without sound)", - "font - Fonts (Default format: TTF)", - "font4 - DefineFont4 (Default format: CFF)", - "frame - Frames (Default format: PNG)", - "sprite - Sprites (Default format: PNG)", - "button - Buttons (Default format: PNG)", - "sound - Sounds (Default format: MP3/WAV/FLV only sound)", - "binaryData - Binary data (Default format: Raw data)", - "symbolClass - Symbol-Class mapping (Default format: CSV)", - "text - Texts (Default format: Plain text)", - "all - Every resource (but not FLA and XFL)", - "fla - Everything to FLA compressed format", - "xfl - Everything to uncompressed FLA format (XFL)"} - ) - private String[] types; - - @Option(names = "--format", split = ",", paramLabel = "", description = { - "Sets output format for export:", - "script:as - ActionScript source", - "script:pcode - ActionScript P-code", - "script:pcodehex - ActionScript P-code with hex", - "script:hex - ActionScript Hex only", - "shape:svg - SVG format for Shapes", - "shape:png - PNG format for Shapes", - "shape:canvas - HTML5 Canvas format for Shapes", - "shape:bmp - BMP format for Shapes", - "morphshape:svg - SVG format for MorphShapes", - "morphshape:canvas - HTML5 Canvas format for MorphShapes", - "frame:png - PNG format for Frames", - "frame:gif - GIF format for Frames", - "frame:avi - AVI format for Frames", - "frame:svg - SVG format for Frames", - "frame:canvas - HTML5 Canvas format for Frames", - "frame:pdf - PDF format for Frames", - "frame:bmp - BMP format for Frames", - "sprite:png - PNG format for Sprites", - "sprite:gif - GIF format for Sprites", - "sprite:avi - AVI format for Sprites", - "sprite:svg - SVG format for Sprites", - "sprite:canvas - HTML5 Canvas format for Sprites", - "sprite:pdf - PDF format for Sprites", - "sprite:bmp - BMP format for Sprites", - "button:png - PNG format for Buttons", - "button:svg - SVG format for Buttons", - "button:bmp - BMP format for Buttons", - "image:png_gif_jpeg - PNG/GIF/JPEG format for Images", - "image:png - PNG format for Images", - "image:jpeg - JPEG format for Images", - "image:bmp - BMP format for Images", - "image:png_gif_jpeg_alpha - PNG/GIF/JPEG+ALPHA format for Images", - "text:plain - Plain text format for Texts", - "text:formatted - Formatted text format for Texts", - "text:svg - SVG format for Texts", - "sound:mp3_wav_flv - MP3/WAV/FLV format for Sounds", - "sound:mp3_wav - MP3/WAV format for Sounds", - "sound:wav - WAV format for Sounds", - "sound:flv - FLV format for Sounds", - "font:ttf - TTF format for Fonts", - "font:woff - WOFF format for Fonts", - "font4:cff - CFF format for DefineFont4", - "fla: or xfl: - Specify FLA format version", - " - values for : cs5,cs5.5,cs6,cc", - }) - private String[] formats; + converter = ExportObjectFormatConverter.class, + paramLabel = "", + description = {"What objects to export. Available formats:", + "script:as (default)", + "script:pcode", + "script:pcodehex", + "script:hex", + "shape:svg (default)", + "shape:png", + "shape:canvas", + "shape:bmp", + "morphshape:svg (default)", + "morphshape:canvas", + "frame:png (default)", + "frame:gif", + "frame:avi", + "frame:svg", + "frame:canvas", + "frame:pdf", + "frame:bmp", + "sprite:png (default)", + "sprite:gif", + "sprite:avi", + "sprite:svg", + "sprite:canvas", + "sprite:pdf", + "sprite:bmp", + "button:png (default)", + "button:svg", + "button:bmp", + "image:png_gif_jpeg (default)", + "image:png", + "image:jpeg", + "image:bmp", + "image:png_gif_jpeg_alpha", + "text:plain (default)", + "text:formatted", + "text:svg", + "sound:mp3_wav_flv (default)", + "sound:mp3_wav", + "sound:wav", + "sound:flv", + "font:ttf (default)", + "font:woff", + "font4:cff (default)", + "fla:cs5", + "fla:cs5.5", + "fla:cs6", + "fla:cc", + "xfl:cs5", + "xfl:cs5.5", + "xfl:cs6", + "xfl:cc", + }) + private List objects; @Parameters(index = "1", description = "Target directory") private String outDirectory; @Parameters(index = "2", description = "Input file or directory") private String inFileOrDirectory; + + @Override + public void run() { + System.out.println("exporting...ok"); + } } diff --git a/src/com/jpexs/decompiler/flash/console/commands/Main.java b/src/com/jpexs/decompiler/flash/console/commands/Main.java index 11c1217aa..56d71b684 100644 --- a/src/com/jpexs/decompiler/flash/console/commands/Main.java +++ b/src/com/jpexs/decompiler/flash/console/commands/Main.java @@ -16,13 +16,17 @@ */ package com.jpexs.decompiler.flash.console.commands; import com.jpexs.decompiler.flash.ApplicationInfo; +import com.jpexs.decompiler.flash.console.commands.types.ConfigConverter; import java.io.File; +import java.util.HashMap; +import java.util.Map; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.IVersionProvider; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; import picocli.CommandLine.HelpCommand; +import picocli.CommandLine.ScopeType; /** * @@ -40,6 +44,17 @@ import picocli.CommandLine.HelpCommand; ) public class Main implements Runnable { + @Option(names = "--config", + paramLabel = "=[,=...]", + converter = ConfigConverter.class, + description = { + "Sets configuration values for this session.", + "Use command 'config' to list available configuration settings. " + }, + scope = ScopeType.INHERIT + ) + private Map configs = new HashMap<>(); + @Parameters(paramLabel = "FILE", description = "one or more files to open in GUI") private File[] files; diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/ConfigConverter.java b/src/com/jpexs/decompiler/flash/console/commands/types/ConfigConverter.java new file mode 100644 index 000000000..9eb8dfa59 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/ConfigConverter.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +import com.jpexs.decompiler.flash.configuration.Configuration; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import picocli.CommandLine; + +/** + * + * @author JPEXS + */ +public class ConfigConverter implements CommandLine.ITypeConverter>{ + + @Override + public Map convert(String value) throws Exception { + String[] cfgs; + if (value.contains(",")) { + cfgs = value.split(","); + } else { + cfgs = new String[]{value}; + } + + Map ret = new HashMap<>(); + + for (String c : cfgs) { + String[] cp = c.split("="); + if (cp.length == 1) { + cp = new String[]{cp[0], "1"}; + } + ret.put(cp[0], cp[1]); + } + return ret; + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/ExportObject.java b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObject.java new file mode 100644 index 000000000..8a8dd9719 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObject.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +import com.jpexs.decompiler.flash.exporters.modes.BinaryDataExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ButtonExportMode; +import com.jpexs.decompiler.flash.exporters.modes.Font4ExportMode; +import com.jpexs.decompiler.flash.exporters.modes.FontExportMode; +import com.jpexs.decompiler.flash.exporters.modes.FrameExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ImageExportMode; +import com.jpexs.decompiler.flash.exporters.modes.MorphShapeExportMode; +import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SpriteExportMode; +import com.jpexs.decompiler.flash.exporters.modes.SymbolClassExportMode; +import com.jpexs.decompiler.flash.exporters.modes.TextExportMode; +import com.jpexs.decompiler.flash.types.sound.SoundExportFormat; +import com.jpexs.decompiler.flash.xfl.FLAVersion; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author JPEXS + */ +public enum ExportObject { + SCRIPT(ScriptExportMode.class), + IMAGE(ImageExportMode.class), + SHAPE(ShapeExportMode.class), + MORPHSHAPE(MorphShapeExportMode.class), + MOVIE(MovieExportMode.class), + FONT(FontExportMode.class), + FONT4(Font4ExportMode.class), + FRAME(FrameExportMode.class), + SPRITE(SpriteExportMode.class), + BUTTON(ButtonExportMode.class), + SOUND(SoundExportMode.class), + BINARYDATA(BinaryDataExportMode.class), + SYMBOLCLASS(SymbolClassExportMode.class), + TEXT(TextExportMode.class), + ALL(null), + FLA(FLAVersion.class), + XFL(FLAVersion.class); + + private Class formatsEnum; + + ExportObject(Class formatsEnum) { + this.formatsEnum = formatsEnum; + } + + public List getAllowedFormats() { + if (formatsEnum == null) { + return new ArrayList<>(); + } + return Arrays.asList(formatsEnum.getEnumConstants()); + } + public List getAllowedFormatsAsStr() { + if (formatsEnum == null) { + return new ArrayList<>(); + } + List ret = new ArrayList<>(); + for (Object o : formatsEnum.getEnumConstants()) { + ret.add(o.toString().toLowerCase()); + } + return ret; + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormat.java b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormat.java new file mode 100644 index 000000000..08bc31531 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormat.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +/** + * + * @author JPEXS + */ +public class ExportObjectFormat { + public ExportObject object; + public String format; + + public ExportObjectFormat(ExportObject type, String format) { + this.object = type; + this.format = format; + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormatConverter.java b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormatConverter.java new file mode 100644 index 000000000..e59e147dd --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/ExportObjectFormatConverter.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import picocli.CommandLine; + + +/** + * + * @author JPEXS + */ +public class ExportObjectFormatConverter implements CommandLine.ITypeConverter{ + + @Override + public ExportObjectFormat convert(String value) throws Exception { + Pattern pat = Pattern.compile("^(?[a-z0-9]+)(:(?[a-z0-9]+))?$"); + Matcher mat = pat.matcher(value); + if (!mat.matches()) { + throw new CommandLine.TypeConversionException("Invalid value: must be 'type:format' or 'type' but was '" + value + "'"); + } + String typeStr = mat.group("type"); + String formatStr = mat.group("format"); + ExportObject type = null; + try { + type = ExportObject.valueOf(typeStr.toUpperCase()); + } catch (IllegalArgumentException ex) { + List ts = new ArrayList<>(); + for (ExportObject t : ExportObject.values()) { + ts.add("'" + ts.toString().toLowerCase() + "'"); + } + throw new CommandLine.TypeConversionException("Invalid type: must be one of " + String.join(", ", ts) + " but was '" + typeStr+ "'"); + } + List allowedFormats = type.getAllowedFormatsAsStr(); + if (!allowedFormats.isEmpty() && formatStr != null) { + if (!allowedFormats.contains(formatStr)) { + throw new CommandLine.TypeConversionException("Invalid format: for type '" + type + "' must format be one of '" + String.join("', '", allowedFormats) + "' but was " + formatStr); + } + } + + return new ExportObjectFormat(type, formatStr); + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/Range.java b/src/com/jpexs/decompiler/flash/console/commands/types/Range.java new file mode 100644 index 000000000..b562f4d59 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/Range.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +/** + * + * @author JPEXS + */ +public class Range { + + public Integer min; + + public Integer max; + + public Range(Integer min, Integer max) { + this.min = min; + this.max = max; + } + + public boolean contains(int index) { + int minimum = min == null ? Integer.MIN_VALUE : min; + int maximum = max == null ? Integer.MAX_VALUE : max; + + return index >= minimum && index <= maximum; + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/Selection.java b/src/com/jpexs/decompiler/flash/console/commands/types/Selection.java new file mode 100644 index 000000000..602bd0a45 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/Selection.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class Selection { + + public List ranges; + + public Selection() { + this.ranges = new ArrayList<>(); + this.ranges.add(new Range(null, null)); + } + + public Selection(List ranges) { + this.ranges = ranges; + } + + public boolean contains(int index) { + for (Range r : ranges) { + if (r.contains(index)) { + return true; + } + } + return false; + } +} diff --git a/src/com/jpexs/decompiler/flash/console/commands/types/SelectionConverter.java b/src/com/jpexs/decompiler/flash/console/commands/types/SelectionConverter.java new file mode 100644 index 000000000..c9ddb2657 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/commands/types/SelectionConverter.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2024 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.console.commands.types; + +import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; +import static com.jpexs.decompiler.flash.console.CommandLineArgumentParser.badArguments; +import java.util.ArrayList; +import java.util.List; +import picocli.CommandLine; + +/** + * + * @author JPEXS + */ +public class SelectionConverter implements CommandLine.ITypeConverter{ + + @Override + public Selection convert(String value) throws Exception { + List ret = new ArrayList<>(); + + String[] ranges; + if (value.contains(",")) { + ranges = value.split(","); + } else { + ranges = new String[]{value}; + } + for (String r : ranges) { + Integer min = null; + Integer max = null; + if (r.contains("-")) { + String[] ps = r.split("\\-"); + if (ps.length != 2) { + throw new CommandLine.TypeConversionException("Invalid range: " + r); + } + try { + if (!"".equals(ps[0])) { + min = Integer.parseInt(ps[0]); + } + if (!"".equals(ps[1])) { + max = Integer.parseInt(ps[1]); + } + } catch (NumberFormatException nfe) { + throw new CommandLine.TypeConversionException("Invalid range: " + r); + } + } else { + try { + min = Integer.parseInt(r); + max = min; + } catch (NumberFormatException nfe) { + throw new CommandLine.TypeConversionException("Invalid range: " + r); + } + } + ret.add(new Range(min, max)); + } + return new Selection(ret); + } +} diff --git a/src/picocli/CommandLine.java b/src/picocli/CommandLine.java index 7a7babe8a..9f4df91a7 100644 --- a/src/picocli/CommandLine.java +++ b/src/picocli/CommandLine.java @@ -11089,6 +11089,7 @@ public class CommandLine { final String name; int position; + @SuppressWarnings("deprecation") //JPEXS public MethodParam(Method method, int paramIndex) { this.method = method; this.paramIndex = paramIndex; @@ -15871,7 +15872,9 @@ public class CommandLine { } else { text = text.concat("[").concat(name).concat(param).concat("]"); if (option.isMultiValue()) { // add ellipsis to show option is repeatable - text = text.concat("..."); + if (option.splitRegex().isEmpty() && option.converters().length == 0) { //JPEXS + text = text.concat("..."); + } } } }